this repo has no description
at develop 8.2 kB view raw
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 3/* 4 * Main authors: 5 * Jip J. Dekker <jip.dekker@monash.edu> 6 * Guido Tack <guido.tack@monash.edu> 7 */ 8 9/* This Source Code Form is subject to the terms of the Mozilla Public 10 * License, v. 2.0. If a copy of the MPL was not distributed with this 11 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 12 13#include <minizinc/interpreter.hh> 14#include <minizinc/interpreter/primitives.hh> 15 16namespace MiniZinc { 17 18namespace BytecodePrimitives { 19IntPlus int_plus; 20IntMinus int_minus; 21IntSum int_sum; 22IntTimes int_times; 23 24IntLinEq int_lin_eq; 25IntLinEqReif int_lin_eq_reif; 26IntLinLe int_lin_le; 27IntLinLeReif int_lin_le_reif; 28 29MkIntVar mk_intvar; 30BoolNot boolnot; 31OpNot opnot; 32Clause clause; 33ClauseReif clause_reif; 34Forall forall; 35Exists exists; 36Uniform uniform; 37Sol sol; 38Sort sort; 39SortBy sortby; 40IntMax intmax; 41Infinity infinity; 42InfiniteDomain inf_dom; 43BooleanDomain bool_dom; 44SliceXd slice_xd; 45ArrayXd array_xd; 46IndexSet index_set; 47 48PrimitiveMap::Primitive* AllPrimitives[] = { 49 &int_plus, &int_minus, 50 &int_sum, &int_times, 51 52 &int_lin_eq, &int_lin_eq_reif, 53 &int_lin_le, &int_lin_le_reif, 54 55 &mk_intvar, &boolnot, 56 &opnot, &clause, 57 &clause_reif, &forall, 58 &exists, &uniform, 59 &sol, &sort, 60 &sortby, &intmax, 61 &infinity, &inf_dom, 62 &bool_dom, &slice_xd, 63 &array_xd, &index_set, 64}; 65} // namespace BytecodePrimitives 66 67PrimitiveMap::PrimitiveMap(void) : _p(PrimitiveMap::MAX_ID + 1) { 68 for (PrimitiveMap::Primitive* p : BytecodePrimitives::AllPrimitives) { 69 _p[p->ident()] = p; 70 } 71 for (Primitive* p : _p) { 72 _s.insert(std::make_pair(p->name(), p)); 73 } 74 _n.resize(_s.size()); 75 for (auto& entry : _s) { 76 _n[entry.second->ident()] = entry.first; 77 } 78} 79 80PrimitiveMap& primitiveMap(void) { 81 static PrimitiveMap _pm; 82 return _pm; 83} 84 85namespace BytecodePrimitives { 86 87void Uniform::execute(Interpreter& i, const std::vector<Val>& args) { 88 assert(args.size() == 2); 89 assert(args[0].isInt() && args[1].isInt()); 90 91 std::uniform_int_distribution<> dis(args[0].toInt(), args[1].toInt()); 92 Val rnd = dis(generator); 93 i.pushAgg(rnd, -1); 94} 95 96void Sol::execute(Interpreter& i, const std::vector<Val>& args) { 97 assert(args.size() == 1); 98 if (args[0].isVar()) { 99 auto it = i.solutions.find(args[0].timestamp()); 100 assert(it != i.solutions.end()); 101 i.pushAgg(Val(it->second), -1); 102 } else { 103 assert(args[0].isInt()); 104 i.pushAgg(args[0], -1); 105 } 106}; 107 108void Sort::execute(Interpreter& i, const std::vector<Val>& args) { 109 assert(args.size() == 1); 110 111 Val al = args[0].toVec()->raw_data(); 112 std::vector<int> ai(al.size()); 113 for (int j = 0; j < al.size(); j++) { 114 ai[j] = al[j].toInt(); 115 } 116 std::stable_sort(ai.begin(), ai.end()); 117 118 std::vector<Val> sorted(al.size()); 119 for (int j = 0; j < al.size(); j++) { 120 sorted[j] = Val(ai[j]); 121 } 122 Vec* al_sorted = Vec::a(&i, i.newIdent(), sorted); 123 124 i.pushAgg(Val(al_sorted), -1); 125}; 126 127void SortBy::execute(Interpreter& i, const std::vector<Val>& args) { 128 assert(args.size() == 2); 129 130 Val al = args[0].toVec()->raw_data(); 131 Val order_e = args[1].toVec()->raw_data(); 132 std::vector<Val> order(order_e.size()); 133 std::vector<int> a(order_e.size()); 134 for (int j = 0; j < order.size(); j++) { 135 a[j] = j; 136 order[j] = order_e[j]; 137 } 138 struct Ord { 139 std::vector<Val>& order; 140 explicit Ord(std::vector<Val>& order0) : order(order0) {} 141 bool operator()(int i, int j) { return order[i] < order[j]; } 142 } _ord(order); 143 std::stable_sort(a.begin(), a.end(), _ord); 144 std::vector<Val> sorted(a.size()); 145 for (int j = sorted.size(); j--;) { 146 sorted[j] = al[a[j]]; 147 } 148 Vec* al_sorted = Vec::a(&i, i.newIdent(), sorted); 149 150 i.pushAgg(Val(al_sorted), -1); 151}; 152 153void Infinity::execute(Interpreter& i, const std::vector<Val>& args) { 154 assert(args.size() == 1); 155 assert(args[0].isInt()); 156 157 if (args[0] > 0) { 158 i.pushAgg(Val::infinity(), -1); 159 } else { 160 i.pushAgg(-Val::infinity(), -1); 161 } 162} 163 164void InfiniteDomain::execute(Interpreter& i, const std::vector<Val>& args) { 165 assert(args.size() == 0); 166 i.pushAgg(i.infinite_domain(), -1); 167} 168 169void BooleanDomain::execute(Interpreter& i, const std::vector<Val>& args) { 170 assert(args.size() == 0); 171 i.pushAgg(i.boolean_domain(), -1); 172}; 173 174void SliceXd::execute(Interpreter& i, const std::vector<Val>& args) { 175 assert(args.size() == 3); 176 assert(args[0].isVec() && args[1].isVec() && args[2].isVec()); 177 178 Val content = args[0].toVec()->raw_data(); 179 Val selection = args[1].toVec()->raw_data(); 180 Val new_idxs = args[2].toVec()->raw_data(); 181 182 std::vector<Val> idxs(args[1].size()); 183 std::vector<Val> slice; 184 // Initialise indexes to the index lower bound 185 if (args[0].toVec()->hasIndexSet()) { 186 Val index_set = args[0].toVec()->index_set(); 187 assert(index_set.size() / 2 == selection.size()); 188 for (int j = 0; j < idxs.size(); ++j) { 189 idxs[j] = index_set[j * 2]; 190 } 191 } else { 192 assert(selection.size() == 1); 193 idxs[0] = 1; 194 } 195 196 // Walk through array and make slice selection 197 int level = idxs.size() - 1; 198 int it = 0; 199 while (level >= 0) { 200 bool in_slice = true; 201 for (int k = 0; k < idxs.size(); ++k) { 202 assert(selection[k].size() == 2); 203 in_slice = in_slice && selection[k][0] <= idxs[k] && idxs[k] <= selection[k][1]; 204 } 205 206 assert(it < content.size()); 207 if (in_slice) { 208 slice.push_back(content[it]); 209 } 210 it++; 211 212 while (level >= 0) { 213 if (args[0].toVec()->hasIndexSet()) { 214 Val index_set = args[0].toVec()->index_set(); 215 if (idxs[level] < index_set[level * 2 + 1]) { 216 idxs[level]++; 217 level = idxs.size() - 1; 218 break; 219 } else { 220 idxs[level] = index_set[level * 2]; 221 level--; 222 } 223 } else { 224 assert(level == 0); 225 if (idxs[0] < content.size()) { 226 idxs[0]++; 227 // No need to reset level, there is only one. 228 break; 229 } else { 230 // Done (no need to reset index values). 231 level--; 232 } 233 } 234 } 235 } 236 237 // Format new index sets 238 std::vector<Val> dom; 239 dom.reserve(new_idxs.size() * 2); 240 for (int j = 0; j < new_idxs.size(); ++j) { 241 assert(new_idxs[j].size() == 2); 242 dom.push_back(new_idxs[j][0]); 243 dom.push_back(new_idxs[j][1]); 244 } 245 246 Vec* values = Vec::a(&i, i.newIdent(), slice); 247 Vec* idx = Vec::a(&i, i.newIdent(), dom); 248 Vec* nv = Vec::a(&i, i.newIdent(), {Val(values), Val(idx)}, true); 249 250 i.pushAgg(Val(nv), -1); 251} 252 253void ArrayXd::execute(Interpreter& i, const std::vector<Val>& args) { 254 assert(args.size() == 2); 255 assert(args[0].isVec()); 256 257 // Array Elements 258 Val arr = args[0].toVec()->raw_data(); 259 260 if (args[1].isInt()) { 261 assert(args[1].toInt() == 0); 262 i.pushAgg(arr, -1); 263 return; 264 } 265 266 assert(args[1].isVec()); 267 assert(args[1].size() % 2 == 0); 268 // Check if the index sets actually match up 269 int prod = 1; 270 for (int i = 0; i < args[1].size(); i += 2) { 271 prod *= (args[1][i + 1].toInt() - args[1][i].toInt() + 1); 272 } 273 if (arr.size() != prod) { 274 throw std::runtime_error("ArrayXd cardinality mismatch"); 275 } 276 277 Val ret = arr; 278 if (args[1].size() != 0 && !(args[1].size() == 2 && args[1][0].toInt() == 1)) { 279 ret = Val(Vec::a(&i, i.newIdent(), {arr, args[1]}, true)); 280 } 281 i.pushAgg(ret, -1); 282} 283 284void IndexSet::execute(Interpreter& i, const std::vector<Val>& args) { 285 assert(args.size() == 2); 286 assert(args[0].isVec() && args[1].isInt()); 287 288 Val ret; 289 if (!args[0].toVec()->hasIndexSet()) { 290 assert(args[1].toInt() == 1 || args[1] == 0); 291 ret = Val(Vec::a(&i, i.newIdent(), {Val(1), Val(args[0].size())})); 292 } else if (args[1] == 0) { 293 ret = args[0].toVec()->index_set(); 294 } else { 295 assert(args[0].size() == 2); 296 assert(args[0][1].isVec()); 297 assert(args[0][1].size() / 2 >= args[1].toInt()); 298 Val index_sets = args[0].toVec()->index_set(); 299 ret = Val( 300 Vec::a(&i, i.newIdent(), 301 {index_sets[(args[1].toInt() - 1) * 2], index_sets[(args[1].toInt() - 1) * 2 + 1]})); 302 } 303 i.pushAgg(ret, -1); 304} 305 306} // namespace BytecodePrimitives 307} // namespace MiniZinc