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