/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * Guido Tack * * Copyright: * Christian Schulte, 2004 * Guido Tack, 2004 * * Last modified: * $Date: 2008-08-20 15:55:47 +0200 (Wed, 20 Aug 2008) $ by $Author: tack $ * $Revision: 7658 $ * * 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. * */ namespace Gecode { /** * \defgroup TaskBranchViewVal Generic branching based on view and value selection * * Implements view-based branching for an array of views and value. * \ingroup TaskActor */ //@{ /// Status returned by member functions of view selection class enum ViewSelStatus { VSS_NONE, ///< Current view is not better VSS_SELECT, ///< Current view is better VSS_COMMIT ///< Current view is known to be a best one }; /** * \brief Generic branching * * Implements view-based branching for an array of views (of type * \a View) and value (of type \a Val). The behaviour is defined by * the class \a ViewSel (which view is selected for branching) * and the class \a ValSel (which value is selected for branching). * * The class \a ViewSel must implement two member functions: * - Gecode::ViewSelStatus init(const Space* \a home, \a View \a x) * Initializes view selection with the \a View \a x. If \a x * is known to be a best one, VSS_COMMIT should be returned. * Otherwise, either VSS_NONE or VSS_SELECT should be returned. * - Gecode::ViewSelStatus select(const Space* \a home, \a View \a x) * If \a x is not better than the previously selected view, * return VSS_NONE. If it is better, return VSS_SELECT. If * it is a best view, return VSS_COMMIT. * * The class \a ValSel must implement two member functions: * - \a Val val(const Space* \a home, View \a x) const * returns the value (most likely determined by \a x) to branch with. * - Gecode::ModEvent tell(Space* \a home, unsigned int \a a, \a View \a x, \a Val \a n) * performs a tell for alternative \a a on \a x with value \a n. * * For examples, see \link int/branch.hh integer branchings \endlink. */ template class ViewValBranching : public Branching { protected: ViewArray x; ///< Views to branch on mutable int start; ///< Unassigned views start at x[start] /// Constructor for cloning \a b ViewValBranching(Space* home, bool share, ViewValBranching& b); public: /// Constructor for creation ViewValBranching(Space* home, ViewArray& x); /// Check status of branching, return true if alternatives left virtual bool status(const Space* home) const; /// Return branching description (of type Gecode::PosValDesc) virtual const BranchingDesc* description(const Space* home) const; /// Perform commit for branching description \a d and alternative \a a virtual ExecStatus commit(Space* home, const BranchingDesc* d, unsigned int a); /// Return specification for this branching given a variable map \a m virtual Reflection::ActorSpec spec(const Space* home, Reflection::VarMap& m) const; /// Return specification for a branch virtual Reflection::BranchingSpec branchingSpec(const Space* home, Reflection::VarMap& m, const BranchingDesc* d) const; /// Actor type identifier of this branching static Support::Symbol ati(void); /// Post branching according to specification static void post(Space* home, Reflection::VarMap& m, const Reflection::ActorSpec& spec); /// Perform cloning virtual Actor* copy(Space* home, bool share); }; /** * \brief Generic assignment * * Implements view-based assignment for an array of views (of type * \a View) and value (of type \a Val). The behaviour is defined by * the class \a ValSel (which value is selected for assignment). * * The class \a ValSel must implement two member functions: * - \a Val val(const Space* \a home, View \a x) const * returns the value (most likely determined by \a x) to branch with. * - Gecode::ModEvent tell(Space* \a home, unsigned int a, \a View \a x, \a Val \a n) * performs a tell on \a x with value \a n (the value for \a a is * always 0, it is present such that assignments can use the same * value selection as branchings). * * For examples, see \link int/branch.hh integer branchings \endlink. */ template class ViewValAssignment : public Branching { protected: ViewArray x; ///< Views to branch on mutable int start; ///< Unassigned views start at x[start] /// Constructor for cloning \a b ViewValAssignment(Space* home, bool share, ViewValAssignment& b); public: /// Constructor for creation ViewValAssignment(Space* home, ViewArray& x); /// Check status of branching, return true if alternatives left virtual bool status(const Space* home) const; /// Return branching description (of type Gecode::PosValDesc) virtual const BranchingDesc* description(const Space* home) const; /// Perform commit for branching description \a d and alternative \a a virtual ExecStatus commit(Space* home, const BranchingDesc* d, unsigned int a); /// Return specification for this assignment given a variable map \a m virtual Reflection::ActorSpec spec(const Space* home, Reflection::VarMap& m) const; /// Return specification for a branch virtual Reflection::BranchingSpec branchingSpec(const Space* home, Reflection::VarMap& m, const BranchingDesc* d) const; /// Actor type identifier of this assignment static Support::Symbol ati(void); /// Post assignment according to specification static void post(Space* home, Reflection::VarMap& m, const Reflection::ActorSpec& spec); /// Perform cloning virtual Actor* copy(Space* home, bool share); }; /** * \brief %Branching descriptions storing position and value * * The maximal number of alternatives is defined by \a alt. */ template class PosValDesc : public BranchingDesc { protected: /// Position of view const int _pos; /// Value to assign to const Val _val; public: /** \brief Initialize description for branching \a b, position \a p, value \a n, and start position \a s. * * The start position can be used in the commit function to eliminate * assigned variables from the array. */ PosValDesc(const Branching* b, const int p, const Val& n); /// Return position in array int pos(void) const; /// Return value to branch with Val val(void) const; /// Report size occupied virtual size_t size(void) const; }; //@} /* * Branching descriptions with position and value * */ template forceinline PosValDesc::PosValDesc(const Branching* b, const int p, const Val& n) : BranchingDesc(b,alt), _pos(p), _val(n) {} template forceinline int PosValDesc::pos(void) const { return _pos; } template forceinline Val PosValDesc::val(void) const { return _val; } template size_t PosValDesc::size(void) const { return sizeof(PosValDesc); } /* * Generic branching based on variable/value selection * */ template forceinline ViewValBranching ::ViewValBranching(Space* home, ViewArray& x0) : Branching(home), x(x0), start(0) {} template forceinline ViewValBranching ::ViewValBranching(Space* home, bool share, ViewValBranching& b) : Branching(home,share,b), start(b.start) { x.update(home,share,b.x); } template Actor* ViewValBranching::copy(Space* home, bool share) { return new (home) ViewValBranching(home,share,*this); } template bool ViewValBranching ::status(const Space*) const { for (int i=start; i < x.size(); i++) if (!x[i].assigned()) { start = i; return true; } return false; } template const BranchingDesc* ViewValBranching ::description(const Space* home) const { assert(!x[start].assigned()); ViewSel vs; // For view selection ValSel vl; // For value selection int i = start; int b = i++; if (vs.init(home,x[b]) != VSS_COMMIT) for (; i < x.size(); i++) if (!x[i].assigned()) switch (vs.select(home,x[i])) { case VSS_SELECT: b=i; break; case VSS_COMMIT: b=i; goto create; case VSS_NONE: break; default: GECODE_NEVER; } create: return new PosValDesc(this,b,vl.val(home,x[b])); } template ExecStatus ViewValBranching ::commit(Space* home, const BranchingDesc* d, unsigned int a) { const PosValDesc* pvd = static_cast*>(d); ValSel vs; return me_failed(vs.tell(home,a,x[pvd->pos()],pvd->val())) ? ES_FAILED : ES_OK; } template Support::Symbol ViewValBranching::ati(void) { return Reflection::mangle("Gecode::ViewValBranching"); } template void ViewValBranching ::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(1); ViewArray x(home, vars, spec[0]); (void) new (home) ViewValBranching(home, x); } template Reflection::ActorSpec ViewValBranching::spec(const Space* home, Reflection::VarMap& m) const { Reflection::ActorSpec s(ati()); return s << x.spec(home, m); } template Reflection::BranchingSpec ViewValBranching::branchingSpec(const Space* home, Reflection::VarMap& m, const BranchingDesc* d) const { Reflection::BranchingSpec bs(d); const PosValDesc* pvd = static_cast*>(d); ValSel vs; vs.branchingSpec(home, m, bs, 2, x[pvd->pos()], pvd->val()); return bs; } /* * Generic assignment based on value selection * */ template forceinline ViewValAssignment ::ViewValAssignment(Space* home, ViewArray& x0) : Branching(home), x(x0), start(0) {} template forceinline ViewValAssignment ::ViewValAssignment(Space* home, bool share, ViewValAssignment& b) : Branching(home,share,b), start(b.start) { x.update(home,share,b.x); } template Actor* ViewValAssignment::copy(Space* home, bool share) { return new (home) ViewValAssignment(home,share,*this); } template bool ViewValAssignment ::status(const Space*) const { for (int i=start; i < x.size(); i++) if (!x[i].assigned()) { start = i; return true; } return false; } template const BranchingDesc* ViewValAssignment ::description(const Space* home) const { assert(!x[start].assigned()); ValSel vl; // For value selection return new PosValDesc(this,start,vl.val(home,x[start])); } template ExecStatus ViewValAssignment ::commit(Space* home, const BranchingDesc* d, unsigned int) { const PosValDesc* pvd = static_cast*>(d); ValSel vs; return me_failed(vs.tell(home,0,x[pvd->pos()],pvd->val())) ? ES_FAILED : ES_OK; } template Support::Symbol ViewValAssignment::ati(void) { return Reflection::mangle("Gecode::ViewValAssignment"); } template void ViewValAssignment ::post(Space* home, Reflection::VarMap& vars, const Reflection::ActorSpec& spec) { spec.checkArity(1); ViewArray x(home, vars, spec[0]); (void) new (home) ViewValAssignment(home, x); } template Reflection::ActorSpec ViewValAssignment::spec(const Space* home, Reflection::VarMap& m) const { Reflection::ActorSpec s(ati()); return s << x.spec(home, m); } template Reflection::BranchingSpec ViewValAssignment::branchingSpec(const Space* home, Reflection::VarMap& m, const BranchingDesc* d) const { Reflection::BranchingSpec bs(d); const PosValDesc* pvd = static_cast*>(d); ValSel vs; vs.branchingSpec(home, m, bs, 1, x[pvd->pos()], pvd->val()); return bs; } } // STATISTICS: kernel-other