static //Formula buildBDD(const Linear& c, int size, int lower_limit, int upper_limit, int material_left, Map<Pair<int,Int>,Formula>& memo, int max_cost) Formula buildBDD(const Linear& c, int size, Int sum, Int material_left, Map<Pair<int,Int>,Formula>& memo, int max_cost) { Int lower_limit = (c.lo == Int_MIN) ? Int_MIN : c.lo - sum; Int upper_limit = (c.hi == Int_MAX) ? Int_MAX : c.hi - sum; if (lower_limit <= 0 && upper_limit >= material_left) return _1_; else if (lower_limit > material_left || upper_limit < 0) return _0_; else if (FEnv::topSize() > max_cost) return _undef_; // (mycket elegant!) Pair<int,Int> key = Pair_new(size, lower_limit); Formula ret; if (!memo.peek(key, ret)){ assert(size != 0); size--; material_left -= c(size); Int hi_sum = sign(c[size]) ? sum : sum + c(size); Int lo_sum = sign(c[size]) ? sum + c(size) : sum; Formula hi = buildBDD(c, size, hi_sum, material_left, memo, max_cost); if (hi == _undef_) return _undef_; Formula lo = buildBDD(c, size, lo_sum, material_left, memo, max_cost); if (lo == _undef_) return _undef_; ret = ITE(var(var(c[size])), hi, lo); memo.set(key, ret); } return ret; }
void Map_set(Map* map, void* key, void* value) { Pair* pair = Pair_new(); pair->left = key; pair->right = value; BinarySearchTree_insert((BinarySearchTree*) map, pair); }
// Normalize a PB constraint to only positive constants. Depends on: // // bool ok -- Will be set to FALSE if constraint is unsatisfiable. // lbool value(Lit) -- Returns the value of a literal (however, it is sound to always return 'l_Undef', but produces less efficient results) // bool addUnit(Lit) -- Enqueue unit fact for propagation (returns FALSE if conflict detected). // // The two vectors 'ps' and 'Cs' (which are modififed by this method) should be interpreted as: // // 'p[0]*C[0] + p[1]*C[1] + ... + p[N-1]*C[N-1] >= C[N]' // // The method returns TRUE if constraint was normalized, FALSE if the constraint was already // satisfied or determined contradictory. The vectors 'ps' and 'Cs' should ONLY be used if // TRUE is returned. // bool PbSolver::normalizePb(vec<Lit>& ps, vec<Int>& Cs, Int& C) { assert(ps.size() == Cs.size()); if (!ok) return false; // Remove assigned literals and literals with zero coefficients: int new_sz = 0; for (int i = 0; i < ps.size(); i++){ if (value(ps[i]) != l_Undef){ if (value(ps[i]) == l_True) C -= Cs[i]; }else if (Cs[i] != 0){ ps[new_sz] = ps[i]; Cs[new_sz] = Cs[i]; new_sz++; } } ps.shrink(ps.size() - new_sz); Cs.shrink(Cs.size() - new_sz); //**/reportf("No zero, no assigned :"); for (int i = 0; i < ps.size(); i++) reportf(" %d*%sx%d", Cs[i], sign(ps[i])?"~":"", var(ps[i])); reportf(" >= %d\n", C); // Group all x/~x pairs // Map<Var, Pair<Int,Int> > var2consts(Pair_new(0,0)); // Variable -> negative/positive polarity constant for (int i = 0; i < ps.size(); i++){ Var x = var(ps[i]); Pair<Int,Int> consts = var2consts.at(x); if (sign(ps[i])) consts.fst += Cs[i]; else consts.snd += Cs[i]; var2consts.set(x, consts); } // Normalize constants to positive values only: // vec<Pair<Var, Pair<Int,Int> > > all; var2consts.pairs(all); vec<Pair<Int,Lit> > Csps(all.size()); for (int i = 0; i < all.size(); i++){ if (all[i].snd.fst < all[i].snd.snd){ // Negative polarity will vanish C -= all[i].snd.fst; Csps[i] = Pair_new(all[i].snd.snd - all[i].snd.fst, Lit(all[i].fst)); }else{ // Positive polarity will vanish C -= all[i].snd.snd; Csps[i] = Pair_new(all[i].snd.fst - all[i].snd.snd, ~Lit(all[i].fst)); } } // Sort literals on growing constant values: // sort(Csps); // (use lexicographical order of 'Pair's here) Int sum = 0; for (int i = 0; i < Csps.size(); i++){ Cs[i] = Csps[i].fst, ps[i] = Csps[i].snd, sum += Cs[i]; if (sum < 0) fprintf(stderr, "ERROR! Too large constants encountered in constraint.\n"), exit(1); } ps.shrink(ps.size() - Csps.size()); Cs.shrink(Cs.size() - Csps.size()); // Propagate already present consequences: // bool changed; do{ changed = false; while (ps.size() > 0 && sum-Cs.last() < C){ changed = true; if (!addUnit(ps.last())){ ok = false; return false; } sum -= Cs.last(); C -= Cs.last(); ps.pop(); Cs.pop(); } // Trivially true or false? if (C <= 0) return false; if (sum < C){ ok = false; return false; } assert(sum - Cs[ps.size()-1] >= C); // GCD: assert(Cs.size() > 0); Int div = Cs[0]; for (int i = 1; i < Cs.size(); i++) div = gcd(div, Cs[i]); for (int i = 0; i < Cs.size(); i++) Cs[i] /= div; C = (C + div-1) / div; if (div != 1) changed = true; // Trim constants: for (int i = 0; i < Cs.size(); i++) if (Cs[i] > C) changed = true, Cs[i] = C; }while (changed); //**/reportf("Normalized constraint:"); for (int i = 0; i < ps.size(); i++) reportf(" %d*%sx%d", Cs[i], sign(ps[i])?"~":"", var(ps[i])); reportf(" >= %d\n", C); return true; }