-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolver_instance_base.cpp
137 lines (121 loc) · 4.47 KB
/
solver_instance_base.cpp
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Guido Tack <[email protected]>
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <minizinc/solver_instance_base.hh>
#include <minizinc/flatten_internal.hh>
namespace MiniZinc {
SolverInstanceBase::Status
SolverInstanceBase::solve(void) { return SolverInstance::FAILURE; }
void
SolverInstanceBase::Registry::add(const ASTString& name, poster p) {
_keepAlive->addItem(new ConstraintI(Location(),new StringLit(Location(),name)));
_registry.insert(std::make_pair(name, p));
}
void
SolverInstanceBase::Registry::post(Call* c) {
ASTStringMap<poster>::t::iterator it = _registry.find(c->id());
if (it == _registry.end()) {
std::cerr << "Error: constraint not found: " << c->id() << "\n";
exit(EXIT_FAILURE);
}
it->second(_base, c);
}
void
SolverInstanceBase::assignSolutionToOutput(void) {
for (VarDeclIterator it = _env.output()->begin_vardecls(); it != _env.output()->end_vardecls(); ++it) {
if (it->e()->e() == NULL) {
it->e()->e(getSolutionValue(it->e()->id()));
}
}
}
void
SolverInstanceBase::flattenSearchAnnotations(const Annotation& ann, std::vector<Expression*>& out) {
for(ExpressionSetIter i = ann.begin(); i != ann.end(); ++i) {
Expression* e = *i;
if(e->isa<Call>() && e->cast<Call>()->id().str() == "seq_search") {
Call* c = e->cast<Call>();
ArrayLit* anns = c->args()[0]->cast<ArrayLit>();
for(unsigned int i=0; i<anns->v().size(); i++) {
Annotation subann;
subann.add(anns->v()[i]);
flattenSearchAnnotations(subann, out);
}
}
else if(e->isa<Call>() && e->cast<Call>()->id() == constants().ann.combinator) {
continue; // don't collect the search combinator annotation
} else {
out.push_back(*i);
}
}
}
bool
NISolverInstanceBase::updateIntBounds(VarDecl* vd, int lb, int ub) {
// the bounds have already been updated in the flat model
return true;
}
bool
NISolverInstanceBase::postConstraints(std::vector<Call*> cts) {
// the constraints are already added to the flat model
return true;
}
bool
NISolverInstanceBase::addVariables(const std::vector<VarDecl*>& vars) {
// the variables are already added to the flat model
return true;
}
KeepAlive
NISolverInstanceBase::deriveNoGoodsFromSolution(void) {
Model* flat = env().flat();
GCLock lock;
std::vector<Expression*> disequalities;
for (VarDeclIterator it = flat->begin_vardecls(); it!=flat->end_vardecls(); ++it) {
if (it->e()->ann().contains(constants().ann.output_var)) {
Id* id = it->e()->id();
Expression* sv = getSolutionValue(it->e()->id());
Expression* e = eval_par(env().envi(),sv);
// create the constraints: x_i != sol_i
BinOp* bo = new BinOp(Location(), id, BOT_NQ, e);
bo->type(Type::varbool());
disequalities.push_back(bo);
}
}
ArrayLit* array = new ArrayLit(Location(), disequalities);
array->type(Type::varbool(1));
std::vector<Expression*> args;
args.push_back(array);
Call* disjunction = new Call(Location(), constants().ids.exists, args);
disjunction->type(Type::varbool());
disjunction->decl(env().model()->matchFn(env().envi(), disjunction));
KeepAlive ka(disjunction);
return ka;
}
SolverInstance::Status
NISolverInstanceBase::next(void) {
if(_new_solution) {
// the variables and constraints to be posted are already added to the flat model during flattening
postSolutionNoGoods();
}
Status status = nextSolution();
if(status == Status::SUCCESS) {
_new_solution = true;
assignSolutionToOutput();
}
else _new_solution = false;
return status;
}
void
NISolverInstanceBase::postSolutionNoGoods(void) {
KeepAlive nogoods = deriveNoGoodsFromSolution();
// flatten the nogoods, which adds it to the model
FlatteningOptions fopt;
fopt.keepOutputInFzn = true;
(void) flatten(env().envi(), nogoods(), constants().var_true, constants().var_true, fopt);
// convert to old flatzinc
oldflatzinc(env());
}
}