// Will return '_undef_' if 'cost_limit' is exceeded. // Formula buildConstraint(const Linear& c, int max_cost) { vec<Formula> ps; vec<Int> Cs; for (int j = 0; j < c.size; j++) ps.push(lit2fml(c[j])), Cs.push(c(j)); vec<Int> dummy; int cost; vec<int> base; optimizeBase(Cs, dummy, cost, base); FEnv::push(); Formula ret; try { ret = buildConstraint(ps, Cs, base, c.lo, c.hi, max_cost); }catch (Exception_TooBig){ FEnv::pop(); return _undef_; } if (opt_verbosity >= 1){ reportf("Sorter-cost:%5d ", FEnv::topSize()); reportf("Base:"); for (int i = 0; i < base.size(); i++) reportf(" %d", base[i]); reportf("\n"); } FEnv::keep(); return ret; }
/** * Probably one of the more interesting functions. */ SearchMetaData* searchForBase(vec<Int>& inCoeffs, vec<int>& outputBase,PrimesLoader& pl, PBOptions* options) { std::map<unsigned int,unsigned int> multiSet; vecToMultiSet(inCoeffs,multiSet); unsigned int weights[multiSet.size()][2]; coeffsToDescendingWeights(multiSet, weights); SearchMetaData* data = 0; unsigned int cutof = pl.loadPrimes(weights[0][0],options->opt_max_generator); std::vector<unsigned int>& pri = pl.primeVector(); if (options->opt_base == base_Forward) data = findBaseFWD(weights, multiSet.size(), pri,cutof); else if (options->opt_base == base_SOD) data = bnb_SOD_Carry_Cost_search(weights, multiSet.size(),pri,cutof,false,true,true); else if (options->opt_base == base_Carry) data = bnb_SOD_Carry_Cost_search(weights, multiSet.size(), pri,cutof,options->opt_non_prime,options->opt_abstract); else if (options->opt_base == base_Comp) data = bnb_Comp_Cost_search(weights, multiSet.size(), pri,cutof,options->opt_non_prime,options->opt_abstract); else if (options->opt_base == base_oddEven) data = bnb_oddEven_Cost_search(weights, multiSet.size(), pri,cutof,options->opt_non_prime,options->opt_abstract); else if (options->opt_base == base_Rel) data = bnb_Relative_search(weights, multiSet.size() , pri,cutof,options->opt_non_prime,options->opt_abstract); else if (options->opt_base == base_Bin) { data = new SearchMetaData(lg2(weights[0][0]),cutof,weights[0][0],multiSet.size(),"BinaryBase"); data->finalize(0); } else if (options->opt_base == base_M) { vec<Int> dummy; int cost; data = optimizeBase(inCoeffs, dummy, cost, outputBase,weights,multiSet.size(), cutof); } else printf("Unknown option!"), exit(-1); data->inputCountCost = inputCountEval(weights,data->base,multiSet.size()); data->carryOnlyCost = carryOnlyEval(weights,data->base,multiSet.size()); data->compCost = compCountEval(weights,data->base,multiSet.size()); for (unsigned int j=0;j<multiSet.size();j++){ data->emptyBaseNOI += weights[j][0]*weights[j][1]; data->numOfCoffes += weights[j][1]; } carryVecEval(weights,data->base,multiSet.size(),data->carry); inputVecEval(weights,data->base,multiSet.size(),data->inputs); if (options->opt_verbosity >= 1) { data->print(); printf("Run time is in micro seconds!!!\n"); } if (options->opt_base != base_M) metaDataToBase(data, outputBase); options->baseMetaData.push_back(data); return data; }
static void optimizeBase(vec<Int>& seq, int carry_ins, vec<Int>& rhs, int cost, vec<int>& base, int& cost_bestfound, vec<int>& base_bestfound) { if (cost >= cost_bestfound) return; // "Base case" -- don't split further, build sorting network for current sequence: int final_cost = 0; for (int i = 0; i < seq.size(); i++){ if (seq[i] > INT_MAX) goto TooBig; #ifdef ExpensiveBigConstants final_cost += toint(seq[i]); #else int c; for (c = 1; c*c < seq[i]; c++); final_cost += c; #endif if (final_cost < 0) goto TooBig; } if (cost + final_cost < cost_bestfound){ base.copyTo(base_bestfound); cost_bestfound = cost + final_cost; } TooBig:; /**/static int depth = 0; // <<== could count 1:s here for efficiency vec<Int> new_seq; vec<Int> new_rhs; #ifdef PickSmallest int p = -1; for (int i = 0; i < seq.size(); i++) if (seq[i] > 1){ p = seq[i]; break; } if (p != -1){ #else //int upper_lim = (seq.size() == 0) ? 1 : seq.last(); // <<== Check that sqRoot is an 'int' (no truncation of 'Int') //for (int i = 0; i < (int)elemsof(primes) && primes[i] <= upper_lim; i++){ for (int i = 0; i < (int)elemsof(primes); i++){ int p = primes[i]; #endif int rest = carry_ins; // Sum of all the remainders. Int div, rem; /**/for (int n = depth; n != 0; n--) pf(" "); pf("prime=%d carry_ins=%d\n", p, carry_ins); /**/for (int n = depth; n != 0; n--) pf(" "); pf("New seq:"); for (int j = 0; j < seq.size(); j++){ rest += toint(seq[j] % Int(p)); div = seq[j] / Int(p); if (div > 0) //**/pf(" %d", div), new_seq.push(div); } /**/pf("\n"); /**/for (int n = depth; n != 0; n--) pf(" "); pf("rest=%d\n", rest); /**/for (int n = depth; n != 0; n--) pf(" "); pf("New rhs:"); #ifdef AllDigitsImportant bool digit_important = true; #else bool digit_important = false; #endif for (int j = 0; j < rhs.size(); j++){ div = rhs[j] / p; if (new_rhs.size() == 0 || div > new_rhs.last()){ rem = rhs[j] % p; /**/pf(" %d:%d", div, rem), new_rhs.push(div); if (!(rem == 0 && rest < p) && !(rem > rest)) digit_important = true; } /* <<== om 'rhs' slutar på 0:a och 'rest' inte kan overflowa, då behövs inte det sorterande nätverket för 'rest' ("always TRUE") samma sak om 'rhs' sista siffra är strikt större än 'rest' ("never TRUE") */ } /**/pf("\n\n"); base.push(p); /**/depth++; optimizeBase(new_seq, rest/p, new_rhs, cost+(digit_important ? rest : 0), base, cost_bestfound, base_bestfound); /**/depth--; base.pop(); new_seq.clear(); new_rhs.clear(); } } static void optimizeBase(vec<Int>& seq, vec<Int>& rhs, int& cost_bestfound, vec<int>& base_bestfound) { vec<int> base; cost_bestfound = INT_MAX; base_bestfound.clear(); optimizeBase(seq, 0, rhs, 0, base, cost_bestfound, base_bestfound); }