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

org.chocosolver.solver.constraints.reification.PropXltYCReif Maven / Gradle / Ivy

There is a newer version: 4.10.17
Show newest version
/*
 * This file is part of choco-solver, http://choco-solver.org/
 *
 * Copyright (c) 2019, IMT Atlantique. All rights reserved.
 *
 * Licensed under the BSD 4-clause license.
 *
 * See LICENSE file in the project root for full license information.
 */
package org.chocosolver.solver.constraints.reification;

import org.chocosolver.solver.constraints.Propagator;
import org.chocosolver.solver.constraints.PropagatorPriority;
import org.chocosolver.solver.exception.ContradictionException;
import org.chocosolver.solver.learn.ExplanationForSignedClause;
import org.chocosolver.solver.learn.Implications;
import org.chocosolver.solver.variables.BoolVar;
import org.chocosolver.solver.variables.IntVar;
import org.chocosolver.util.ESat;
import org.chocosolver.util.objects.ValueSortedMap;
import org.chocosolver.util.objects.setDataStructures.iterable.IntIterableRangeSet;

/**
 * A propagator dedicated to express in a compact way: (x < y + c) ⇔ b
 *
 * @author Charles Prud'homme
 * @since 03/05/2016.
 */
public class PropXltYCReif extends Propagator {

    int cste;

    public PropXltYCReif(IntVar x, IntVar y, int c, BoolVar r) {
        super(new IntVar[]{x, y, r}, PropagatorPriority.TERNARY, false);
        this.cste = c;
    }

    @Override
    public void propagate(int evtmask) throws ContradictionException {
        if (vars[2].getLB() == 1) {
            vars[0].updateUpperBound(vars[1].getUB() + cste - 1, this);
            vars[1].updateLowerBound(vars[0].getLB() - cste + 1, this);
            if (vars[0].getUB() < vars[1].getLB() + cste) {
                this.setPassive();
            }
        } else if (vars[2].getUB() == 0) {
            vars[0].updateLowerBound(vars[1].getLB() + cste, this);
            vars[1].updateUpperBound(vars[0].getUB() - cste, this);
            if (vars[0].getLB() >= vars[1].getUB() + cste) {
                setPassive();
            }
        } else {
            if (vars[0].getUB() < vars[1].getLB() + cste) {
                vars[2].instantiateTo(1, this);
                setPassive();
            } else if (vars[0].getLB() >= vars[1].getUB() + cste) {
                vars[2].instantiateTo(0, this);
                setPassive();
            }
        }
    }

    @Override
    public ESat isEntailed() {
        if(isCompletelyInstantiated()){
            if(vars[2].isInstantiatedTo(1)){
                return ESat.eval(vars[0].getValue() < vars[1].getValue() + cste);
            }else{
                return ESat.eval(vars[0].getValue() >= vars[1].getValue() + cste);
            }
        }
        return ESat.UNDEFINED;
    }

    /**
     * @implSpec
     *
     * Premise: (x < y + c) ⇔ b
     * 

* 6 cases here (only cases that triggered filtering are reported): *

    *
  1. *
         *      (b = [0,1] ∧ x ∈ (-∞, m] ∧ y ∈ [n, +∞) ∧ m < n + c) → b = 1
         *  
    *
         *      ⇔ (b = 1 ∨ x ∈ [n + c, +∞) ∨ y ∈ (-∞, n - 1])
         *  
    *
         *      (alt.) (b = 1 ∨ x ∈ [m + 1, +∞) ∨ y ∈ (-∞, m - c])
         *  
    *
  2. *
  3. *
         *      (b = [0,1] ∧ x ∈ [m, +∞) ∧ y ∈ (-∞,n] ∧ m ≥ n + c) → b = 0
         *  
    *
         *      ⇔ (b = 0 ∨ x ∈ (-∞, m - 1] ∨ y ∈ [m - t + 1,+∞))
         *  
    *
         *      (alt.) (b = 0 ∨ x ∈ (-∞,n + c - 1] ∨ y ∈ [n + 1, +∞))
         *  
    *
  4. *
  5. *
         *      (b = 1 ∧ x ∈ [m, +∞) ∧ y ∈ (-∞, +∞)) → y ∈ [m - c + 1, +∞)
         *  
    *
         *      ⇔ (b = 0 ∨ x ∈ (-∞, m-1] ∨ y ∈ [m - c + 1, +∞))
         *  
    *
  6. *
  7. *
         *      (b = 1 ∧ x ∈ (-∞, +∞) ∧ y ∈ (-∞, n]) → x ∈ (-∞, n + c - 1]
         *  
    *
         *      ⇔ (b = 0 ∨ x ∈ (-∞, n + c - 1] ∨ y ∈ [n + 1, +∞))
         *  
    *
  8. *
  9. *
         *      (b = 0 ∧ x ∈ (-∞,m] ∧ y ∈ (-∞, +∞)) → y ∈ (-∞,m - c]
         *  
    *
         *      ⇔ (b = 1 ∨ x ∈ [m + 1, +∞) ∨ y ∈ (-∞,m - c])
         *  
    *
  10. *
  11. *
         *      (b = 0 ∧ x ∈ (-∞, +∞) ∧ y ∈ [n, +∞)) → x ∈ [n + c, +∞)
         *  
    *
         *      ⇔ (b = 1 ∨ x ∈ [n + c, +∞) ∨ y ∈ (-∞,n - 1])
         *  
    *
  12. *
*

* * */ @Override public void explain(ExplanationForSignedClause explanation, ValueSortedMap front, Implications ig, int p) { IntVar pivot = ig.getIntVarAt(p); IntIterableRangeSet set0, set1; set0 = explanation.getRootSet(vars[0]); set1 = explanation.getRootSet(vars[1]); if (vars[2].isInstantiatedTo(1)) { // b is true and X < Y + c holds if (pivot == vars[2]) { // b is the pivot, case a. in javadoc explanation.addLiteral(vars[2], explanation.getFreeSet(1), true); // deal with alternatives if(front.getValue(vars[0]) > front.getValue(vars[1])){ int n = ig.getDomainAt(front.getValue(vars[1])).min(); set0.retainBetween(n+cste, IntIterableRangeSet.MAX); explanation.addLiteral(vars[0], set0, false); set1.retainBetween(IntIterableRangeSet.MIN, n - 1); explanation.addLiteral(vars[1], set1, false); }else{ int m = ig.getDomainAt(front.getValue(vars[0])).max(); set0.retainBetween(m+1, IntIterableRangeSet.MAX); explanation.addLiteral(vars[0], set0, false); set1.retainBetween(IntIterableRangeSet.MIN, m - cste); explanation.addLiteral(vars[1], set1, false); } } else if (pivot == vars[0]) { // x is the pivot, case d. in javadoc explanation.addLiteral(vars[2], explanation.getFreeSet(0), false); int n = ig.getDomainAt(front.getValue(vars[1])).max(); set0.retainBetween(IntIterableRangeSet.MIN, n + cste - 1); explanation.addLiteral(vars[0], set0, true); set1.retainBetween(n + 1, IntIterableRangeSet.MAX); explanation.addLiteral(vars[1], set1, false); } else if (pivot == vars[1]) { // y is the pivot, case c. in javadoc explanation.addLiteral(vars[2], explanation.getFreeSet(0), false); int m = ig.getDomainAt(front.getValue(vars[0])).min(); set0.retainBetween(IntIterableRangeSet.MIN, m - 1); explanation.addLiteral(vars[0], set0, false); set1.retainBetween(m - cste + 1, IntIterableRangeSet.MAX); explanation.addLiteral(vars[1], set1, true); } } else if (vars[2].isInstantiatedTo(0)) { if (pivot == vars[2]) { // b is the pivot, case b. in javadoc explanation.addLiteral(vars[2], explanation.getFreeSet(0), true); set0 = explanation.getRootSet(vars[0]); set1 = explanation.getRootSet(vars[1]); // deal with alternatives if(front.getValue(vars[0]) > front.getValue(vars[1])){ int n = ig.getDomainAt(front.getValue(vars[1])).max(); set0.retainBetween(IntIterableRangeSet.MIN, n + cste - 1); explanation.addLiteral(vars[0], set0, false); set1.retainBetween(n + 1, IntIterableRangeSet.MAX); explanation.addLiteral(vars[1], set1, false); }else{ int m = ig.getDomainAt(front.getValue(vars[0])).min(); set0.retainBetween(IntIterableRangeSet.MIN, m - 1); explanation.addLiteral(vars[0], set0, false); set1.retainBetween(m - cste + 1, IntIterableRangeSet.MAX); explanation.addLiteral(vars[1], set1, false); } } else if (pivot == vars[0]) { // x is the pivot, case f. in javadoc explanation.addLiteral(vars[2], explanation.getFreeSet(1), false); int n = ig.getDomainAt(front.getValue(vars[1])).min(); set0.retainBetween(n + cste, IntIterableRangeSet.MAX); explanation.addLiteral(vars[0], set0, true); set1.retainBetween(IntIterableRangeSet.MIN, n - 1); explanation.addLiteral(vars[1], set1, false); } else if (pivot == vars[1]) { // y is the pivot, case e. in javadoc explanation.addLiteral(vars[2], explanation.getFreeSet(1), false); int m = ig.getDomainAt(front.getValue(vars[0])).max(); set0.retainBetween(m + 1, IntIterableRangeSet.MAX); explanation.addLiteral(vars[0], set0, false); set1.retainBetween(IntIterableRangeSet.MIN, m - cste); explanation.addLiteral(vars[1], set1, true); } } else { throw new UnsupportedOperationException(); } } @Override public String toString() { return "(" + vars[0].getName() +" < " + vars[1].getName() + " + "+cste+") <=> "+vars[2].getName(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy