this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3/*
4 * Main authors:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7
8/* This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12#include <minizinc/eval_par.hh>
13#include <minizinc/solver_instance_base.hh>
14
15#ifdef _MSC_VER
16#define _CRT_SECURE_NO_WARNINGS
17#undef ERROR // MICROsoft.
18#undef min
19#undef max
20#endif
21
22namespace MiniZinc {
23
24SolverInstanceBase::Status SolverInstanceBase::solve(void) { return SolverInstance__ERROR; }
25
26void SolverInstanceBase::reset(void) { assert(false); }
27
28void SolverInstanceBase::resetWithConstraints(Model::iterator begin, Model::iterator end) {
29 assert(false);
30}
31
32void SolverInstanceBase::processPermanentConstraints(Model::iterator begin, Model::iterator end) {
33 assert(false);
34}
35
36void Registry::add(const std::string& name, poster p) { _registry.insert(std::make_pair(name, p)); }
37void Registry::post(std::string name, Constraint* c) {
38 std::unordered_map<std::string, poster>::iterator it = _registry.find(name);
39 if (it == _registry.end()) {
40 GCLock lock;
41 throw InternalError("Error: solver backend cannot handle constraint: " + name + "\n");
42 }
43 it->second(_base, c);
44}
45
46void SolverInstanceBase::printSolution() {
47 std::ostringstream oss;
48
49 if (_options->printStatistics) printStatistics(1); // Insert stats before sol separator
50 if (0 == pS2Out) {
51 getEnv()->evalOutput(std::cout); // deprecated
52 std::cout << oss.str();
53 if (oss.str().size() && '\n' != oss.str().back()) std::cout << '\n';
54 std::cout << "----------" << std::endl;
55 } else
56 getSolns2Out()->evalOutput(oss.str());
57}
58
59void SolverInstanceBase2::printSolution() {
60 GCLock lock;
61 assignSolutionToOutput();
62 SolverInstanceBase::printSolution();
63}
64
65// void
66// SolverInstanceBase::assignSolutionToOutput(void) {
67// for (VarDeclIterator it = getEnv()->output()->begin_vardecls(); it !=
68// getEnv()->output()->end_vardecls(); ++it) {
69// if (it->e()->e() == NULL) {
70// it->e()->e(getSolutionValue(it->e()->id()));
71// }
72// }
73// }
74
75void SolverInstanceBase2::assignSolutionToOutput() {
76 GCLock lock;
77
78 MZN_ASSERT_HARD_MSG(
79 0 != pS2Out, "Setup a Solns2Out object to use default solution extraction/reporting procs");
80
81 if (_varsWithOutput.empty()) {
82 for (VarDeclIterator it = getEnv()->flat()->begin_vardecls();
83 it != getEnv()->flat()->end_vardecls(); ++it) {
84 if (!it->removed()) {
85 VarDecl* vd = it->e();
86 if (!vd->ann().isEmpty()) {
87 if (vd->ann().containsCall(constants().ann.output_array.aststr()) ||
88 vd->ann().contains(constants().ann.output_var)) {
89 _varsWithOutput.push_back(vd);
90 }
91 }
92 }
93 }
94 }
95
96 pS2Out->declNewOutput(); // Even for empty output decl
97
98 // iterate over set of ids that have an output annotation && obtain their right hand side from the
99 // flat model
100 for (unsigned int i = 0; i < _varsWithOutput.size(); i++) {
101 VarDecl* vd = _varsWithOutput[i];
102 // std::cout << "DEBUG: Looking at var-decl with output-annotation: " << *vd << std::endl;
103 if (Call* output_array_ann = Expression::dyn_cast<Call>(
104 getAnnotation(vd->ann(), constants().ann.output_array.aststr()))) {
105 assert(vd->e());
106
107 if (ArrayLit* al = vd->e()->dyn_cast<ArrayLit>()) {
108 std::vector<Expression*> array_elems;
109 ArrayLit& array = *al;
110 for (unsigned int j = 0; j < array.size(); j++) {
111 if (Id* id = array[j]->dyn_cast<Id>()) {
112 // std::cout << "DEBUG: getting solution value from " << *id << " : " << id->v() <<
113 // std::endl;
114 array_elems.push_back(getSolutionValue(id));
115 } else if (FloatLit* floatLit = array[j]->dyn_cast<FloatLit>()) {
116 array_elems.push_back(floatLit);
117 } else if (IntLit* intLit = array[j]->dyn_cast<IntLit>()) {
118 array_elems.push_back(intLit);
119 } else if (BoolLit* boolLit = array[j]->dyn_cast<BoolLit>()) {
120 array_elems.push_back(boolLit);
121 } else if (SetLit* setLit = array[j]->dyn_cast<SetLit>()) {
122 array_elems.push_back(setLit);
123 } else if (StringLit* strLit = array[j]->dyn_cast<StringLit>()) {
124 array_elems.push_back(strLit);
125 } else {
126 std::ostringstream oss;
127 oss << "Error: array element " << *array[j] << " is not an id nor a literal";
128 throw InternalError(oss.str());
129 }
130 }
131 GCLock lock;
132 ArrayLit* dims;
133 Expression* e = output_array_ann->arg(0);
134 if (ArrayLit* al = e->dyn_cast<ArrayLit>()) {
135 dims = al;
136 } else if (Id* id = e->dyn_cast<Id>()) {
137 dims = id->decl()->e()->cast<ArrayLit>();
138 } else {
139 throw -1;
140 }
141 std::vector<std::pair<int, int> > dims_v;
142 for (int i = 0; i < dims->length(); i++) {
143 IntSetVal* isv = eval_intset(getEnv()->envi(), (*dims)[i]);
144 if (isv->size() == 0) {
145 dims_v.push_back(std::pair<int, int>(1, 0));
146 } else {
147 dims_v.push_back(std::pair<int, int>(static_cast<int>(isv->min().toInt()),
148 static_cast<int>(isv->max().toInt())));
149 }
150 }
151 ArrayLit* array_solution = new ArrayLit(Location(), array_elems, dims_v);
152 KeepAlive ka(array_solution);
153 auto& de = getSolns2Out()->findOutputVar(vd->id()->str().str());
154 de.first->e(array_solution);
155 }
156 } else if (vd->ann().contains(constants().ann.output_var)) {
157 Expression* sol = getSolutionValue(vd->id());
158 vd->e(sol);
159 auto& de = getSolns2Out()->findOutputVar(vd->id()->str().str());
160 de.first->e(sol);
161 }
162 }
163}
164
165void SolverInstanceBase::flattenSearchAnnotations(const Annotation& ann,
166 std::vector<Expression*>& out) {
167 for (ExpressionSetIter i = ann.begin(); i != ann.end(); ++i) {
168 Expression* e = *i;
169 if (e->isa<Call>() && (e->cast<Call>()->id().str() == "seq_search" ||
170 e->cast<Call>()->id().str() == "warm_start_array")) {
171 Call* c = e->cast<Call>();
172 auto* anns = c->arg(0)->cast<ArrayLit>();
173 for (unsigned int i = 0; i < anns->size(); i++) {
174 Annotation subann;
175 subann.add((*anns)[i]);
176 flattenSearchAnnotations(subann, out);
177 }
178 } else {
179 out.push_back(*i);
180 }
181 }
182}
183
184} // namespace MiniZinc