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

org.openl.ie.constrainer.impl.IntExpCard Maven / Gradle / Ivy

There is a newer version: 5.27.9
Show newest version
package org.openl.ie.constrainer.impl;

import org.openl.ie.constrainer.*;

/**
 * An implementation of the expression: cardinality(IntExpArray).
 */
public final class IntExpCard extends IntExpImpl {
    /**
     * This is an Observer for min/max events on _possible_required variable: _possible_required.min() <= this.min() <=
     * this.max() <= _possible_required.max()
     */

    class ObserverIndexes extends Observer {

        @Override
        public Object master() {
            return IntExpCard.this;
        }

        @Override
        public int subscriberMask() {
            return EventOfInterest.MINMAX | EventOfInterest.REMOVE;
        }

        @Override
        public String toString() {
            return "ObserverIndexes";
        }

        @Override
        public void update(Subject var, EventOfInterest interest) throws Failure {
            // Debug.on();Debug.print("ObserverPossibleRequired
            // "+interest);Debug.off();

            // any _possible event may produce only decrease in size
            _possible_required.setMax(_indexes.size() - 1);

        }
    } // ~ ObserverPossibleRequired

    private final IntExpArray _vars;
    private final IntVar _possible_required;
    private final IntVarImpl _indexes;

    private final int _card_value;

    public IntExpCard(Constrainer constrainer, IntExpArray vars, int card_value) throws Failure {
        // super(constrainer,0,vars.size(),"C" + card_value,
        // IntVarImplTrace.TRACE_ALL);
        super(constrainer, "C" + card_value);
        _card_value = card_value;

        // int trace = IntVarImplTrace.TRACE_ALL;

        int size = vars.size();
        _vars = vars;

        _indexes = (IntVarImpl) constrainer()
            .addIntVarTraceInternal(0, size, "IX" + card_value, IntVar.DOMAIN_BIT_FAST);

        int required_instances = 0;
        for (int i = 0; i < size; i++) {
            IntExp exp = vars.get(i);
            if (exp.contains(card_value)) {
                if (exp.bound()) {
                    required_instances++;
                }
            } else {
                _indexes.removeValue(i);
            }

        }

        _possible_required = constrainer().addIntVarTraceInternal(required_instances,
            _indexes.size() - 1,
            "PR" + card_value,
            IntVar.DOMAIN_PLAIN
        );

        _indexes.attachObserver(new ObserverIndexes());

        // _possible_required.attachObserver(new ObserverPossibleRequired());
        // constrainer().trace(_possible_required);
        // constrainer().trace(this);

        // this.attachObserver(new ObserverCardValue());

    }

    public void addValueIndex(int idx) throws Failure {
        _possible_required.setMin(_possible_required.min() + 1);
    }

    @Override
    public void attachObserver(Observer observer) {
        super.attachObserver(observer);
        _possible_required.attachObserver(observer);
    }

    public void bindAll() throws Failure {
        IntExp.IntDomainIterator it = i -> {
            if (i == _vars.size()) {
                return true;
            }
            IntExp exp = _vars.get(i);
            exp.setValue(_card_value);
            return true;
        };

        _indexes.iterateDomain(it);
    }

    @Override
    public void detachObserver(Observer observer) {
        super.detachObserver(observer);
        _possible_required.detachObserver(observer);
    }

    /*
     * extending to 5.1.0 added by S. Vanskov
     */
    int get_cardinality_value() {
        return _card_value;
    }
    /* EO additions */

    @Override
    public int max() {
        return _possible_required.max();
    }

    @Override
    public int min() {
        return _possible_required.min();
    }

    @Override
    public void reattachObserver(Observer observer) {
        super.reattachObserver(observer);
        _possible_required.reattachObserver(observer);
    }

    public void removeIndex(int idx) throws Failure {
        _indexes.removeValue(idx);
    }

    public void removeUnbounds() throws Failure {
        IntExp.IntDomainIterator it = i -> {
            if (i == _vars.size()) {
                return true;
            }
            IntExp exp = _vars.get(i);
            if (!exp.bound()) {
                exp.removeValue(_card_value);
            }
            return true;
        };

        _indexes.iterateDomain(it);
    }

    @Override
    public void setMax(int max) throws Failure {
        if (max == min()) {
            removeUnbounds();
        }
    }

    @Override
    public void setMin(int min) throws Failure {
        if (min == max()) {
            bindAll();
        }
    }

    @Override
    public String toString() {
        return "(" + _possible_required + ":" + _indexes + ")";
    }

} // ~IntExpCard




© 2015 - 2024 Weber Informatics LLC | Privacy Policy