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

org.chocosolver.solver.constraints.IReificationFactory 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) 2022, 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;

import org.chocosolver.solver.ISelf;
import org.chocosolver.solver.Model;
import org.chocosolver.solver.constraints.reification.*;
import org.chocosolver.solver.search.SearchState;
import org.chocosolver.solver.variables.BoolVar;
import org.chocosolver.solver.variables.IntVar;
import org.chocosolver.util.ESat;
import org.chocosolver.util.objects.setDataStructures.iterable.IntIterableRangeSet;

/**
 * Interface to reify constraints
 *
 * A kind of factory relying on interface default implementation to allow (multiple) inheritance
 *
 * @author Jean-Guillaume FAGES
 * @since 4.0.0
 */
public interface IReificationFactory extends ISelf {

	//***********************************************************************************
	// Non-reifiable reification constraints
	//***********************************************************************************

	/**
	 * Posts a constraint ensuring that if ifCstr is satisfied, then thenCstr must be satisfied as well
	 * Otherwise, elseCstr must be satisfied
	 *
	 * ifCstr => ThenCstr
	 * not(ifCstr) => ElseCstr
	 *
	 * BEWARE : it is automatically posted (it cannot be reified)
	 *
	 * @param ifCstr a constraint
	 * @param thenCstr a constraint
	 * @param elseCstr a constraint
	 */
	default void ifThenElse(Constraint ifCstr, Constraint thenCstr, Constraint elseCstr){
		ifThenElse(ifCstr.reify(), thenCstr, elseCstr);
	}

	/**
	 * Posts an implication constraint: ifVar => thenCstr && not(ifVar) => elseCstr.
	 * 
* Ensures: *

- ifVar = 1 => thenCstr is satisfied,
*

- ifVar = 0 => elseCstr is satisfied,
*

- thenCstr is not satisfied => ifVar = 0
*

- elseCstr is not satisfied => ifVar = 1
*

*

In order to get ifVar <=> thenCstr, use reification * * BEWARE : it is automatically posted (it cannot be reified) * * @param ifVar variable of reification * @param thenCstr the constraint to be satisfied when ifVar = 1 * @param elseCstr the constraint to be satisfied when ifVar = 0 */ default void ifThenElse(BoolVar ifVar, Constraint thenCstr, Constraint elseCstr) { ifThen(ifVar,thenCstr); ifThen(ifVar.not(),elseCstr); } /** * Posts a constraint ensuring that if ifCstr is satisfied, then thenCstr is satisfied as well * * BEWARE : it is automatically posted (it cannot be reified) * * @param ifCstr a constraint * @param thenCstr a constraint */ default void ifThen(Constraint ifCstr, Constraint thenCstr) { ifThen(ifCstr.reify(), thenCstr); } /** * Posts an implication constraint: ifVar => thenCstr * Also called half reification constraint * Ensures:
*

- ifVar = 1 => thenCstr is satisfied,
*

- thenCstr is not satisfied => ifVar = 0
*

* Example :
* - ifThen(b1, arithm(v1, "=", 2));: * b1 is equal to 1 => v1 = 2, so v1 != 2 => b1 is equal to 0 * But if b1 is equal to 0, nothing happens * * BEWARE : it is automatically posted (it cannot be reified) *

* * @param ifVar variable of reification * @param thenCstr the constraint to be satisfied when ifVar = 1 */ default void ifThen(BoolVar ifVar, Constraint thenCstr) { // PRESOLVE if(ifVar.contains(1)){ if(ifVar.isInstantiated()) { thenCstr.post(); }else if(thenCstr.isSatisfied() == ESat.FALSE) { ref().arithm(ifVar, "=", 0).post(); } // END OF PRESOLVE else { ref().arithm(ifVar, "<=", thenCstr.reify()).post(); } } } /** * Posts an equivalence constraint stating that * cstr1 is satisfied <=> cstr2 is satisfied, * * BEWARE : it is automatically posted (it cannot be reified) * * @param cstr1 a constraint to be satisfied if and only if cstr2 is satisfied * @param cstr2 a constraint to be satisfied if and only if cstr1 is satisfied */ default void ifOnlyIf(Constraint cstr1, Constraint cstr2){ reification(cstr1.reify(),cstr2); } /** * Reify a constraint with a boolean variable: * var = 1 <=> cstr is satisfied, * * Equivalent to ifOnlyIf * * BEWARE : it is automatically posted (it cannot be reified) * * @param var variable of reification * @param cstr the constraint to be satisfied if and only if var = 1 */ default void reification(BoolVar var, Constraint cstr){ // PRESOLVE ESat entail = cstr.isSatisfied(); if(var.isInstantiatedTo(1)) { cstr.post(); }else if(var.isInstantiatedTo(0)) { cstr.getOpposite().post(); }else if(entail == ESat.TRUE) { ref().arithm(var, "=", 1).post(); }else if(entail == ESat.FALSE) { ref().arithm(var, "=", 0).post(); } // END OF PRESOLVE else { cstr.reifyWith(var); } } /** * Posts one constraint that expresses : (x = c) ⇔ b. * Bypasses the reification system. * @param X a integer variable * @param C an int * @param B a boolean variable */ default void reifyXeqC(IntVar X, int C, BoolVar B){ // no check to allow addition during resolution if(ref().getSolver().getSearchState() == SearchState.NEW){ if(X.isInstantiatedTo(C)){ ref().arithm(B, "=", 1).post(); return; }else if(!X.contains(C)) { ref().arithm(B, "=", 0).post(); return; } } ref().post(new Constraint(ConstraintsName.BASIC_REI, new PropXeqCReif(X, C, B))); } /** * Posts one constraint that expresses : (x ≠ c) ⇔ b. * Bypasses the reification system. * @param X a integer variable * @param C an int * @param B a boolean variable */ default void reifyXneC(IntVar X, int C, BoolVar B){ // no check to allow addition during resolution reifyXeqC(X, C, B.not()); } /** * Posts one constraint that expresses : (x = y) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param B a boolean variable */ default void reifyXeqY(IntVar X, IntVar Y, BoolVar B){ if(X.isAConstant()){ reifyXeqC(Y, X.getValue(), B); }else if(Y.isAConstant()){ reifyXeqC(X, Y.getValue(), B); }else { // no check to allow addition during resolution ref().post(new Constraint(ConstraintsName.BASIC_REI, new PropXeqYCReif(X, Y, 0, B))); } } /** * Posts one constraint that expresses : (x ≠ y) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param B a boolean variable */ default void reifyXneY(IntVar X, IntVar Y, BoolVar B){ if(X.isAConstant()){ reifyXneC(Y, X.getValue(), B); }else if(Y.isAConstant()){ reifyXneC(X, Y.getValue(), B); }else { // no check to allow addition during resolution reifyXeqY(X, Y, B.not()); } } /** * Posts one constraint that expresses : (x = y + c) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param C an int * @param B a boolean variable */ default void reifyXeqYC(IntVar X, IntVar Y, int C, BoolVar B){ if(X.isAConstant()){ reifyXeqC(Y, X.getValue() - C, B); }else if(Y.isAConstant()){ reifyXeqC(X, Y.getValue() + C, B); }else { // no check to allow addition during resolution ref().post(new Constraint(ConstraintsName.BASIC_REI, new PropXeqYCReif(X, Y, C, B))); } } /** * Posts one constraint that expresses : (x ≠ y + c) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param C an int * @param B a boolean variable */ default void reifyXneYC(IntVar X, IntVar Y, int C, BoolVar B){ if(X.isAConstant()){ reifyXneC(Y, X.getValue() - C, B); }else if(Y.isAConstant()){ reifyXneC(X, Y.getValue() + C, B); }else { // no check to allow addition during resolution reifyXeqYC(X, Y, C, B.not()); } } /** * Posts one constraint that expresses : (x < c) ⇔ b. * Bypasses the reification system. * @param X a integer variable * @param C an int * @param B a boolean variable */ default void reifyXltC(IntVar X, int C, BoolVar B){ // no check to allow addition during resolution if(ref().getSolver().getSearchState() == SearchState.NEW){ if(X.getUB() < C){ ref().arithm(B, "=", 1).post(); return; }else if(X.getLB() >= C) { ref().arithm(B, "=", 0).post(); return; } } ref().post(new Constraint(ConstraintsName.BASIC_REI, new PropXltCReif(X, C, B))); } /** * Posts one constraint that expresses : (x > c) ⇔ b. * Bypasses the reification system. * @param X a integer variable * @param C an int * @param B a boolean variable */ default void reifyXgtC(IntVar X, int C, BoolVar B){ // no check to allow addition during resolution reifyXltC(X, C + 1, B.not()); } /** * Posts one constraint that expresses : (x < y) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param B a boolean variable */ default void reifyXltY(IntVar X, IntVar Y, BoolVar B){ if(X.isAConstant()){ reifyXgtC(Y, X.getValue(), B); }else if(Y.isAConstant()){ reifyXltC(X, Y.getValue(), B); }else { // no check to allow addition during resolution reifyXltYC(X, Y, 0, B); } } /** * Posts one constraint that expresses : (x > y) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param B a boolean variable */ default void reifyXgtY(IntVar X, IntVar Y, BoolVar B){ reifyXltYC(X, Y, 1, B.not()); } /** * Posts one constraint that expresses : (x ≤ y) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param B a boolean variable */ default void reifyXleY(IntVar X, IntVar Y, BoolVar B){ // no check to allow addition during resolution reifyXltYC(X, Y, 1, B); } /** * Posts one constraint that expresses : (x ≥ y) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param B a boolean variable */ default void reifyXgeY(IntVar X, IntVar Y, BoolVar B){ // no check to allow addition during resolution reifyXltYC(X, Y, 0, B.not()); } /** * Posts one constraint that expresses : (x < y + c) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param C an int * @param B a boolean variable */ default void reifyXltYC(IntVar X, IntVar Y, int C, BoolVar B){ // no check to allow addition during resolution if(X.isAConstant()){ reifyXgtC(Y, X.getValue() - C, B); }else if(Y.isAConstant()){ reifyXltC(X, Y.getValue() + C, B); }else { ref().post(new Constraint(ConstraintsName.BASIC_REI, new PropXltYCReif(X, Y, C, B))); } } /** * Posts one constraint that expresses : (x > y + c) ⇔ b. * Bypasses the reification system. * @param X an integer variable * @param Y an integer variable * @param C an int * @param B a boolean variable */ default void reifyXgtYC(IntVar X, IntVar Y, int C, BoolVar B){ // no check to allow addition during resolution reifyXltYC(X, Y, C+1, B.not()); } /** * Posts one constraint that expresses : (X ∈ S) ⇔ B. * Bypasses the reification system. * @param X an integer variable * @param S a set of values * @param B a boolean variable */ default void reifyXinS(IntVar X, IntIterableRangeSet S, BoolVar B){ // no check to allow addition during resolution ref().post(new Constraint(ConstraintsName.BASIC_REI, new PropXinSReif(X, S, B))); } /** * Posts one constraint that expresses : (X ∉ S) ⇔ B. * Bypasses the reification system. * @param X an integer variable * @param S a set of values * @param B a boolean variable */ default void reifyXnotinS(IntVar X, IntIterableRangeSet S, BoolVar B){ // no check to allow addition during resolution ref().post(new Constraint(ConstraintsName.BASIC_REI, new PropXinSReif(X, S, B.not()))); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy