/*
  For more information about this file, see 
  "Choco: Constraint Programming i Java"
  http://www.hakank.org/webblogg/archives/001113.html
  


  Choco program for solving the furniture moving problem from
  Kim Marriot & Peter J Stuckey 'Programming with constraints', page 112f.

  Some furnitures should be moved. The tasks takes different resources (time
  and number of persons).

   Item     Time required    Number of people
   ------------------------------------------
   piano    30               3
   chair    10               1 
   bed      15               3
   table    15               2

  The problem is to assign time for each task. 

  Note: In the standard distribution only 5 solution is printed.

  You can change the number of solutions to print by altering the 
  following line in AbstractSolver.java:

     public int maxNbSolutionStored = 5;

  e.g. to
     public int maxNbSolutionStored = 50;

  Then recompile the source code for choco.
  
*/

import choco.Problem;
import choco.*;
import choco.integer.*;

import java.io.*;
import java.util.*;
import java.text.*;

public class FurnitureMoving {

    public static void main(String args[]) {

        Problem pb = new Problem();

        int NumPersons = 3;

        // define variables and their time limit (start time, end time)
        IntDomainVar Sp = pb.makeEnumIntVar("Sp", 0, 30); // Piano
        IntDomainVar Sc = pb.makeEnumIntVar("Sc", 0, 50); // Chair 
        IntDomainVar Sb = pb.makeEnumIntVar("Sb", 0, 45); // Bed
        IntDomainVar St = pb.makeEnumIntVar("St", 0, 45); // Table
        IntDomainVar SumStartTimes = pb.makeBoundIntVar("SumStartTimes", 0, 1000);

        // the start time
        IntVar[] starts = {Sp, Sc, Sb, St};

        // define variables for end times
        IntDomainVar SpEnd = pb.makeEnumIntVar("SpEnd", 0, 60);
        IntDomainVar ScEnd = pb.makeEnumIntVar("ScEnd", 0, 60);
        IntDomainVar SbEnd = pb.makeEnumIntVar("SbEnd", 0, 60);
        IntDomainVar StEnd = pb.makeEnumIntVar("StEnd", 0, 60);
        IntVar[] ends = {SpEnd, ScEnd, SbEnd, StEnd};


        // duration of tasks
        IntVar[] durations = new IntVar[4];
        int durationsInts[] = {30,10,15,15};
        for (int i = 0; i<durationsInts.length; i++) {
            durations[i] = pb.makeConstantIntVar("durations" + i, durationsInts[i]);
        }


        // the number of resources required
        int[] heights = {3,1,3,2};

        // the constraints
        pb.post(pb.cumulative(starts, ends, durations, heights, NumPersons));
        pb.post(pb.eq(pb.sum(starts), SumStartTimes));


        /* 
           These constraints minimimes the problem, which gives only one solution.
         */
        
        /*
          pb.minimize(SumStartTimes,false);
          pb.minimize(SpEnd,false);
          pb.minimize(ScEnd,false);
          pb.minimize(SbEnd,false);
          pb.minimize(StEnd,false);
        */


        Solver s = pb.getSolver();
        pb.solve(true); // true: all solutions, false: just the first solution

        // System.out.println(pb.pretty()); // prints first solution
        
        // Print some statistics
        System.out.println("Feasible: " + pb.isFeasible());
        if (pb.isFeasible() == Boolean.TRUE) {
          System.out.println("Number of solutions: " + s.getSearchSolver().solutions.size());
          System.out.println("nbSol: " + s.getNbSolutions());


          // print the result
          for (int sol = 0; sol < s.getSearchSolver().solutions.size(); sol++) {
            Solution ss = (Solution) s.getSearchSolver().solutions.get(sol);
            System.out.println("\nSolution:");
            
            System.out.println("Piano: " + ss.getValue(0)  + " - " + ss.getValue(5) + "(" + heights[0] + " pers) " + 
                               " Chair: " + ss.getValue(1) + " - " + ss.getValue(6) + "(" + heights[1] + " pers) " + 
                               " Bed: " + ss.getValue(2) + " - " + ss.getValue(7) + "(" + heights[2] + " pers) " + 
                               " Table: " + ss.getValue(3) + " - " + ss.getValue(8) + "(" + heights[3] + " pers)"
                               );
            System.out.println("SumStartTimes: " + ss.getValue(4));
          }
          
        } else {
          System.out.println("Problem is not feasible!");
        }
        

    } // end main

} // end class
