1 #ifndef __EVMDD_PROP_H_
2 #define __EVMDD_PROP_H_
3 // Propagator for weighted (edge-valued) MDDs.
4 #include <utility>
5 
6 #include <chuffed/core/propagator.h>
7 #include <chuffed/vars/int-view.h>
8 #include <chuffed/support/misc.h>
9 #include <chuffed/support/sparse_set.h>
10 #include <chuffed/support/BVec.h>
11 #include <climits>
12 
13 #include <chuffed/mdd/opts.h>
14 #include <chuffed/mdd/weighted_dfa.h>
15 
16 typedef int EdgeID;
17 
18 typedef struct {
19   // Permanent properties
20   int val;
21   int weight;
22   int begin;
23   int end;
24 
25   // Transient info
26   unsigned int kill_flags;
27   unsigned int watch_flags;
28 } Edge;
29 
30 // A disjunction of edges.
31 typedef struct {
32   int sz;
33   int curr_sz;
34   EdgeID edges[1];
35 } Disj;
36 
37 // Separation of the watch from the clause.
38 // Seems to add complexity without any real benefit.
39 typedef Disj* DisjRef;
40 
41 typedef struct {
42   int var;
43   int val;
44   DisjRef edges;
45 
46   // Transient info
47   unsigned int status;
48 //  unsigned int val_lim;
49 } Val;
50 
51 typedef struct {
52   // Basic properties
53   int var;
54   DisjRef in;
55   DisjRef out;
56 
57   // Trailed state
58   int in_pathC;
59   int out_pathC;
60 
61   // Temporary state
62   int in_value;
63   int out_value;
64   int status;
65 } Node;
66 
67 class WMDDProp : public Propagator {
68   // ====================================
69   // Structures for explanation rewinding
70   // ====================================
71   /*
72   struct Pinfo {
73     BTPos btpos;                      // backtrack point
74     // which thing is changed (some leaf, or cost)
75     // Tag format: [----leaf---|0] or [----ub----|1]
76     int tag;
77     // May need to add an additional field here for the bound.
78     Pinfo(BTPos p, int t) : btpos(p), tag(t) {}
79   };
80   bool trailed_pinfo_sz;
81   vec<Pinfo> p_info;
82   */
83 
84 
85   // ====================================
86   // Useful enums & structures
87   // ====================================
88   enum ValFlags { VAL_UNSUPP = 1 };
89   enum KillCause { K_BELOW, K_ABOVE, K_VAL, K_COST };
90 
91   class VarInfo {
92   public:
VarInfo(int _min,int _offset,int _dom)93     VarInfo(int _min, int _offset, int _dom)
94       : min(_min), offset(_offset), dom(_dom)
95     { }
96     int min;
97     int offset;
98     int dom;
99   };
100 
101 public:
102   WMDDProp(vec< IntView<> >& _vs, IntView<> _c, vec<int>& _levels, vec<Edge>& _edges, const MDDOpts& opts);
103 
104   bool fullProp(void);
105   bool incProp(void);
106 
107   void incPropDown(vec<int>& clear_queue, int maxC, vec<int>& valQ);
108   void incPropUp(vec<int>& clear_queue, int maxC, vec<int>& valQ);
109 
numNodes(void)110   inline int numNodes(void) { return nodes.size(); }
111 
112   void debugStateTikz(unsigned int lim, bool debug = true);
113   void verify(void);
114 
115   // Wake up only parts relevant to this event
wakeup(int i,int c)116   void wakeup(int i, int c) {
117     if(i == boolvars.size())
118     {
119       // Cost has changed.
120       assert(c&EVENT_U);
121       cost_changed = true;
122       pushInQueue();
123     } else {
124       assert(boolvars[i].isFixed());
125       assert(!boolvars[i].getVal());
126       if( fixedvars.elem(i) )
127         return;
128       clear_queue.push(i);
129 //      vals[i].val_lim = fixedvars.size();
130       fixedvars.insert(i);
131       pushInQueue();
132     }
133   }
134 
edge_dead(int eid)135   inline bool edge_dead(int eid)
136   {
137     return dead_edges.elem(eid);
138   }
139 
edge_pathC(int eid)140   inline int edge_pathC(int eid)
141   {
142     Edge& e(edges[eid]);
143     return nodes[e.begin].in_pathC + e.weight + nodes[e.end].out_pathC;
144   }
145 
kill_edge(int eid,KillCause cause)146   inline void kill_edge(int eid, KillCause cause)
147   {
148     assert(!dead_edges.elem(eid));
149     edges[eid].kill_flags = cause;
150     dead_edges.insert(eid);
151   }
152 
153   // Propagate woken up parts
154   bool propagate();
155   Clause* explain(Lit p, int inf);
156   Clause* explainConflict(void);
157 
158   // Clear intermediate states
clearPropState()159   void clearPropState() {
160     clear_queue.clear();
161     cost_changed = false;
162     in_queue = false;
163   }
164 
165 protected:
166   // ===========================
167   // Rewinding methods
168   // ===========================
169   // Create a Reason for a lazily explained bounds change
createReason(int leaf)170   Reason createReason(int leaf) {
171     /*
172     if (!trailed_pinfo_sz) {
173       engine.trail.last().push(TrailElem(&p_info._size(), 4));
174       trailed_pinfo_sz = true;
175     }
176     p_info.push(Pinfo(engine.getBTPos(), leaf));
177     return Reason(prop_id, p_info.size()-1);
178     */
179     return Reason(prop_id, leaf);
180   }
181   /*
182   Reason createReason(BTPos pos, int leaf) {
183     if (!trailed_pinfo_sz) {
184       engine.trail.last().push(TrailElem(&p_info._size(), 4));
185       trailed_pinfo_sz = true;
186     }
187     p_info.push(Pinfo(pos, leaf));
188     return Reason(prop_id, p_info.size()-1);
189   }
190   */
191 
192   // ===========================
193   // Explanation support methods
194   // ===========================
195   // Compute the lowest smallest value of ub(c)
196   // that makes a given state satisfiable.
197   int compute_minC(int var, int val);
198   // Same as compute_minC, but using only vals with non-zero
199   // status.
200   int late_minC(int var, int val);
201 
202   // Compute the shortest distance n -> T.
203   int mark_frontier(int var, int val);
204 
205   // Given that mark_frontier has just been called, compute
206   // a minimal subset of the current assignment which maintains
207   // unsatisfiability.
208   void minimize_expln(int var, int val, int maxC);
209   void collect_lits(vec<Lit>& expln);
210 
211   // Incrementally explain a given inference.
212   Clause* incExplain(Lit p, int var, int val);
213   void incExplainUp(vec<int>& upQ, vec<Lit>& expln);
214   void incExplainDown(vec<int>& downQ, vec<Lit>& expln);
215 
216   // Shrink the constraint according
217   // to the current partial assignment.
218   void compact();
219 
220   // Debug printout of the propagator state.
221   void debugStateDot(void);
222   void checkIncProp(void);
223 
224   // Data
225   vec< IntView<> > intvars;
226   vec<VarInfo> varinfo;
227 
228   vec<BoolView> boolvars;
229 
230   IntView<> cost;
231 
232   vec<Val> vals;
233   vec<Node> nodes;
234 
235   // The base cost to & from each node.
236   vec<int> in_base;
237   vec<int> out_base;
238 
239   // FIXME: Not yet initialized
240   int root;
241   int T;
242 
243   vec<Edge> edges;
244   TBitVec dead_edges;
245 
246   TrailedSet fixedvars;
247   // Intermediate state
248   vec<int> clear_queue;
249   bool cost_changed;
250 
251   // Keeping track of which nodes have
252   // some path through x=v when doing
253   // explanation.
254   SparseSet<> expl_care;
255 
256   // Used for the incremental algorithm,
257   // to restore the propagator state to
258   // the correct point in time.
259   /* NOT USED AT PRESENT: We simply trail all path changes.
260   vec<int> history;
261   int hist_end;
262    */
263   MDDOpts opts;
264 };
265 
266 // Maybe should move this to a separate module.
267 WMDDProp* evgraph_to_wmdd(vec<IntVar*> vs, IntVar* cost, EVLayerGraph& g, EVLayerGraph::NodeID rootID, const MDDOpts& opts);
268 
269 #endif
270