(!****************************************************************
   CP example problems
   ===================
   
   file tracereverse2.mos
   ``````````````````````
   Tracing the values of reversible numbers.
   - Specifying callback routines by name -

   (c) 2010 Artelys S.A. and Fair Isaac Corporation
       Creation: 2010, rev. Mar. 2013        
*****************************************************************!)
model "Tracing reversible numbers"
 uses "kalis", "mmsystem"
 
 forward public procedure save_node_state
 forward public procedure branch_up
 forward public procedure branch_down

 declarations
   N = 5
   R = 1..N
   C: array(R) of integer

   x: array(R) of cpvar

   k,depth: cpreversible
   ka: cpreversiblearray
 end-declarations

 C::(1..5)[-7,15,-3,19,-45]

! Initialization: all reversible numbers at 0 
 set_reversible_attributes(depth, 0)
 set_reversible_attributes(k, 0)
 set_reversible_attributes(ka, 1, N, 0)
 
! Decision variables and constraints 
 forall(i in R) setdomain(x(i), 0, 1)
 sum(i in R) x(i) >= 3
 
 cp_set_node_callback("save_node_state")
 cp_set_branch_callback("branch_down", "branch_up")

 cp_set_branching(assign_var(KALIS_SMALLEST_DOMAIN, KALIS_MAX_TO_MIN))
 setparam("KALIS_MAX_SOLUTIONS", 3)
 while (cp_find_next_sol) do
  writeln(" "*2*round(depth.val), "Solution: ", x)
 end-do

!************ Callback functions ************
 public procedure save_node_state 
  setval(depth, getval(depth)+1)
  k.val:= sum(i in R) if(is_fixed(x(i)), C(i)*x(i).val, 0)
  forall(i in R) setelt(ka,i, if(is_fixed(x(i)), C(i)*x(i).val, 0))   
 end-procedure

 public procedure branch_up      
  writeln(textfmt(" "*2*round(depth.val)+ "up  ",-20), k, "\t", ka)    
 end-procedure

 public procedure branch_down      
  writeln(textfmt(" "*2*round(depth.val)+ "down  ",-20), k, "\t", ka)    
 end-procedure

end-model
