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

org.openl.ie.constrainer.impl.IntExpAddArray1 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: sum(IntExpArray). This implementation "remember and propagate"
 * setMin/Max.
 */
public final class IntExpAddArray1 extends IntExpImpl {
    final class DomainVar extends IntVarImpl {
        public DomainVar(Constrainer c, int min, int max) {
            super(c, min, max, "", DOMAIN_PLAIN);
        }

        @Override
        public void propagate() throws Failure {
            enforceDomainC();
        }

    } // ~DomainVar

    class ExpAddVectorObserver extends Observer {

        ExpAddVectorObserver() {
            // super(event_map);
        }

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

        @Override
        public int subscriberMask() {
            return MIN | MAX | VALUE;
        }

        @Override
        public String toString() {
            return "ExpAddVectorObserver: " + _vars;
        }

        @Override
        public void update(Subject exp, EventOfInterest event) throws Failure {
            IntEvent e = (IntEvent) event;

            // System.out.println("Event:" + e);

            _domainE.setMin(_domainE.min() + e.mindiff());
            _domainE.setMax(_domainE.max() + e.maxdiff());

            // update domainC
            _domainC.setMin(_domainE.min());
            _domainC.setMax(_domainE.max());

        }

    } // ~ ExpAddVectorObserver

    static final private int[] event_map = { MIN, MIN, MAX, MAX, MIN | MAX | VALUE, VALUE,
            // REMOVE, REMOVE
    };
    private final IntExpArray _vars;

    private final Observer _observer;

    private final IntVar _domainC; // constraint domain

    private final DomainVar _domainE; // expression domain

    public IntExpAddArray1(Constrainer constrainer, IntExpArray vars) {
        super(constrainer);
        vars.size();
        _vars = vars;
        _observer = new ExpAddVectorObserver();

        IntExp[] data = _vars.data();

        for (IntExp datum : data) {
            datum.attachObserver(_observer);
        }

        String sum_name = "";

        if (constrainer().showInternalNames()) {
            StringBuilder s = new StringBuilder();
            s.append("(");
            for (int i = 0; i < data.length; i++) {
                if (i != 0) {
                    s.append("+");
                }
                s.append(data[i].name());
            }
            s.append(")");
            _name = s.toString();

            sum_name = "sum(" + _vars.name() + ")";
        }

        int min = calc_min();
        int max = calc_max();
        _domainC = constrainer().addIntVarTraceInternal(min, max, sum_name, IntVar.DOMAIN_PLAIN);
        _domainE = new DomainVar(constrainer(), min, max);
    }

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

    int calc_max() {
        int max_sum = 0;

        IntExp[] vars = _vars.data();

        for (IntExp var : vars) {
            max_sum += var.max();
        }
        return max_sum;
    }

    int calc_min() {
        int min_sum = 0;

        IntExp[] vars = _vars.data();

        for (IntExp var : vars) {
            min_sum += var.min();
        }
        return min_sum;
    }

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

    void enforceDomainC() throws Failure {
        int minC = _domainC.min();
        int maxC = _domainC.max();
        int minE = _domainE.min();
        int maxE = _domainE.max();

        if (minC == minE && maxC == maxE) {
            // System.out.println("*** enforceDomainC():
            // ["+minE+".."+maxE+"]->["+minC+".."+maxC+"]");
            return;
        }

        IntExp[] vars = _vars.data();

        for (IntExp vari : vars) {
            int mini = vari.min();
            int maxi = vari.max();

            int new_min = minC - (maxE - maxi);
            if (new_min > mini) {
                vari.setMin(new_min);
            }

            int new_max = maxC - (minE - mini);
            if (new_max < maxi) {
                vari.setMax(new_max);
            }
        }
    }

    @Override
    public boolean isLinear() {
        for (int i = 0; i < _vars.size(); i++) {
            if (!_vars.get(i).isLinear()) {
                return false;
            }
        }
        return true;
    }

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

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

    @Override
    public void name(String name) {
        super.name(name);
        _domainC.name(name);
    }

    @Override
    public void onMaskChange() {
        // int mask = publisherMask();
        // IntExp[] data =_vars.data();
        // for(int i=0; i < data.length; i++)
        // {
        // _observer.publish(mask,data[i]);
        // }
    }

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

    @Override
    public void removeValue(int value) throws Failure {
        int Max = _domainC.max();
        if (value > Max) {
            return;
        }
        int Min = _domainC.min();
        if (value < Min) {
            return;
        }
        if (Min == Max) {
            constrainer().fail("remove for IntExpAddVector");
        }
        if (value == Max) {
            setMax(value - 1);
        }
        if (value == Min) {
            setMin(value + 1);
        }
    }

    @Override
    public void setMax(int max) throws Failure {

        if (max >= _domainC.max()) {
            return;
        }

        _domainC.setMax(max);

        // System.out.println("++++ Set max: " + max + " in " + this);

        int min_sum = _domainE.min();

        IntExp[] vars = _vars.data();

        for (IntExp vari : vars) {
            int maxi = max - (min_sum - vari.min());
            if (maxi < vari.max()) {
                vari.setMax(maxi);
            }
        }
        // System.out.println("---- set max:" + max + " in " + this);
    }

    @Override
    public void setMin(int min) throws Failure {

        if (min <= _domainC.min()) {
            return;
        }

        _domainC.setMin(min);

        // System.out.println("++++ Set min: " + min + " in " + this);

        int max_sum = _domainE.max();

        IntExp[] vars = _vars.data();

        for (IntExp vari : vars) {
            int mini = min - (max_sum - vari.max());
            if (mini > vari.min()) {
                vari.setMin(mini);
            }
        }
        // System.out.println("---- set min:" + min + " in " + this);
    }

    @Override
    public void setValue(int value) throws Failure {
        if (_domainC.min() == value && _domainC.max() == value) {
            return;
        }

        _domainC.setValue(value);

        // System.out.println("++++ Set value: " + value + " in " + this);

        int sum_min = _domainE.min();
        int sum_max = _domainE.max();

        IntExp[] vars = _vars.data();

        for (IntExp vari : vars) {
            int mini = vari.min();
            int maxi = vari.max();

            int new_min = value - (sum_max - maxi);
            if (new_min > mini) {
                vari.setMin(new_min);
            }

            int new_max = value - (sum_min - mini);
            if (new_max < maxi) {
                vari.setMax(new_max);
            }
        }

        // System.out.println("---- set value: " + value + " in " + this);
    }

    @Override
    public int size() {
        return max() - min() + 1;
    }

} // ~IntExpAddArray1




© 2015 - 2024 Weber Informatics LLC | Privacy Policy