Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
8.2 kB · 307 lines
C++
at develop
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* * Main authors: * Jip J. Dekker <jip.dekker@monash.edu> * Guido Tack <guido.tack@monash.edu> */
/* 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/interpreter.hh>#include <minizinc/interpreter/primitives.hh>
namespace MiniZinc {
namespace BytecodePrimitives {IntPlus int_plus;IntMinus int_minus;IntSum int_sum;IntTimes int_times;
IntLinEq int_lin_eq;IntLinEqReif int_lin_eq_reif;IntLinLe int_lin_le;IntLinLeReif int_lin_le_reif;
MkIntVar mk_intvar;BoolNot boolnot;OpNot opnot;Clause clause;ClauseReif clause_reif;Forall forall;Exists exists;Uniform uniform;Sol sol;Sort sort;SortBy sortby;IntMax intmax;Infinity infinity;InfiniteDomain inf_dom;BooleanDomain bool_dom;SliceXd slice_xd;ArrayXd array_xd;IndexSet index_set;
PrimitiveMap::Primitive* AllPrimitives[] = { &int_plus, &int_minus, &int_sum, &int_times,
&int_lin_eq, &int_lin_eq_reif, &int_lin_le, &int_lin_le_reif,
&mk_intvar, &boolnot, &opnot, &clause, &clause_reif, &forall, &exists, &uniform, &sol, &sort, &sortby, &intmax, &infinity, &inf_dom, &bool_dom, &slice_xd, &array_xd, &index_set,};} // namespace BytecodePrimitives
PrimitiveMap::PrimitiveMap(void) : _p(PrimitiveMap::MAX_ID + 1) { for (PrimitiveMap::Primitive* p : BytecodePrimitives::AllPrimitives) { _p[p->ident()] = p; } for (Primitive* p : _p) { _s.insert(std::make_pair(p->name(), p)); } _n.resize(_s.size()); for (auto& entry : _s) { _n[entry.second->ident()] = entry.first; }}
PrimitiveMap& primitiveMap(void) { static PrimitiveMap _pm; return _pm;}
namespace BytecodePrimitives {
void Uniform::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 2); assert(args[0].isInt() && args[1].isInt());
std::uniform_int_distribution<> dis(args[0].toInt(), args[1].toInt()); Val rnd = dis(generator); i.pushAgg(rnd, -1);}
void Sol::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 1); if (args[0].isVar()) { auto it = i.solutions.find(args[0].timestamp()); assert(it != i.solutions.end()); i.pushAgg(Val(it->second), -1); } else { assert(args[0].isInt()); i.pushAgg(args[0], -1); }};
void Sort::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 1);
Val al = args[0].toVec()->raw_data(); std::vector<int> ai(al.size()); for (int j = 0; j < al.size(); j++) { ai[j] = al[j].toInt(); } std::stable_sort(ai.begin(), ai.end());
std::vector<Val> sorted(al.size()); for (int j = 0; j < al.size(); j++) { sorted[j] = Val(ai[j]); } Vec* al_sorted = Vec::a(&i, i.newIdent(), sorted);
i.pushAgg(Val(al_sorted), -1);};
void SortBy::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 2);
Val al = args[0].toVec()->raw_data(); Val order_e = args[1].toVec()->raw_data(); std::vector<Val> order(order_e.size()); std::vector<int> a(order_e.size()); for (int j = 0; j < order.size(); j++) { a[j] = j; order[j] = order_e[j]; } struct Ord { std::vector<Val>& order; explicit Ord(std::vector<Val>& order0) : order(order0) {} bool operator()(int i, int j) { return order[i] < order[j]; } } _ord(order); std::stable_sort(a.begin(), a.end(), _ord); std::vector<Val> sorted(a.size()); for (int j = sorted.size(); j--;) { sorted[j] = al[a[j]]; } Vec* al_sorted = Vec::a(&i, i.newIdent(), sorted);
i.pushAgg(Val(al_sorted), -1);};
void Infinity::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 1); assert(args[0].isInt());
if (args[0] > 0) { i.pushAgg(Val::infinity(), -1); } else { i.pushAgg(-Val::infinity(), -1); }}
void InfiniteDomain::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 0); i.pushAgg(i.infinite_domain(), -1);}
void BooleanDomain::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 0); i.pushAgg(i.boolean_domain(), -1);};
void SliceXd::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 3); assert(args[0].isVec() && args[1].isVec() && args[2].isVec());
Val content = args[0].toVec()->raw_data(); Val selection = args[1].toVec()->raw_data(); Val new_idxs = args[2].toVec()->raw_data();
std::vector<Val> idxs(args[1].size()); std::vector<Val> slice; // Initialise indexes to the index lower bound if (args[0].toVec()->hasIndexSet()) { Val index_set = args[0].toVec()->index_set(); assert(index_set.size() / 2 == selection.size()); for (int j = 0; j < idxs.size(); ++j) { idxs[j] = index_set[j * 2]; } } else { assert(selection.size() == 1); idxs[0] = 1; }
// Walk through array and make slice selection int level = idxs.size() - 1; int it = 0; while (level >= 0) { bool in_slice = true; for (int k = 0; k < idxs.size(); ++k) { assert(selection[k].size() == 2); in_slice = in_slice && selection[k][0] <= idxs[k] && idxs[k] <= selection[k][1]; }
assert(it < content.size()); if (in_slice) { slice.push_back(content[it]); } it++;
while (level >= 0) { if (args[0].toVec()->hasIndexSet()) { Val index_set = args[0].toVec()->index_set(); if (idxs[level] < index_set[level * 2 + 1]) { idxs[level]++; level = idxs.size() - 1; break; } else { idxs[level] = index_set[level * 2]; level--; } } else { assert(level == 0); if (idxs[0] < content.size()) { idxs[0]++; // No need to reset level, there is only one. break; } else { // Done (no need to reset index values). level--; } } } }
// Format new index sets std::vector<Val> dom; dom.reserve(new_idxs.size() * 2); for (int j = 0; j < new_idxs.size(); ++j) { assert(new_idxs[j].size() == 2); dom.push_back(new_idxs[j][0]); dom.push_back(new_idxs[j][1]); }
Vec* values = Vec::a(&i, i.newIdent(), slice); Vec* idx = Vec::a(&i, i.newIdent(), dom); Vec* nv = Vec::a(&i, i.newIdent(), {Val(values), Val(idx)}, true);
i.pushAgg(Val(nv), -1);}
void ArrayXd::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 2); assert(args[0].isVec());
// Array Elements Val arr = args[0].toVec()->raw_data();
if (args[1].isInt()) { assert(args[1].toInt() == 0); i.pushAgg(arr, -1); return; }
assert(args[1].isVec()); assert(args[1].size() % 2 == 0); // Check if the index sets actually match up int prod = 1; for (int i = 0; i < args[1].size(); i += 2) { prod *= (args[1][i + 1].toInt() - args[1][i].toInt() + 1); } if (arr.size() != prod) { throw std::runtime_error("ArrayXd cardinality mismatch"); }
Val ret = arr; if (args[1].size() != 0 && !(args[1].size() == 2 && args[1][0].toInt() == 1)) { ret = Val(Vec::a(&i, i.newIdent(), {arr, args[1]}, true)); } i.pushAgg(ret, -1);}
void IndexSet::execute(Interpreter& i, const std::vector<Val>& args) { assert(args.size() == 2); assert(args[0].isVec() && args[1].isInt());
Val ret; if (!args[0].toVec()->hasIndexSet()) { assert(args[1].toInt() == 1 || args[1] == 0); ret = Val(Vec::a(&i, i.newIdent(), {Val(1), Val(args[0].size())})); } else if (args[1] == 0) { ret = args[0].toVec()->index_set(); } else { assert(args[0].size() == 2); assert(args[0][1].isVec()); assert(args[0][1].size() / 2 >= args[1].toInt()); Val index_sets = args[0].toVec()->index_set(); ret = Val( Vec::a(&i, i.newIdent(), {index_sets[(args[1].toInt() - 1) * 2], index_sets[(args[1].toInt() - 1) * 2 + 1]})); } i.pushAgg(ret, -1);}
} // namespace BytecodePrimitives} // namespace MiniZinc