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

org.chocosolver.solver.constraints.nary.alldifferent.PropAllDiffInst 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) 2023, 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.nary.alldifferent;

import gnu.trove.stack.array.TIntArrayStack;

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.variables.IntVar;
import org.chocosolver.solver.variables.events.IntEventType;
import org.chocosolver.util.ESat;
import org.chocosolver.util.objects.setDataStructures.iterable.IntIterableRangeSet;

import java.util.stream.IntStream;

/**
 * Propagator for AllDifferent that only reacts on instantiation
 *
 * @author Charles Prud'homme
 */
public class PropAllDiffInst extends Propagator {

    protected static class FastResetArrayStack extends TIntArrayStack{
        void resetQuick(){
            this._list.resetQuick();
        }
    }

    protected final int n;
    protected FastResetArrayStack toCheck = new FastResetArrayStack();

    //***********************************************************************************
    // CONSTRUCTORS
    //***********************************************************************************

    /**
     * AllDifferent constraint for integer variables
     * enables to control the cardinality of the matching
     *
     * @param variables array of integer variables
     */
    public PropAllDiffInst(IntVar[] variables) {
        super(variables, PropagatorPriority.UNARY, true);
        n = vars.length;
    }


    //***********************************************************************************
    // INFO
    //***********************************************************************************

    @Override
    public int getPropagationConditions(int vIdx) {
        return IntEventType.instantiation();
    }

    //***********************************************************************************
    // PROPAGATION
    //***********************************************************************************

    @Override
    public void propagate(int evtmask) throws ContradictionException {
//        toCheck.clear();
        toCheck.resetQuick();
        for (int v = 0; v < n; v++) {
            if (vars[v].isInstantiated()) {
                toCheck.push(v);
            }
        }
        fixpoint();
    }

    @Override
    public void propagate(int varIdx, int mask) throws ContradictionException {
//        toCheck.clear();
        toCheck.resetQuick();
        toCheck.push(varIdx);
        fixpoint();
    }

    protected void fixpoint() throws ContradictionException {
        while (toCheck.size() > 0) {
            int vidx = toCheck.pop();
            int val = vars[vidx].getValue();
            for (int i = 0; i < n; i++) {
                if (i != vidx) {
                    if (vars[i].removeValue(val, this) && vars[i].isInstantiated()) {
                        toCheck.push(i);
                    }
                }
            }
        }
    }


    @Override
    public ESat isEntailed() {
        int nbInst = 0;
        for (int i = 0; i < n; i++) {
            if (vars[i].isInstantiated()) {
                nbInst++;
                for (int j = i + 1; j < n; j++) {
                    if (vars[j].isInstantiatedTo(vars[i].getValue())) {
                        return ESat.FALSE;
                    }
                }
            }
        }
        if (nbInst == vars.length) {
            return ESat.TRUE;
        }
        return ESat.UNDEFINED;
    }

    /**
     * Find in the implication graph and add in the explanation one instantiation event to the value t
     * @param t value
     */
    private void explainEqualExistit(ExplanationForSignedClause e, int[] indexes, int t){
        for (int i : indexes)  {
            if (vars[i].isInstantiatedTo(t)){
                vars[i].unionLit(e.complement(vars[i]), e);
                break;
            }
        }
    }
    /**
     * @implSpec
     * This version of alldiff algo only reacts on instantiation.
     * So, the explaining algorithm should also be basic, and only infer on instantiation.
     * 

* First, from Dx and Dx', resp. the domain of x before and after propagation, deduce the values removed. * Then, scan other variables and store those that intersect the set of values. * Fill the clause with stored variables only. *

*

* Optionally, since this propagator can filter multiple variables in one loop, a good approach is to * go back in the implication graph as much as possible. *

* */ @Override public void explain(int p,ExplanationForSignedClause e) { IntVar pivot = e.readVar(p); int[] X = IntStream.rangeClosed(0, vars.length - 1).filter(i->vars[i]!=pivot).toArray(); switch (e.readMask(p)) { case 1://REMOVE IntIterableRangeSet dbef = e.domain(pivot); dbef.removeAll(e.readDom(p)); int t = dbef.min(); explainEqualExistit(e, X, t); IntIterableRangeSet set = e.universe(); set.remove(t); pivot.intersectLit(set, e); break; case 2://INCLOW case 4://DECUPP case 8://INSTANTIATE case 0://VOID case 6://BOUND inclow+decup default: throw new UnsupportedOperationException("Unknown event type for explanation"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy