/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Guido Tack * * Copyright: * Guido Tack, 2006 * * Last modified: * $Date: 2008-01-13 15:02:42 +0100 (Sun, 13 Jan 2008) $ by $Author: schulte $ * $Revision: 5862 $ * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "gecode/set/projectors-compiler.hh" #include #include #include #include namespace Gecode { ProjectorCompiler::Indent::Indent(void) : i(0) {} void ProjectorCompiler::Indent::operator++(void) { i+=2; } void ProjectorCompiler::Indent::operator--(void) { i-=2; } std::ostream& operator<<(std::ostream& os, const ProjectorCompiler::Indent& indent) { for (int i=0; i= 4; } std::string ProjectorCompiler::propcost(void) { switch (spec._arity) { case 1: return "PC_UNARY_HI"; case 2: return "PC_BINARY_HI"; case 3: return "PC_TERNARY_HI"; default: return "PC_LINEAR_HI"; } } void ProjectorCompiler::header(std::ostream& os) { os << "// This file was generated from projector specifications." << std::endl << std::endl; if (spec._namespace != "") { os << indent << spec._namespace << std::endl; ++indent; } } void ProjectorCompiler::footer(std::ostream& os) { if (spec._namespace != "") { --indent; os << indent << "}"; } os << std::endl; } void ProjectorCompiler::viewsarglist(std::ostream& os) { if (nary()) { os << "ViewArray& x"; } else { for (int i=0; i"; } void ProjectorCompiler::templatehead(std::ostream& os) { if (nary() || views==SINGLE_VIEW) os << indent << "template " << std::endl; else { os << indent << "template <"; for (int i=0; i" << std::endl; } } void ProjectorCompiler::classdef(void) { using namespace std; templatehead(hhos); hhos << indent << "class " << spec._name << " : public Propagator { " << endl << indent << "protected:" << endl; if (nary()) hhos << indent << " ViewArray _x; ///< The view array" << endl; else for (int i=0; i scope; spec._ps.scope(scope, projArity); bool isNary = nary(); for (int i=0; i<=projArity; i++) { iccos << indent << "_x"; if (isNary) iccos << "["; iccos << i; if (isNary) iccos << "]"; iccos << ".subscribe(home, this, " << propcond(scope[i]) << ");" << endl; } if (spec._reified) iccos << indent << "_b.subscribe(home, this, Gecode::Int::PC_INT_VAL);" << endl; --indent; iccos << indent << "}" << endl; /////////////////////////////////////////////////// iccos << endl; /////////////////////////////////////////////////// // Copy constructor templatehead(iccos); iccos << indent << spec._name; templateparams(); iccos << "::" << spec._name << endl << indent << "(Space* home, bool share, " << spec._name << "& p)" << endl; ++indent; iccos << indent << ": Propagator(home, share, p) {" << endl; if (isNary) { iccos << indent << "_x.update(home, share, p._x);" << endl; } else { for (int i=0; ifailed()) {" << endl; ++indent; for (int i=0; i<=projArity; i++) { iccos << indent << "_x"; if (isNary) iccos << "["; iccos << i; if (isNary) iccos << "]"; iccos << ".cancel(home, this, " << propcond(scope[i]) << ");" << endl; } if (spec._reified) iccos << indent << "_b.cancel(home, this, Gecode::Int::PC_INT_VAL);" << endl; --indent; iccos << indent << "}" << endl; iccos << indent << "(void) Propagator::dispose(home);" << endl << indent << "return sizeof(*this);" << endl; --indent; iccos << indent << "}" << endl << endl; /////////////////////////////////////////////////// /////////////////////////////////////////////////// // Copy function templatehead(iccos); iccos << indent << "Actor*" << endl << indent << spec._name; templateparams(); iccos << "::copy(Space* home, bool share) {" << endl << indent << " return new (home) " << spec._name << "(home,share,*this);" << endl << indent << "}" << endl << endl; /////////////////////////////////////////////////// /////////////////////////////////////////////////// // Post member function templatehead(iccos); iccos << indent << "ExecStatus" << endl << indent << spec._name; templateparams(); iccos << "::post(Space* home, "; viewsarglist(iccos); iccos << ") {" << endl << indent << " (void) new (home) " << spec._name << "(home, "; if (isNary) { iccos << "x"; } else { for (int i=0; i typestack; vector argstack; int arg = 0; for (int i=0; i i" << (++arg) << "(i" << a << ");" << endl; typestack.push_back("RangesCompl<"+t+" >"); argstack.push_back(arg); } break; case SetExprCode::INTER: { string t2 = typestack.back(); typestack.pop_back(); string t1 = typestack.back(); typestack.pop_back(); int a2 = argstack.back(); argstack.pop_back(); int a1 = argstack.back(); argstack.pop_back(); iccos << indent << "Iter::Ranges::Inter<" << t1 << ", " << t2 << " > i" << (++arg) << "(i" << a1 << ", i" << a2 << ");" << endl; typestack.push_back("Iter::Ranges::Inter<"+t1+", "+t2+" >"); argstack.push_back(arg); } break; case SetExprCode::UNION: { string t2 = typestack.back(); typestack.pop_back(); string t1 = typestack.back(); typestack.pop_back(); int a2 = argstack.back(); argstack.pop_back(); int a1 = argstack.back(); argstack.pop_back(); iccos << indent << "Iter::Ranges::Union<" << t1 << ", " << t2 << " > i" << (++arg) << "(i" << a1 << ", i" << a2 << ");" << endl; typestack.push_back("Iter::Ranges::Union<"+t1+", "+t2+" >"); argstack.push_back(arg); } break; case SetExprCode::GLB: case SetExprCode::LUB: { string bound; if (invert) { if (instrs[i] == SetExprCode::GLB) bound = "Lub"; else bound = "Glb"; } else { if (instrs[i] == SetExprCode::GLB) bound = "Glb"; else bound = "Lub"; } int a = argstack.back(); argstack.pop_back(); iccos << indent; if (nary() || views==SINGLE_VIEW) { iccos << bound << "Ranges i"; string ty = bound + "Ranges"; typestack.push_back(ty); } else { iccos << bound << "Ranges i"; stringstream s; s << a; string ty = bound + "Ranges i" << arg << "(i" << (arg-1) << ");" << endl; } return arg; } void ProjectorCompiler::allAssigned(std::ostream& os) { using namespace std; os << indent << "bool assigned=true;" << endl; if (nary()) { os << indent << "for (int i=_x.size(); i--;)" << endl; os << indent << " assigned = assigned && _x[i].assigned();" << endl; } else { for (int i=0; i 0 && glb[0] != SetExprCode::EMPTY) { iccos << indent << "{" << endl; ++indent; int arg = iterator(glb, false, true); iccos << indent << me_check; if (nary()) iccos << "_x[" << spec._ps[i].getIdx() << "]"; else iccos << "_x" << spec._ps[i].getIdx(); iccos << ".includeI(home, i" << arg << "));" << endl; --indent; iccos << indent << "}" << endl; } SetExprCode lub = spec._ps[i].getLub(); if (lub.size() > 0 && lub[0] != SetExprCode::UNIVERSE) { iccos << indent << "{" << endl; ++indent; int arg = iterator(lub); iccos << indent << me_check; if (nary()) iccos << "_x[" << spec._ps[i].getIdx() << "]"; else iccos << "_x" << spec._ps[i].getIdx(); iccos << ".intersectI(home, i" << arg << "));" << endl; --indent; iccos << indent << "}" << endl; } } switch (fixpoint) { case NO_FIX: iccos << indent << "return assigned ? ES_SUBSUMED(this,home) : ES_NOFIX;" << endl; break; case ITER_FIX: { --indent; iccos << indent << "}" << endl; allAssigned(iccos); iccos << indent << "return assigned ? ES_SUBSUMED(this,home) : ES_FIX;" << endl; } break; default: GECODE_NEVER; } --indent; iccos << indent << "}" << endl << endl; } if (spec._negated || spec._reified) { templatehead(iccos); iccos << indent << "ExecStatus" << endl << indent << spec._name; templateparams(); iccos << "::check(Space* home) {" << endl; ++indent; iccos << indent << "ExecStatus es = ES_SUBSUMED(this,home);" << endl; for (int i=spec._ps.size(); i--; ) { SetExprCode glb = spec._ps[i].getGlb(); if (glb.size() > 0 && glb[0] != SetExprCode::EMPTY) { iccos << indent << "{" << endl; ++indent; int arg = iterator(glb,true,true); iccos << indent; if (nary()) iccos << "LubRanges j(_x[" << spec._ps[i].getIdx() << "]);"; else if (views==SINGLE_VIEW) iccos << "LubRanges j(_x" << spec._ps[i].getIdx() << ");"; else iccos << "LubRanges j(x" << spec._ps[i].getIdx() << ");"; iccos << endl; iccos << indent << "if (!Iter::Ranges::subset(i" << arg << ",j)) return ES_FAILED;" << endl; iccos << indent << "while (i" << arg << "()) ++i" << arg << ";" << endl; if (nary()) iccos << indent << "if (i" << arg << ".size() > _x[" << i << "].cardMax())"; else iccos << indent << "if (i" << arg << ".size() > _x" << i << ".cardMax())"; iccos << endl; iccos << indent << " return ES_FAILED;" << endl; --indent; iccos << indent << "}" << endl; } SetExprCode lub = spec._ps[i].getLub(); if (lub.size() > 0 && lub[0] != SetExprCode::UNIVERSE) { iccos << indent << "{" << endl; ++indent; int arg = iterator(lub,true); iccos << indent; if (nary()) iccos << "GlbRanges j(_x[" << spec._ps[i].getIdx() << "]);"; else if (views==SINGLE_VIEW) iccos << "GlbRanges j(_x" << spec._ps[i].getIdx() << ");"; else iccos << "GlbRanges j(x" << spec._ps[i].getIdx() << ");"; iccos << endl; iccos << indent << "if (!Iter::Ranges::subset(j,i" << arg << ")) return ES_FAILED;" << endl; iccos << indent << "while (i" << arg << "()) ++i" << arg << ";" << endl; if (nary()) iccos << indent << "if (i" << arg << ".size() < _x[" << i << "].cardMin())"; else iccos << indent << "if (i" << arg << ".size() < _x" << i << ".cardMin())"; iccos << endl; iccos << indent << " return ES_FAILED;" << endl; --indent; iccos << indent << "}" << endl; } if (glb.size() > 0 && glb[0] != SetExprCode::EMPTY) { iccos << indent << "{" << endl; ++indent; int arg = iterator(glb,false,false); iccos << indent; if (nary()) iccos << "GlbRanges j(_x[" << spec._ps[i].getIdx() << "]);"; else if (views==SINGLE_VIEW) iccos << "GlbRanges j(_x" << spec._ps[i].getIdx() << ");"; else iccos << "GlbRanges j(_x" << spec._ps[i].getIdx() << ");"; iccos << endl; iccos << indent << "if (!Iter::Ranges::subset(i" << arg << ",j)) es = ES_FIX;" << endl; --indent; iccos << indent << "}" << endl; } if (lub.size() > 0 && lub[0] != SetExprCode::UNIVERSE) { iccos << indent << "{" << endl; ++indent; int arg = iterator(lub,false,true); iccos << indent; if (nary()) iccos << "LubRanges j(_x[" << spec._ps[i].getIdx() << "]);"; else if (views==SINGLE_VIEW) iccos << "LubRanges j(_x" << spec._ps[i].getIdx() << ");"; else iccos << "LubRanges j(_x" << spec._ps[i].getIdx() << ");"; iccos << endl; iccos << indent << "if (!Iter::Ranges::subset(j,i" << arg << ")) es = ES_FIX;" << endl; --indent; iccos << indent << "}" << endl; } } iccos << indent << "return es;" << endl; --indent; iccos << indent << "}" << endl << endl; templatehead(iccos); iccos << indent << "ExecStatus" << endl << indent << spec._name; templateparams(); iccos << "::propagateNegative(Space* home) {" << endl; ++indent; iccos << indent << "switch (ExecStatus es=check(home)) {" << endl; iccos << indent << "case ES_FAILED: return ES_SUBSUMED(this,home);" << endl; iccos << indent << "case ES_SUBSUMED(this,home): return ES_FAILED;" << endl; iccos << indent << "default: return es;" << endl; iccos << indent << "}" << endl; --indent; iccos << indent << "}" << endl << endl; } templatehead(iccos); iccos << indent << "ExecStatus" << endl << indent << spec._name; templateparams(); iccos << "::propagate(Space* home, ModEventDelta) {" << endl; ++indent; if (spec._negated && ! spec._reified) { iccos << indent << "return propagateNegative(home);" << endl; --indent; iccos << indent << "}" << endl; return; } if (spec._reified) { if (spec._negated) { iccos << indent << "if (_b.zero()) return propagatePositive(home);" << endl; iccos << indent << "if (_b.one()) return propagateNegative(home);" << endl; iccos << indent << "switch (check(home)) {" << endl; iccos << indent << "case ES_SUBSUMED(this,home):" << endl; iccos << indent << " GECODE_ME_CHECK(_b.zero_none(home));" << endl; iccos << indent << " return ES_SUBSUMED(this,home);" << endl; iccos << indent << "case ES_FAILED:" << endl; iccos << indent << " GECODE_ME_CHECK(_b.one_none(home));" << endl; iccos << indent << " return ES_SUBSUMED(this,home);" << endl; iccos << indent << "default:" << endl; iccos << indent << " return ES_FIX;" << endl; iccos << indent << "}" << endl; --indent; iccos << indent << "}" << endl; } else { iccos << indent << "if (_b.one()) return propagatePositive(home);" << endl; iccos << indent << "if (_b.zero()) return propagateNegative(home);" << endl; iccos << indent << "switch (check(home)) {" << endl; iccos << indent << "case ES_SUBSUMED(this,home):" << endl; iccos << indent << " GECODE_ME_CHECK(_b.one_none(home));" << endl; iccos << indent << " return ES_SUBSUMED(this,home);" << endl; iccos << indent << "case ES_FAILED:" << endl; iccos << indent << " GECODE_ME_CHECK(_b.zero_none(home));" << endl; iccos << indent << " return ES_SUBSUMED(this,home);" << endl; iccos << indent << "default:" << endl; iccos << indent << " return ES_FIX;" << endl; iccos << indent << "}" << endl; --indent; iccos << indent << "}" << endl; } return; } iccos << indent << "return propagatePositive(home);" << endl; --indent; iccos << indent << "}" << endl; return; } ProjectorCompiler::ProjectorCompiler(std::ostream& _hhos, std::ostream& _iccos, const ProjectorPropagatorSpec& _spec) : hhos(_hhos), iccos(_iccos), spec(_spec), compiletest(false), fixpoint(NO_FIX), views(SINGLE_VIEW) {} void ProjectorCompiler::compile(void) { using namespace std; if (spec._arity < spec._ps.arity()) { /// TODO: Add proper error handling std::cerr << "Arity mismatch\n"; exit(2); } header(hhos); classdef(); footer(iccos); hhos << endl; header(iccos); standardMemberFunctions(); iccos << endl; propagation(); footer(iccos); } } // STATISTICS: set-prop