Clone wiki

OscaR / cpmodelling

Your model should be in a class or an object extending the CPModel trait (equivalent to interface in Java). Let's define an object MyModel inside a file MyModel.scala with a main method in it:

import oscar.cp.modeling._
import oscar.cp.core._

object MyModel extends App {
    // put your model here
}

You can then create a new CPSolver object (let's call it cp). You then declare variables belonging to this solver by giving it a set or a range of values:

import oscar.cp.modeling._
import oscar.cp.core._

object MyModel extends App {
    val cp = CPSolver()
    val x1 = CPVarInt(cp,Set(1,5,9)) // Dom(x1) = {1,5,9} 
    val x2 = CPVarInt(cp,1 to 5)     // Dom(x2) = [1..5] 
    val x3 = CPVarInt(cp,1 until 5)  // Dom(x3) = [1..4] 
        
}

You are now ready to add constraints to your cp object is a solve block to find one solution (use solveAll to find them all). Note that each time you add a constraint with the method add you trigger the fix-point algorithm so that you can see immediately the propagation effect of adding this constraint.

import oscar.cp.modeling._
import oscar.cp.core._

object MyModel extends App {
     val cp = CPSolver()
     val x1 = CPVarInt(cp,Set(1,5,9)) // Dom(x1) = {1,5,9} 
     val x2 = CPVarInt(cp,1 to 5)     // Dom(x2) = [1..5] 
     val x3 = CPVarInt(cp,1 until 5)  // Dom(x3) = [1..4] 

     cp.solve {
         cp.add(x1 != x2)
         cp.add(x1 + x2 == x3)
     }
     
}

You are just missing one thing, the exploration of the DFS search tree. On the next example we use a binary-first fail DFS search on the array of variables [x1,x2,x3].

import oscar.cp.modeling._
import oscar.cp.core._

object MyModel extends App {
     val cp = CPSolver()
     val x1 = CPVarInt(cp,Set(1,5,9)) // Dom(x1) = {1,5,9} 
     val x2 = CPVarInt(cp,1 to 5)     // Dom(x2) = [1..5] 
     val x3 = CPVarInt(cp,1 until 5)  // Dom(x3) = [1..4] 

     cp.solve {
         cp.add(x1 != x2)
         cp.add(x1 + x2 == x3)
     } exploration {
         cp.binaryFirstFail(x1,x2)
         println("Solution found, value of x1 in this solution:" + x1.getValue())
     } run(1)
     
}

The run(1) is asking to run the exploration and stop as soon as the first solution is discovered. To find all the solutions, you can simply do run().

You can also solve an optimization (minimization/maximization) problem with CP (Branch and Bound search) by providing an objective function (CPVarInt). Here is how to do it:

object MyModel extends App {
     val cp = CPSolver()
     val x1 = CPVarInt(cp,Set(1,5,9)) // Dom(x1) = {1,5,9} 
     val x2 = CPVarInt(cp,1 to 5)     // Dom(x2) = [1..5] 
     val x3 = CPVarInt(cp,1 until 5)  // Dom(x3) = [1..4] 

     cp.maximize(x1+x3) subjectTo { // use maximize for maximization
     cp.add(x1 != x2)
        cp.add(x1 + x2 == x3)
     } exploration {
        cp.binaryFirstFail(x1,x2)
        println("Solution found, value of x1 in this solution:" + x1.getValue())
     } run()
}

OscaR support several global constraints, give a look at the api: constraints. Note also that most of the binary constraints are directly accessible from the CPVarInt api.

Updated