[gecode-users] Branching and FlatZincGecode

Morten Boysen boysen at itu.dk
Tue Jan 27 23:30:26 CET 2009


Hi Guido

Thank you very much for the reply. I do have some follow-up questions:

>> 3) I want to make a branching that follows the standard "fail-first"
>> heuristic, that is, choose the value with the smallest domain possible
>> and then use a special value heuristic. As I understand I need to
>> implement a branching for the integer variables in the FlatZincGecode
>> space and a branching for the boolean variables. If I understand it
>> correctly, this means the search will process all integer variables
>> first and then the boolean variables or vice verse, depending on the
>> order the branching were posted to the space (the branching posted first
>> is tested first). Is this correct?
> 
> Yes, that's right.  For your own branching, you can reuse the 
> ViewValBranching class, and instantiate it with the BySizeMin view 
> selector class and your own value selector.  Then you can add support 
> for that branching to the FlatZinc parser in gecode.cc, in the function 
> parseSolveAnn.  That's also the place where you can disable the default 
> branching.  Let us know if you need more help.

Earlier I was advised not to use the ViewValBranching class, but to 
implement the complete branching (I originally implemented this 
branching a couple of months ago, but never got around to make it work). 
  It works now, but I am a bit unsure whether it is as efficient as the 
standard Gecode branchings (The IConfigurator class can be seen as a 
black-box, where we can get a set from with some values. We want to find 
a value, that is not in this set):

class BranchingIntegers : public Gecode::Branching
{
public:

   virtual const BranchingDesc* description(const Space* home) const;

   virtual bool status(const Space* home) const;
   virtual ExecStatus commit(Space* home,
                             const BranchingDesc* d,
                             unsigned int a);

   // Copy a BranchingIntegers object.
   virtual Actor* copy(Space *home, bool share);

   // Add the branching strategy to the space home,
   // where the home has the IntVarArgs vars
   static void post( Space* home, IntVarArgs vars, IConfigurator* conf );

private:
   static const int POS_BEGIN = -1;
   static const int VAL_BEGIN = -1;

   const IConfigurator& configurator;

   Gecode::ViewArray<Gecode::Int::IntView> vars;
   mutable int pos; // TODO: Is this neeeded?
   mutable int val; // TODO: Is this neeeded?

   BranchingIntegers(Space* home,
                     ViewArray<Int::IntView>& xv,
                     const IConfigurator& conf);

   BranchingIntegers(Space* home, bool share, BranchingIntegers& b);
};


BranchingIntegers::BranchingIntegers(Space* home, 	
                                      ViewArray<Int::IntView>& xv,
                                      const IConfigurator& conf)
   : Branching( home ),
     vars( xv ),
     configurator( conf ),
     pos( POS_BEGIN ),
     val( VAL_BEGIN )
{ }


BranchingIntegers::BranchingIntegers(Space* home,
                                      bool share,
                                      BranchingIntegers& b)
   : Branching(home, share, b),
     configurator(b.configurator),
     pos(b.pos),
     val(b.val)
{
   vars.update(home, share, b.vars);
}

// What does this do???
const BranchingDesc* BranchingIntegers::description(const Space*) const
{
   assert( pos != POS_BEGIN && pos < vars.size() );
   return new PosValDesc<int,2>(this, pos, val);
}

// Compute the variable and value to branch on
bool BranchingIntegers::status(const Space* home) const
{
   // First we find the variable to branch one, using the standard
   // fail-first heuristic where the variable with the smallest domain is
   // chosen. This is done by iterating over all variable, checking
   // if they have been assigned, and if not, then we check whether the
   // domain of the variable is smaller than the smallest seen so far. If
   // it is, we choose the new one. There is no tiebreaking as the
   // first variable occuring with the smallest domain is used.
   int smallest_domain = numeric_limits<int>::max();

   for ( int i = 0; i < vars.size(); ++i ) {
     if ( !vars[i].assigned() ) {
       if ( vars[i].size() < smallest_domain ) {
         pos = i;
         smallest_domain = vars[i].size();
       }
     }
   }
   if ( pos == POS_BEGIN ) {
     // No non-assigned variables left
     return false;
   }

   // When the variable has been detected we need to find a value that
   // does not have support. In case several values does not have
   // support, we choose the first one. If all values have support
   // we choose the first one in the domain.

   // Get the valid domains computed so far for variable
   // we are dealing with.
   const set<int>& valid = configurator.getValidIntegerDomain( pos );

   // Iterate over the values in the view and take the
   // first one not found to be valid
   Int::ViewValues<Int::IntView> vals( vars[pos] );
   val = vals.val();
   while ( vals() ) {
     if ( valid.find( vals.val() ) == valid.end() ) {
       // This value has not been found to be valid yet, so use it.
       val = vals.val();
       return true;
     }
     ++vals;
   }

   // If we reach here, all values were supported,
   // so use the first one in the domain.
   return true;
}

ExecStatus BranchingIntegers::commit(Space *home,
                                      const BranchingDesc* d,
                                      unsigned int a)
{
   const PosValDesc<int,2> *desc =
     static_cast<const PosValDesc<int,2>*>( d );
   pos = POS_BEGIN;
   val = VAL_BEGIN;
   if ( a ) {
     return me_failed( vars[desc->pos()].nq( home, desc->val() ) )
                       ? ES_FAILED : ES_OK;
   }
   else {
     return me_failed( vars[desc->pos()].eq( home, desc->val() ) )
                       ? ES_FAILED : ES_OK;
   }
}

// Copy a BranchingIntegers object.
Actor* BranchingIntegers::copy(Space *home, bool share)
{
   return new (home) BranchingIntegers(home, share, *this);
}

// Add the branching strategy to the space home,
// where the home has the IntVarArgs vars
void BranchingIntegers::post( Space* home,
                               IntVarArgs vars,
                               IConfigurator* conf )
{
   ViewArray<Int::IntView> xv( home, vars );
   (void) new (home) BranchingIntegers( home, xv, *conf );
}

Kind regards
Morten




More information about the gecode-users mailing list