All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.btrplace.scheduler.choco.extensions.RoundedUpDivision Maven / Gradle / Ivy

/*
 * Copyright (c) 2016 University Nice Sophia Antipolis
 *
 * This file is part of btrplace.
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 */

package org.btrplace.scheduler.choco.extensions;


import org.chocosolver.solver.constraints.Constraint;
import org.chocosolver.solver.constraints.Propagator;
import org.chocosolver.solver.constraints.PropagatorPriority;
import org.chocosolver.solver.exception.ContradictionException;
import org.chocosolver.solver.variables.IntVar;
import org.chocosolver.solver.variables.events.IntEventType;
import org.chocosolver.util.ESat;

/**
 * A constraint to enforce {@code a == b / divider} where {@code divider} is a real and {@code a} and {@code b} are
 * both integers.
 * The division is rounded up to the smallest integer.
 * 

* In practice, the constraint maintains: *

    *
  • {@code a = Math.ceil(b / divider)}
  • *
  • {@code b = ((a - 1 )* divider) % 1 == 0 ? [(a - 1)*divider + 1; Math.floor(a * divider)] : [Math.ceil((a -1)*divider); Math.floor(a * divider)]}
  • *
* * @author Fabien Hermenier */ public class RoundedUpDivision extends Constraint { /** * Make a new constraint. * * @param a the variable to divide * @param b the resulting ratio * @param d the divider */ public RoundedUpDivision(IntVar a, IntVar b, double d) { super("RoundedUpDivision", new RoundedUpDivisionPropagator(a, b, d)); } static class RoundedUpDivisionPropagator extends Propagator { private double divider; /** * New propagator * * @param a the variable to divide * @param b the resulting ratio * @param d the divider */ public RoundedUpDivisionPropagator(IntVar a, IntVar b, double d) { super(new IntVar[]{a, b}, PropagatorPriority.BINARY, true); this.divider = d; } @Override public int getPropagationConditions(int vIdx) { return IntEventType.DECUPP.getMask() + IntEventType.INCLOW.getMask() + IntEventType.INSTANTIATE.getMask(); } @Override public ESat isEntailed() { if (vars[0].getDomainSize() == 1 && vars[1].getDomainSize() == 1) { return ESat.eval(vars[0].getValue() == (int) Math.ceil((double) vars[1].getValue() / divider)); } return ESat.UNDEFINED; } private int div(int b) { return (int) Math.ceil((double) b / divider); } private int multLB(int a) { if ((a - 1 * divider) % 1 == 0) { return (int) ((a - 1) * divider + 1); } return (int) Math.ceil(divider * (a - 1)); } @Override public void propagate(int evtMask) throws ContradictionException { filter(); if (vars[0].getLB() != div(vars[1].getLB()) || vars[0].getUB() != div(vars[1].getUB())) { this.contradiction(null, ""); } } private boolean filter() throws ContradictionException { boolean fix = awakeOnInf(0); fix |= awakeOnSup(0); fix |= awakeOnInf(1); fix |= awakeOnSup(1); return fix; } @Override public void propagate(int idx, int mask) throws ContradictionException { do { } while (filter()); } public boolean awakeOnInf(int i) throws ContradictionException { if (i == 1) { return vars[0].updateLowerBound(div(vars[1].getLB()), this); } return vars[1].updateLowerBound(multLB(vars[0].getLB()), this); } public boolean awakeOnSup(int i) throws ContradictionException { if (i == 1) { return vars[0].updateUpperBound(div(vars[1].getUB()), this); } return vars[1].updateUpperBound((int) Math.floor(divider * vars[0].getUB()), this); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy