Пример #1
0
 /// Post a distinct-linear constraint on variables \a x with sum \a c
 void distinctlinear(Cache& dc, const IntVarArgs& x, int c,
                     const SizeOptions& opt) {
   int n=x.size();
   if (opt.model() == MODEL_DECOMPOSE) {
     if (n < 8)
       linear(*this, x, IRT_EQ, c, opt.icl());
     else if (n == 8)
       rel(*this, x, IRT_NQ, 9*(9+1)/2 - c);
     distinct(*this, x, opt.icl());
   } else {
     switch (n) {
     case 0:
       return;
     case 1:
       rel(*this, x[0], IRT_EQ, c);
       return;
     case 8:
       // Prune the single missing digit
       rel(*this, x, IRT_NQ, 9*(9+1)/2 - c);
       break;
     case 9:
       break;
     default:
       if (c == n*(n+1)/2) {
         // sum has unique decomposition: 1 + ... + n
         rel(*this, x, IRT_LQ, n);
       } else if (c == n*(n+1)/2 + 1) {
         // sum has unique decomposition: 1 + ... + n-1 + n+1
         rel(*this, x, IRT_LQ, n+1);
         rel(*this, x, IRT_NQ, n);
       } else if (c == 9*(9+1)/2 - (9-n)*(9-n+1)/2) {
         // sum has unique decomposition: (9-n+1) + (9-n+2) + ... + 9
         rel(*this, x, IRT_GQ, 9-n+1);
       } else if (c == 9*(9+1)/2 - (9-n)*(9-n+1)/2 + 1) {
         // sum has unique decomposition: (9-n) + (9-n+2) + ... + 9
         rel(*this, x, IRT_GQ, 9-n);
         rel(*this, x, IRT_NQ, 9-n+1);
       } else {
         extensional(*this, x, dc.get(n,c));
         return;
       }
     }
     distinct(*this, x, opt.icl());
   }
 }
Пример #2
0
  /// The actual model
  GraphColor(const SizeOptions& opt)
    : g(opt.size() == 1 ? g2 : g1),
      v(*this,g.n_v,0,g.n_v),
      m(*this,0,g.n_v) {
    rel(*this, v, IRT_LQ, m);
    for (int i = 0; g.e[i] != -1; i += 2)
      rel(*this, v[g.e[i]], IRT_NQ, v[g.e[i+1]]);

    const int* c = g.c;
    for (int i = *c++; i--; c++)
      rel(*this, v[*c], IRT_EQ, i);
    while (*c != -1) {
      int n = *c;
      IntVarArgs x(n); c++;
      for (int i = n; i--; c++)
        x[i] = v[*c];
      distinct(*this, x, opt.icl());
      if (opt.model() == MODEL_CLIQUE)
        rel(*this, m, IRT_GQ, n-1);
    }
    branch(*this, m, INT_VAL_MIN);
    switch (opt.branching()) {
    case BRANCH_SIZE:
      branch(*this, v, INT_VAR_SIZE_MIN, INT_VAL_MIN);
      break;
    case BRANCH_DEGREE:
      branch(*this, v, tiebreak(INT_VAR_DEGREE_MAX,INT_VAR_SIZE_MIN),
             INT_VAL_MIN);
      break;
    case BRANCH_SIZE_DEGREE:
      branch(*this, v, INT_VAR_SIZE_DEGREE_MIN, INT_VAL_MIN);
      break;
    case BRANCH_SIZE_AFC:
      branch(*this, v, INT_VAR_SIZE_AFC_MIN, INT_VAL_MIN);
      break;
    default:
      break;
    }
  }
Пример #3
0
  /// Actual model
  AllInterval(const SizeOptions& opt) :
  	Script(opt),
    x(*this, opt.size(), 0, 66) { // 66 or opt.size() - 1
		const int n = x.size();
		
		IntVarArgs d(n-1);
		IntVarArgs dd(66);
		IntVarArgs xx_(n); // pitch class for AllInterval Chords 
		IntVar douze;
        Rnd r(1U);
		
	if ((opt.model() == MODEL_SET) || (opt.model() == MODEL_SET_CHORD) || (opt.model() == MODEL_SSET_CHORD) ||(opt.model() == MODEL_SYMMETRIC_SET)) // Modele original : serie
		{
			// Set up variables for distance
			for (int i=0; i<n-1; i++)
				d[i] = expr(*this, abs(x[i+1]-x[i]), opt.ipl());
			
			// Constrain them to be between 1 and n-1
			dom(*this, d, 1, n-1); 
			dom(*this, x, 0, n-1); 
			
			if((opt.model() == MODEL_SET_CHORD) || (opt.model() == MODEL_SSET_CHORD))
			{
				/*expr(*this,dd[0]==0);
				// Set up variables for distance
				for (int i=0; i<n-1; i++)
				{
					 expr(*this, dd[i+1] == (dd[i]+d[i])%12, opt.icl());
				}
				
				// Constrain them to be between 1 and n-1
				dom(*this, dd,0, n-1); 
				distinct(*this, dd, opt.icl());
				 */
				
				rel(*this, abs(x[0]-x[n-1]) == 6, opt.ipl());
				
				
			}
		 
			
			if(opt.symmetry())
			{
				// Break mirror symmetry (renversement)
				rel(*this, x[0], IRT_LE, x[1]);
				// Break symmetry of dual solution (retrograde de la serie) -> 1928 solutions pour accords de 12 sons
				rel(*this, d[0], IRT_GR, d[n-2]);
			}
			//series symetriques
			if ((opt.model() == MODEL_SYMMETRIC_SET)|| (opt.model() == MODEL_SSET_CHORD))
			{
				rel (*this, d[n/2 - 1] == 6); // pivot = triton
				for (int i=0; i<(n/2)-2; i++)
					rel(*this,d[i]+d[n-i-2]==12);
			}
		}
				
else 			
		{
			for (int j=0; j<n; j++)
				xx_[j] = expr(*this, x[j] % 12);
			
			dom(*this, xx_, 0, 11);
			distinct(*this, xx_, opt.ipl());
			
			//intervalles
			for (int i=0; i<n-1; i++)
				d[i] =  expr(*this,x[i+1] - x[i],opt.ipl());
			dom(*this, d, 1, n-1); 
			
			
			dom(*this, x, 0, n * (n - 1) / 2.); 
			
			//d'autres choses dont on est certain (contraintes redondantes) :
			
			rel(*this, x[0] == 0);
			rel(*this, x[n-1] ==  n * (n - 1) / 2.);
			
			//  break symmetry of dual solution (renversement de l'accord) 
			if(opt.symmetry())
				rel(*this, d[0], IRT_GR, d[n-2]);
			
			//accords symetriques
			if (opt.model() == MODEL_SYMMETRIC_CHORD)
			{
				rel (*this, d[n/2 - 1] == 6); // pivot = triton
				for (int i=0; i<(n/2)-2; i++)
					rel(*this,d[i]+d[n-i-2]==12);
			}
			if (opt.model() == MODEL_PARALLEL_CHORD)
			{
				rel (*this, d[n/2 - 1] == 6); // pivot = triton
				for (int i=0; i<(n/2)-2; i++)
					rel(*this,d[i]+d[n/2 + i]==12);
			}
		}

		distinct(*this, x, opt.ipl());
		distinct(*this, d, opt.ipl());
#if 0		
		//TEST
		IntVarArray counter(*this,12,0,250);
		IntVar testcounter(*this,0,250);
		
		for (int i=1; i<11; i++) {
			count(*this, d, i,IRT_EQ,testcounter,opt.icl()); // OK
		}
		
		count(*this, d, counter,opt.icl()); // OK
#endif
		//END TEST
		
		if(opt.branching() == 0)
			branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_SPLIT_MIN());
		else 
			branch(*this, x, INT_VAR_RND(r), INT_VAL_RND(r));		
	}
Пример #4
0
  /// The actual model
  GraphColor(const SizeOptions& opt)
    : IntMinimizeScript(opt),
      g(opt.size() == 1 ? g2 : g1),
      v(*this,g.n_v,0,g.n_v-1),
      m(*this,0,g.n_v-1) {
    rel(*this, v, IRT_LQ, m);
    for (int i = 0; g.e[i] != -1; i += 2)
      rel(*this, v[g.e[i]], IRT_NQ, v[g.e[i+1]]);

    const int* c = g.c;
    for (int i = *c++; i--; c++)
      rel(*this, v[*c], IRT_EQ, i);
    while (*c != -1) {
      int n = *c;
      IntVarArgs x(n); c++;
      for (int i = n; i--; c++)
        x[i] = v[*c];
      distinct(*this, x, opt.icl());
      if (opt.model() == MODEL_CLIQUE)
        rel(*this, m, IRT_GQ, n-1);
    }
    /// Branching on the number of colors
    branch(*this, m, INT_VAL_MIN());
    if (opt.symmetry() == SYMMETRY_NONE) {
       /// Branching without symmetry breaking
       switch (opt.branching()) {
          case BRANCH_SIZE:
             branch(*this, v, INT_VAR_SIZE_MIN(), INT_VAL_MIN());
             break;
          case BRANCH_DEGREE:
             branch(*this, v, tiebreak(INT_VAR_DEGREE_MAX(),INT_VAR_SIZE_MIN()),
                   INT_VAL_MIN());
             break;
          case BRANCH_SIZE_DEGREE:
             branch(*this, v, INT_VAR_DEGREE_SIZE_MAX(), INT_VAL_MIN());
             break;
          case BRANCH_SIZE_AFC:
             branch(*this, v, INT_VAR_AFC_SIZE_MAX(opt.decay()), INT_VAL_MIN());
             break;
          case BRANCH_SIZE_ACTIVITY:
             branch(*this, v, INT_VAR_ACTIVITY_SIZE_MAX(opt.decay()), INT_VAL_MIN());
             break;
          default:
             break;
       }
    } else { // opt.symmetry() == SYMMETRY_LDSB
       /// Branching while considering value symmetry breaking
       /// (every permutation of color values gives equivalent solutions)
       Symmetries syms;
       syms << ValueSymmetry(IntArgs::create(g.n_v,0));
       switch (opt.branching()) {
          case BRANCH_SIZE:
             branch(*this, v, INT_VAR_SIZE_MIN(), INT_VAL_MIN(), syms);
             break;
          case BRANCH_DEGREE:
             branch(*this, v, tiebreak(INT_VAR_DEGREE_MAX(),INT_VAR_SIZE_MIN()),
                   INT_VAL_MIN(), syms);
             break;
          case BRANCH_SIZE_DEGREE:
             branch(*this, v, INT_VAR_DEGREE_SIZE_MAX(), INT_VAL_MIN(), syms);
             break;
          case BRANCH_SIZE_AFC:
             branch(*this, v, INT_VAR_AFC_SIZE_MAX(opt.decay()), INT_VAL_MIN(), syms);
             break;
          case BRANCH_SIZE_ACTIVITY:
             branch(*this, v, INT_VAR_ACTIVITY_SIZE_MAX(opt.decay()), INT_VAL_MIN(), syms);
             break;
          default:
             break;
       }
    }
  }
Пример #5
0
  /// Actual model
  Steiner(const SizeOptions& opt)
    : n(opt.size()), noOfTriples((n*(n-1))/6),
      triples(*this, noOfTriples, IntSet::empty, 1, n, 3, 3) {

    for (int i=0; i<noOfTriples; i++) {
      for (int j=i+1; j<noOfTriples; j++) {
        SetVar x = triples[i];
        SetVar y = triples[j];

        SetVar atmostOne(*this,IntSet::empty,1,n,0,1);
        rel(*this, (x & y) == atmostOne);

        IntVar x1(*this,1,n);
        IntVar x2(*this,1,n);
        IntVar x3(*this,1,n);
        IntVar y1(*this,1,n);
        IntVar y2(*this,1,n);
        IntVar y3(*this,1,n);

        if (opt.model() == MODEL_NONE) {
          /* Naive alternative:
           * just including the ints in the set
           */
          rel(*this, singleton(x1) <= x);
          rel(*this, singleton(x2) <= x);
          rel(*this, singleton(x3) <= x);
          rel(*this, singleton(y1) <= y);
          rel(*this, singleton(y2) <= y);
          rel(*this, singleton(y3) <= y);

        } else if (opt.model() == MODEL_MATCHING) {
          /* Smart alternative:
           * Using matching constraints
           */

          channelSorted(*this, IntVarArgs()<<x1<<x2<<x3, x);
          channelSorted(*this, IntVarArgs()<<y1<<y2<<y3, y);
        } else if (opt.model() == MODEL_SEQ) {
          SetVar sx1 = expr(*this, singleton(x1));
          SetVar sx2 = expr(*this, singleton(x2));
          SetVar sx3 = expr(*this, singleton(x3));
          SetVar sy1 = expr(*this, singleton(y1));
          SetVar sy2 = expr(*this, singleton(y2));
          SetVar sy3 = expr(*this, singleton(y3));
          sequence(*this,SetVarArgs()<<sx1<<sx2<<sx3,x);
          sequence(*this,SetVarArgs()<<sy1<<sy2<<sy3,y);
        }

        /* Breaking symmetries */
        rel(*this, x1 < x2);
        rel(*this, x2 < x3);
        rel(*this, x1 < x3);

        rel(*this, y1 < y2);
        rel(*this, y2 < y3);
        rel(*this, y1 < y3);

        linear(*this, IntArgs(6,(n+1)*(n+1),n+1,1,-(n+1)*(n+1),-(n+1),-1), 
               IntVarArgs()<<x1<<x2<<x3<<y1<<y2<<y3, IRT_LE, 0);
      }
    }

    branch(*this, triples, SET_VAR_NONE, SET_VAL_MIN_INC);
  }
Пример #6
0
 queens(const SizeOptions& opt) : q(*this, 2*opt.size() - 1, -opt.size(), 2*opt.size() - 1) {
     // construct the variables
     const int n = opt.size();
     const int varSize = 2*n - 1;
     
     // stores all possible values for the determined key
     map< int, set<int> > allPossibleValueMap;
     
     // set the domains for the variables
     for (int index = 0; index < varSize; ++index) {
         int i = 1 - n + index;
         int end = varSize - abs(i);
         
         // the set stores all the possible values for q[index]
         set<int> possibleValueSet;
         possibleValueSet.insert(-n);
         for (int element = abs(i) + 1; element <= end; element += 2) {
             possibleValueSet.insert(element);
         }
         allPossibleValueMap.insert(make_pair(index, possibleValueSet));
         
         for (int position = -n + 1; position <= 2*n - 1; ++position) {
             if (!possibleValueSet.count(position)) {
                 rel(*this, q[index] != position);
             }
         }
     }
     
     // the first and second constraints
     // the number of (yi != -n) is n,
     // which equals that the number of (yi == -n) is n - 1
     count(*this, q, -n, IRT_EQ, n - 1);
     for (int j = 1; j <= varSize; ++j) {
         count(*this, q, j, IRT_LQ, 1);
     }
     
     // the third constraint, use three models
     switch (opt.model()) {
         // the arithmetic constraint
         case MODEL_ONE: {
             for (int indexI = 0; indexI < varSize; ++indexI) {
                 for (int indexJ = indexI + 1; indexJ < varSize; ++indexJ) {
                     rel(*this, abs(q[indexI] - q[indexJ]) != abs(indexI - indexJ));
                 }
             }
             break;
         }
         
         // the tuple sets constraint
         case MODEL_TWO: {
             // initialize the iterator map to iteratively add tuples
             map<int, set<int>::const_iterator> setIterator;
             map<int, set<int>::const_iterator> iteEnd;
             for (int index = 0; index < varSize; ++index) {
                 set<int>::const_iterator ite = allPossibleValueMap[index].begin();
                 setIterator.insert(make_pair(index, ite));
                 
                 set<int>::const_iterator endIte = allPossibleValueMap[index].end();
                 iteEnd.insert(make_pair(index, endIte));
             }
             
             // stores all the tuples to be added
             TupleSet allTupleSet;
             
             // this iterator is used to detect end conditions
             set<int>::const_iterator firstIteEnd = iteEnd[0];
             const int lastIndex = varSize - 1;
             // test all the possible tuples, then add the valid ones which satisfy the third constraint into tuple set
             while (setIterator[0] != firstIteEnd) {
                 // stores each tuple
                 IntArgs tuple;
                 
                 // use to detect whether a tuple is valid
                 vector<int> tupleVec;
                 bool validFlag = true;
                 for (int index = 0; index < varSize; ++index) {
                     set<int>::const_iterator ite = setIterator[index];
                     int value = *ite;
                     if (tupleVec.empty()) {
                         tupleVec.push_back(value);
                         tuple << value;
                     } else {
                         // using the third constraint, if a new value doesn't satisfy the constraint, skip this tuple
                         for (int vecIndex = 0; vecIndex < tupleVec.size(); ++vecIndex) {
                             if (abs(index - vecIndex) == abs(tuple[vecIndex] -  value)) {
                                 validFlag = false;
                                 break;
                             }
                         }
                         if (validFlag == true) {
                             tupleVec.push_back(value);
                             tuple << value;
                         } else {
                             break;
                         }
                     }
                 }
                 
                 // if it is valid then add this tuple
                 if (validFlag == true) {
                     allTupleSet.add(tuple);
                 }
                 
                 // try next possible tuple
                 ++setIterator[lastIndex];
                 if (setIterator[lastIndex] == iteEnd[lastIndex]) {
                     setIterator[lastIndex] = allPossibleValueMap[lastIndex].begin();
                     for (int index = lastIndex - 1; index >= 0; --index) {
                         ++setIterator[index];
                         if (setIterator[index] != iteEnd[index]) {
                             break;
                         } else if (index != 0) {
                             setIterator[index] = allPossibleValueMap[index].begin();
                         }
                     }
                 }
             }
             allTupleSet.finalize();
             
             extensional(*this, q, allTupleSet);
             
             break;
         }
             
         // the DFAs constraint
         case MODEL_THREE: {
             // use the third constraint to test every pair of two variables
             for (int index = 0; index < varSize; ++index) {
                 // all the possible value for the first variable
                 set<int> valueSet1 = allPossibleValueMap[index];
                 for (int subIndex = index + 1; subIndex < varSize; ++subIndex) {
                     // use for testing
                     cout << index << endl;
                     cout << subIndex << endl;
                     
                     // stores the transition status.
                     DFA::Transition *t = new DFA::Transition[2*n*n];
                     
                     // use this index to set the transition values
                     int transitionIndex = 0;
                     
                     // key: transition state, value: the first variable's value
                     map<int, int> transitionMap;
                     
                     // get transtion states {0, value1, 2}, {0, value2, 3}...
                     for (set<int>::const_iterator set1Ite = valueSet1.begin(); set1Ite != valueSet1.end(); ++set1Ite) {
                         t[transitionIndex] = {0, *set1Ite, transitionIndex + 2};
                         transitionMap.insert(make_pair(transitionIndex + 2, *set1Ite));
                         ++transitionIndex;
                     }
                     
                     //all the possible value for the second variable
                     set<int> valueSet2 = allPossibleValueMap[subIndex];
                     
                     // tests every state, if the second variable satisfy the third constraint, then add the variable into the transition
                     for (map<int, int>::const_iterator mapIte = transitionMap.begin(); mapIte != transitionMap.end(); ++mapIte) {
                         for (set<int>::const_iterator set2Ite = valueSet2.begin(); set2Ite != valueSet2.end(); ++set2Ite) {
                             if (abs(index - subIndex) != abs(mapIte->second -  *set2Ite)) {
                                 t[transitionIndex] = {mapIte->first, *set2Ite, 1};
                                 ++transitionIndex;
                             }
                         }
                     }
                     t[transitionIndex] = {-1, 0, 0};
                     
                     // use 1 as the final state
                     int f[] = {1, -1};
                     DFA d(0, t, f);
                     cout << d << endl;
                     IntVarArgs x;
                     x << q[index] << q[subIndex];
                     extensional(*this, x, d);
                     delete[] t;
                 }
             }
             
             break;
         }
             
         default:
             break;
     }
     
     // post branching
     branch(*this, q, INT_VAR_SIZE_MIN(), INT_VAL_SPLIT_MIN());
 }