@Test
 public void test2() {
   Model s = new Model();
   IntVar a = s.intVar("a", 0, 32, true);
   IntVar b = s.intVar("b", 0, 48, true);
   double q = 1.5;
   s.post(new RoundedUpDivision(a, b, q));
   Assert.assertEquals(s.getSolver().findAllSolutions().size(), 49);
   // Assert.assertEquals(s.getNbSolutions(), 33);
 }
  /**
   * Make a new model.
   *
   * @param p the RP to use as a basis.
   * @param e the VM managed by the action
   * @throws org.btrplace.scheduler.SchedulerException if an error occurred
   */
  public RelocatableVM(ReconfigurationProblem p, VM e) throws SchedulerException {

    // Get vars
    vm = e;
    rp = p;
    src = rp.getSourceModel().getMapping().getVMLocation(e);
    org.chocosolver.solver.Model csp = rp.getModel();
    Model mo = rp.getSourceModel();

    // Default values
    start = rp.getStart();
    end = rp.getStart();
    duration = csp.intVar(0);
    state = csp.boolVar(true);

    // If not manageable, the VM stays on the current host
    if (!p.getManageableVMs().contains(e)) {
      stay = csp.boolVar(true);
      doReinstantiation = csp.boolVar(false);
      manageable = false;

      IntVar host = rp.makeCurrentHost(vm, PREFIX_STAY, vm, ").host");
      cSlice =
          new SliceBuilder(rp, vm, PREFIX_STAY, vm.toString(), ").cSlice")
              .setHoster(host)
              .setEnd(rp.makeUnboundedDuration(PREFIX_STAY, vm, ").cSlice_end"))
              .build();
      dSlice =
          new SliceBuilder(rp, vm, PREFIX_STAY, vm, ").dSlice")
              .setHoster(host)
              .setStart(cSlice.getEnd())
              .build();

      return;
    }

    // The VM can move (to re-instantiate or migrate) OR STAY to the same host
    stay = csp.boolVar(rp.makeVarLabel(vm, "stay"));
    cSlice =
        new SliceBuilder(rp, vm, PREFIX, vm, ").cSlice")
            .setHoster(rp.getNode(rp.getSourceModel().getMapping().getVMLocation(vm)))
            .setEnd(rp.makeUnboundedDuration(PREFIX, vm, ").cSlice_end"))
            .build();

    dSlice =
        new SliceBuilder(rp, vm, PREFIX, vm, ").dSlice")
            .setStart(rp.makeUnboundedDuration(PREFIX, vm, ").dSlice_start"))
            .build();

    // Update start and end vars of the action
    start = dSlice.getStart();
    end = cSlice.getEnd();

    csp.post(new Arithmetic(end, Operator.LE, rp.getEnd()));
    // Get some static durations from evaluators
    DurationEvaluators dev = rp.getDurationEvaluators();
    int migrateDuration = dev.evaluate(rp.getSourceModel(), MigrateVM.class, vm);
    int bootDuration = dev.evaluate(rp.getSourceModel(), org.btrplace.plan.event.BootVM.class, vm);
    int forgeD =
        p.getDurationEvaluators()
            .evaluate(p.getSourceModel(), org.btrplace.plan.event.ForgeVM.class, vm);

    // Compute the re-instantiation duration
    int reInstantiateDuration = bootDuration + forgeD;
    reInstantiateDuration = forgeD; // Compliant with CMaxOnlineTest and others

    // Get the networking view if attached
    Network network = Network.get(mo);
    IntVar migrationDuration;
    if (network != null) {

      // Set the migration algorithm
      postCopy = mo.getAttributes().get(vm, "postCopy", false);

      // Create unbounded/large domain vars for migration duration and bandwidth
      migrationDuration = p.makeUnboundedDuration("migration(", vm, ").duration");
      bandwidth = csp.intVar(PREFIX + vm + ").bandwidth", 0, Integer.MAX_VALUE / 100, true);
    }
    // No networking view, set the duration from the evaluator
    else {
      // The duration can still be 0 => the VM STAY !
      migrationDuration =
          csp.intVar(
              rp.makeVarLabel("migration(", vm, ").duration"), new int[] {0, migrateDuration});
      bandwidth = null;
    }

    // Possibly re-instantiate (if some attributes are defined)
    if (mo.getAttributes().get(vm, "clone", false) && mo.getAttributes().isSet(vm, "template")) {

      doReinstantiation = csp.boolVar(rp.makeVarLabel("relocation_method(", vm, ")"));

      duration =
          csp.intVar(
              rp.makeVarLabel(PREFIX, vm, ").duration"),
              Math.min(migrationDuration.getLB(), reInstantiateDuration),
              Math.max(migrationDuration.getUB(), reInstantiateDuration),
              true);

      // Re-instantiate or migrate
      // (Prefer the re-instantiation if the duration are the same, otherwise choose the min)
      rp.getModel()
          .ifThenElse(
              rp.getModel()
                  .or(
                      new Arithmetic(
                          doReinstantiation, Operator.EQ, 0), // can be instantiated externally !
                      new Arithmetic(migrationDuration, Operator.LT, reInstantiateDuration)),
              new Arithmetic(duration, Operator.EQ, migrationDuration),
              new Arithmetic(duration, Operator.EQ, reInstantiateDuration));

      // If it is a re-instantiation then specify that the dSlice must start AFTER the Forge delay
      IntVar time =
          csp.intVar(rp.makeVarLabel(doReinstantiation.getName(), " * ", forgeD), 0, forgeD, false);
      csp.post(csp.times(doReinstantiation, forgeD, time));
      csp.post(new Arithmetic(start, Operator.GE, time));
      // Be sure that doReinstantiation will be instantiated
      csp.post(new FastIFFEq(doReinstantiation, duration, reInstantiateDuration));
    }
    // The VM either migrate or stay but won't be re-instantiated for sure
    else {
      doReinstantiation = csp.boolVar(false);
      duration = migrationDuration;
    }

    // If the VM stay (src host == dst host), then duration = 0
    csp.post(new FastIFFEq(stay, dSlice.getHoster(), cSlice.getHoster().getValue()));
    csp.post(new FastIFFEq(stay, duration, 0));
    // We have to force the migration duration equals to 0 if it stays
    // otherwise, the variable will be free
    csp.post(new FastIFFEq(stay, migrationDuration, 0));

    // Create the task ('default' cumulative constraint with a height of 1)
    migrationTask = new Task(start, duration, end);
  }