@Override public ESat isEntailed() { boolean possibleTrue = PropUtil.isKerSubsetEnv(result, consequent) && PropUtil.isKerSubsetEnv(consequent, result); boolean possibleFalse = PropUtil.isKerSubsetEnv(result, alternative) && PropUtil.isKerSubsetEnv(alternative, result); if (!possibleTrue && !possibleFalse) { return ESat.FALSE; } if (antecedent.isInstantiated()) { if (antecedent.getValue() == 1) { if (!possibleTrue) { return ESat.FALSE; } return result.isInstantiated() && consequent.isInstantiated() ? ESat.TRUE : ESat.UNDEFINED; } else { if (!possibleFalse) { return ESat.FALSE; } return result.isInstantiated() && alternative.isInstantiated() ? ESat.TRUE : ESat.UNDEFINED; } } if (possibleTrue && possibleFalse && result.isInstantiated() && consequent.isInstantiated() && alternative.isInstantiated()) { return ESat.TRUE; } return ESat.UNDEFINED; }
@Override public void propagate(int evtmask) throws ContradictionException { if (!antecedent.isInstantiated()) { if (!PropUtil.isKerSubsetEnv(result, consequent) || !PropUtil.isKerSubsetEnv(consequent, result)) { antecedent.instantiateTo(0, this); } else if (!PropUtil.isKerSubsetEnv(result, alternative) || !PropUtil.isKerSubsetEnv(alternative, result)) { antecedent.instantiateTo(1, this); } else { ISetIterator iter = result.getUB().iterator(); while (iter.hasNext()) { int i = iter.nextInt(); if (!consequent.getUB().contains(i) && !alternative.getUB().contains(i)) { result.remove(i, this); } else if (consequent.getLB().contains(i) && alternative.getLB().contains(i)) { result.force(i, this); } } } } if (antecedent.isInstantiated()) { if (antecedent.getValue() == 1) { PropUtil.envSubsetEnv(result, consequent, this); PropUtil.envSubsetEnv(consequent, result, this); PropUtil.kerSubsetKer(result, consequent, this); PropUtil.kerSubsetKer(consequent, result, this); } else { PropUtil.envSubsetEnv(result, alternative, this); PropUtil.envSubsetEnv(alternative, result, this); PropUtil.kerSubsetKer(result, alternative, this); PropUtil.kerSubsetKer(alternative, result, this); } } }
@Test(groups = "1s", timeOut = 60000) public void test14() { Model model = new Model(); BoolVar a = model.boolVar("a"); BoolVar b = model.boolVar("b"); LogOp l = LogOp.or(a, b, a.not(), a.not()); ILogical ll = LogicTreeToolBox.toCNF(l, model); Assert.assertEquals(ll.toString(), "cste -- 1 = 1"); }
@Test(groups = "1s", timeOut = 60000) public void test11() { Model model = new Model(); BoolVar a = model.boolVar("a"); BoolVar b = model.boolVar("b"); LogOp l = LogOp.or(LogOp.and(a, b.not()), LogOp.and(a.not(), b), LogOp.and(a.not(), b.not())); ILogical ll = LogicTreeToolBox.toCNF(l, model); Assert.assertEquals(ll.toString(), "(not(b) or not(a))"); }
@Test(groups = "1s", timeOut = 60000) public void test9() { Model model = new Model(); BoolVar a = model.boolVar("a"); BoolVar na = a.not(); BoolVar b = model.boolVar("b"); BoolVar c = model.boolVar("c"); BoolVar d = model.boolVar("d"); LogOp root = LogOp.and(a, b, na, c, d); ILogical l = LogicTreeToolBox.toCNF(root, model); Assert.assertEquals(l.toString(), "cste -- 0 = 0"); }
@Test(groups = "1s", timeOut = 60000) public void test8() { Model model = new Model(); BoolVar a = model.boolVar("a"); BoolVar na = a.not(); BoolVar b = model.boolVar("b"); BoolVar nb = b.not(); BoolVar c = model.boolVar("c"); BoolVar d = model.boolVar("d"); LogOp root = LogOp.and(LogOp.or(a, b, na), LogOp.or(c, d), LogOp.or(b, nb)); ILogical l = LogicTreeToolBox.toCNF(root, model); Assert.assertEquals(l.toString(), "(c or d)"); }
/** * create a logical connection between ``b`` and ``tree``. * * @param b operand * @param tree operand * @return a logical operator */ public static LogOp reified(BoolVar b, ILogical tree) { try { BoolVar nb = b.not(); ILogical ntree = negate(tree); return or(and(b, tree), and(nb, ntree)); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; }
@Test(groups = "1s", timeOut = 60000) public void test17() { Model model = new Model(); IntVar a = model.intVar("a", -1, 1, false); BoolVar b1 = model.boolVar("b1"); BoolVar b2 = model.boolVar("b2"); model.arithm(a, "=", 0).reifyWith(b1); model.arithm(a, ">", 0).reifyWith(b2); model.addClauses(new BoolVar[0], new BoolVar[] {b1, b2}); model.getMinisat().getPropSat().initialize(); try { model.getSolver().propagate(); b1.instantiateTo(1, Cause.Null); model.getSolver().propagate(); } catch (ContradictionException ex) { Assert.fail(); } Assert.assertTrue(b1.isInstantiatedTo(1)); Assert.assertTrue(b2.isInstantiatedTo(0)); Assert.assertTrue(a.isInstantiatedTo(0)); }
/** * 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); }