summaryrefslogtreecommitdiff
path: root/impl/VariableAssignment.hpp
blob: f41dab338602a25ce96349808949238e0b3a894a (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#ifndef VARIABLE_ASSIGNMENT_HPP
#define VARIABLE_ASSIGNMENT_HPP

#include "Expression.hpp"
#include "IdMap.hpp"

template<typename Domain>
struct VariableAssignment {
  virtual ~VariableAssignment() { }
  virtual const Domain& operator[](const Variable<Domain>&) const = 0;
};

template<typename Domain>
struct StableVariableAssignment
: public VariableAssignment<Domain>, public IdMap<Variable<Domain>, Domain> {
  StableVariableAssignment(unsigned int length)
    : IdMap<Variable<Domain>,Domain>(length, -infinity<Domain>()) { }
  StableVariableAssignment(unsigned int length, const Domain& value)
    : IdMap<Variable<Domain>,Domain>(length, value) { }

  const Domain& operator[](const Variable<Domain>& var) const {
    return IdMap<Variable<Domain>,Domain>::operator[](var);
  }
  Domain& operator[](const Variable<Domain>& var) {
    return IdMap<Variable<Domain>,Domain>::operator[](var);
  }
};

#include "EquationSystem.hpp"

template<typename Domain>
struct DynamicMaxStrategy;

template<typename Domain>
struct DynamicVariableAssignment : public VariableAssignment<Domain> {
  DynamicVariableAssignment(
    const EquationSystem<Domain>& system,
    const DynamicMaxStrategy<Domain>& strat
  ) : _system(system),
      _strategy(strat),
      _values(system.variableCount(), infinity<Domain>()),
      _stable(system.variableCount()),
      _influence(system.variableCount(),
                 IdSet<Variable<Domain>>(system.variableCount()))
  { }

  const Domain& operator[](const Variable<Domain>& var) const {
    solve(var);
    return _values[var];
  }

  void invalidate(const Variable<Domain>& x) const {
    log::fixpoint << "invalidating " << x << std::endl;
    _stable.remove(x);
    _values[x] = infinity<Domain>();
  }

private:

  void solve(const Variable<Domain>& x) const {
      if (!_stable.contains(x)) {
        _stable.insert(x);
        
        Domain val = _system[x]->eval(DependencyAssignment(*this, x),
                                      _strategy);

        if (val != _values[x]) {
          log::fixpoint << "Updating value for " << x
                        << " to " << val << std::endl;

          auto oldInfluence = _influence[x];
          _influence[x].clear();
          _values[x] = val;

          _strategy.invalidate(x);
          
          _stable.filter(oldInfluence);
          
          for (auto it = oldInfluence.begin();
               it != oldInfluence.end();
               ++it) {
            solve(_system.variable(*it));
          }
        } else {
          log::fixpoint << x << " did not change" << std::endl;
        }
      } else {
        log::fixpoint << x << " is stable" << std::endl;
      }
    }

    struct DependencyAssignment : public VariableAssignment<Domain> {
      DependencyAssignment(const DynamicVariableAssignment& assignment, const Variable<Domain>& var)
        : _assignment(assignment), _var(var) { }
      const Domain& operator[](const Variable<Domain>& x) const {
        const Domain& result = _assignment[x];
        _assignment._influence[x].insert(_var);
        return result;
      }
    private:
      const DynamicVariableAssignment& _assignment;
      const Variable<Domain>& _var;
    };
  
  const EquationSystem<Domain>& _system;
  const DynamicMaxStrategy<Domain>& _strategy;
  mutable StableVariableAssignment<Domain> _values;
  mutable IdSet<Variable<Domain> > _stable;
  mutable IdMap<Variable<Domain>,IdSet<Variable<Domain> > > _influence;
};

#endif