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

jp.kobe_u.sugar.csp.IntegerDomainOld Maven / Gradle / Ivy

Go to download

This is a JSR331 interface for the open source Java constraint programming library "Sugar" v. 2.1.3

There is a newer version: 2.3.1
Show newest version
package jp.kobe_u.sugar.csp;
 
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import jp.kobe_u.sugar.SugarException;

/**
 * This class implements an integer domain class.
 * @see CSP
 * @author Naoyuki Tamura ([email protected])
 */
public class IntegerDomainOld extends IntegerDomain {
    public static int MAX_SET_SIZE = 128;
    // public static int MAX_SET_SIZE = 256;
    private int lb;
    private int ub;
    private SortedSet domain;

    private static IntegerDomainOld _create(SortedSet domain) throws SugarException {
        int lb = domain.first();
        int ub = domain.last();
        if (domain.size() <= MAX_SET_SIZE) {
            boolean sparse = false;
            for (int value = lb; value <= ub; value++) {
                if (! domain.contains(value)) {
                    sparse = true;
                    break;
                }
            }
            if (! sparse) {
                domain = null;
            }
        } else {
            domain = null;
        }
        if (domain == null) {
            return new IntegerDomainOld(lb, ub); 
        }
        return new IntegerDomainOld(domain);
    }
    
    public IntegerDomainOld(int lb, int ub) throws SugarException {
        if (lb > ub) {
            throw new SugarException("Illegal domain instantiation " + lb + " " + ub);
        }
        this.lb = lb;
        this.ub = ub;
        domain = null;
    }

    public IntegerDomainOld(SortedSet domain) {
        lb = domain.first();
        ub = domain.last();
        this.domain = domain;
    }

    public IntegerDomainOld(IntegerDomainOld d) {
        lb = d.lb;
        ub = d.ub;
        domain = null;
        if (d.domain != null) {
            domain = new TreeSet(d.domain);
        }
    }
    
    public int size() {
        if (domain == null) {
            return lb <= ub ? ub - lb + 1 : 0; 
        } else {
            return domain.size();
        }
    }

    private boolean isContiguous() {
        return domain == null;
    }
    
    public int getLowerBound() {
        if (domain == null) {
            return lb;
        } else {
            return domain.first();
        }
    }

    public int getUpperBound() {
        if (domain == null) {
            return ub;
        } else {
            return domain.last();
        }
    }

    private SortedSet getSet() {
        return domain;
    }
    
    public boolean contains(int value) {
        if (domain == null) {
            return lb <= value && value <= ub;
        } else {
            return domain.contains(value);
        }
    }

    public int sizeLE(int value) {
        if (value < lb)
            return 0;
        if (value >= ub)
            return size();
        if (domain == null) {
            return value - lb + 1;
        } else {
            return domain.headSet(value + 1).size();
        }
    }

    public IntegerDomain bound(int lb0, int ub0) throws SugarException {
        int lb = getLowerBound();
        int ub = getUpperBound();
        if (lb0 <= lb && ub <= ub0)
            return this;
        lb0 = Math.max(lb, lb0);
        ub0 = Math.min(ub, ub0);
        if (domain == null) {
            return new IntegerDomainOld(lb0, ub0);
        } else {
            // System.out.println("## " + lb0 + " " + ub0 + " " + domain);
            return new IntegerDomainOld(domain.subSet(lb0, ub0 + 1));
        }
    }

    private class Iter implements Iterator {
        int value;
        int ub;
        
        public Iter(int lb, int ub) {
            value = lb;
            this.ub = ub;
        }
        
        public boolean hasNext() {
            return value <= ub;
        }

        public Integer next() {
            return value++;
        }

        public void remove() {
        }

    }
    
    public Iterator values(int lb, int ub) {
        if (lb > ub) {
            return new Iter(lb, ub);
        } else if (domain == null) {
                lb = Math.max(lb, this.lb);
                ub = Math.min(ub, this.ub);
                return new Iter(lb, ub);
        } else {
            return domain.subSet(lb, ub + 1).iterator();
        }
    }
    
    public Iterator values() {
        return values(lb, ub);
    }
    
    public Iterator intervals() {
        List intervals = new ArrayList();
        if (isContiguous()) {
            intervals.add(new int[] { getLowerBound(), getUpperBound() });
        } else {
            int value0 = Integer.MIN_VALUE;
            int value1 = Integer.MIN_VALUE;
            for (int value : getSet()) {
                if (value0 == Integer.MIN_VALUE) {
                    value0 = value1 = value;
                } else if (value1 + 1 == value) {
                    value1 = value;
                } else {
                    intervals.add(new int[] { value0, value1 });
                    value0 = value1 = value;
                }
            }
            if (value0 != Integer.MIN_VALUE) {
                intervals.add(new int[] { value0, value1 });
            }
        }
        return intervals.iterator();
    }
    
    public IntegerDomain cap(IntegerDomainOld d1) throws SugarException {
        if (d1.domain == null) {
            return bound(d1.lb, d1.ub); 
        } else if (domain == null) {
            return d1.bound(lb, ub);
        } else {
            SortedSet d = new TreeSet();
            for (int value : domain) {
                if (d1.contains(value)) {
                    d.add(value);
                }
            }
            return new IntegerDomainOld(d);
        }
    }

    public IntegerDomain cup(IntegerDomainOld d1) throws SugarException {
        if (domain == null || d1.domain == null) {
            if (size() == 1 && d1.size() == 1) {
                SortedSet d = new TreeSet();
                d.add(lb);
                d.add(d1.lb);
                return _create(d);
            }
            int lb = Math.min(this.lb, d1.lb);
            int ub = Math.max(this.ub, d1.ub);
            return new IntegerDomainOld(lb, ub);
        } else {
            SortedSet d = new TreeSet(domain);
            d.addAll(d1.domain);
            // return new IntegerDomain(d);
            return _create(d);
        }
    }

    public IntegerDomain neg() throws SugarException {
        if (domain == null) {
            return new IntegerDomainOld(-ub, -lb);
        } else {
            SortedSet d = new TreeSet();
            for (int value : domain) {
                d.add(-value);
            }
            // return new IntegerDomain(d);
            return _create(d);
        }
    }

    public IntegerDomain abs() throws SugarException {
        if (domain == null) {
            int lb0 = Math.min(Math.abs(lb), Math.abs(ub));
            int ub0 = Math.max(Math.abs(lb), Math.abs(ub));
            if (lb <= 0 && 0 <= ub) {
                return new IntegerDomainOld(0, ub0);
            } else {
                return new IntegerDomainOld(lb0, ub0);
            }
        } else {
            SortedSet d = new TreeSet();
            for (int value : domain) {
                d.add(Math.abs(value));
            }
            // return new IntegerDomain(d);
            return _create(d);
        }
    }
    
    private IntegerDomain add(int a) throws SugarException {
        if (domain == null) {
            return new IntegerDomainOld(lb+a, ub+a);
        } else {
            SortedSet d = new TreeSet();
            for (int value : domain) {
                d.add(value + a);
            }
            // return new IntegerDomain(d);
            return _create(d);
        }
    }

    public IntegerDomain add(IntegerDomainOld d) throws SugarException {
        if (d.size() == 1) {
            return add(d.lb);
        } else  if (size() == 1) {
            return d.add(lb);
        }
        if (domain == null || d.domain == null) {
            int lb0 = lb + d.lb;
            int ub0 = ub + d.ub;
            return new IntegerDomainOld(lb0, ub0);
        } else {
            SortedSet d0 = new TreeSet();
            for (int value1 : domain) {
                for (int value2 : d.domain) {
                    d0.add(value1 + value2);
                }
            }
            // return new IntegerDomain(d0);
            return _create(d0);
        }
    }

    private IntegerDomain sub(int a) throws SugarException {
        return add(-a);
    }

    public IntegerDomain sub(IntegerDomainOld d) throws SugarException {
        return add(d.neg());
    }

    public IntegerDomain mul(int a) throws SugarException {
        if (domain == null) {
            // TODO domain calculation for multiplication
            if (false && size() <= MAX_SET_SIZE) {
                SortedSet d = new TreeSet();
                for (int value = lb; value <= ub; value++) {
                    d.add(value * a);
                }
                return _create(d);
            } else if (a < 0) {
                return new IntegerDomainOld(ub*a, lb*a);
            } else {
                return new IntegerDomainOld(lb*a, ub*a);
            }
        } else {
            SortedSet d = new TreeSet();
            for (int value : domain) {
                d.add(value * a);
            }
            return _create(d);
        }
    }

    public IntegerDomain mul(IntegerDomainOld d) throws SugarException {
        if (d.size() == 1) {
            return mul(d.lb);
        } else  if (size() == 1) {
            return d.mul(lb);
        }
        if (domain == null || d.domain == null
                || size() * d.size() > MAX_SET_SIZE) {
            int b00 = lb * d.lb;
            int b01 = lb * d.ub;
            int b10 = ub * d.lb;
            int b11 = ub * d.ub;
            int lb0 = Math.min(Math.min(b00, b01), Math.min(b10, b11));
            int ub0 = Math.max(Math.max(b00, b01), Math.max(b10, b11));
            return new IntegerDomainOld(lb0, ub0);
        } else {
            SortedSet d0 = new TreeSet();
            for (int value1 : domain) {
                for (int value2 : d.domain) {
                    d0.add(value1 * value2);
                }
            }
            return _create(d0);
        }
    }

    private int div(int x, int y) {
        if (x < 0 && x % y != 0) {
            return x / y - 1;
        }
        return x / y;
    }
    
    public IntegerDomain div(int a) throws SugarException {
        if (domain == null) {
            if (a < 0) {
                return new IntegerDomainOld(div(ub,a), div(lb,a));
            } else {
                return new IntegerDomainOld(div(lb,a), div(ub,a));
            }
        } else {
            SortedSet d = new TreeSet();
            for (int value : domain) {
                d.add(div(value, a));
            }
            return _create(d);
        }
    }

    public IntegerDomain div(IntegerDomainOld d) throws SugarException {
        if (d.size() == 1) {
            return div(d.lb);
        }
        if (domain == null || d.domain == null
                || size() * d.size() > MAX_SET_SIZE) {
            int b00 = div(lb, d.lb);
            int b01 = div(lb, d.ub);
            int b10 = div(ub, d.lb);
            int b11 = div(ub, d.ub);
            int lb0 = Math.min(Math.min(b00, b01), Math.min(b10, b11));
            int ub0 = Math.max(Math.max(b00, b01), Math.max(b10, b11));
            if (d.lb <= 1 && 1 <= d.ub) {
                lb0 = Math.min(lb0, Math.min(lb, ub));
                ub0 = Math.max(ub0, Math.max(lb, ub));
            }
            if (d.lb <= -1 && -1 <= d.ub) {
                lb0 = Math.min(lb0, Math.min(-lb, -ub));
                ub0 = Math.max(ub0, Math.max(-lb, -ub));
            }
            return new IntegerDomainOld(lb0, ub0);
        } else {
            SortedSet d0 = new TreeSet();
            for (int value1 : domain) {
                for (int value2 : d.domain) {
                    d0.add(div(value1, value2));
                }
            }
            return _create(d0);
        }
    }

    public IntegerDomain mod(int a) throws SugarException {
        a = Math.abs(a);
        if (domain == null) {
            return new IntegerDomainOld(0, a - 1);
        } else {
            SortedSet d = new TreeSet();
            for (int value : domain) {
                d.add(value % a);
            }
            return _create(d);
        }
    }

    public IntegerDomain mod(IntegerDomainOld d) throws SugarException {
        if (d.size() == 1) {
            return mod(d.lb);
        }
        if (domain == null || d.domain == null) {
            int lb0 = 0;
            int ub0 = Math.max(Math.abs(d.lb), Math.abs(d.ub)) - 1;
            return new IntegerDomainOld(lb0, ub0);
        } else {
            SortedSet d0 = new TreeSet();
            for (int value1 : domain) {
                for (int value2 : d.domain) {
                    d0.add(value1 % value2);
                }
            }
            return _create(d0);
        }
    }

    public IntegerDomain pow(int a) throws SugarException {
        if (domain == null) {
            int a1 = (int)Math.round(Math.pow(lb, a));
            int a2 = (int)Math.round(Math.pow(ub, a));
            int lb0 = Math.min(a1, a2);
            int ub0 = Math.max(a1, a2);
            if (a % 2 == 0 && lb <= 0 && 0 <= ub) {
                return new IntegerDomainOld(0, ub0);
            } else {
                return new IntegerDomainOld(lb0, ub0);
            }
        } else {
            SortedSet d = new TreeSet();
            for (int value : domain) {
                d.add((int)Math.round(Math.pow(value, a)));
            }
            return _create(d);
        }
    }
    
    public IntegerDomain min(IntegerDomainOld d) throws SugarException {
        int lb0 = Math.min(lb, d.lb);
        int ub0 = Math.min(ub, d.ub);
        if (ub <= d.lb) {
            return this;
        } else if (d.ub <= lb) {
            return d;
        } 
        if (domain == null) {
            if (d.domain == null) {
                return new IntegerDomainOld(lb0, ub0);
            } else {
                return d.min(this);
            }
        } else {
            if (d.domain == null) {
                return _create(domain.subSet(lb0, ub0 + 1));
            } else {
                SortedSet d1 = new TreeSet(domain);
                d1.addAll(d.domain);
                d1 = d1.subSet(lb0, ub0 + 1);
                // return new IntegerDomain(d1);
                return _create(d1);
            }
        }
    }

    public IntegerDomain max(IntegerDomainOld d) throws SugarException {
        int lb0 = Math.max(lb, d.lb);
        int ub0 = Math.max(ub, d.ub);
        if (lb >= d.ub) {
            return this;
        } else if (d.lb >= ub) {
            return d;
        } 
        if (domain == null) {
            if (d.domain == null) {
                return new IntegerDomainOld(lb0, ub0);
            } else {
                return d.max(this);
            }
        } else {
            if (d.domain == null) {
                return _create(domain.subSet(lb0, ub0 + 1));
            } else {
                SortedSet d1 = new TreeSet(domain);
                d1.addAll(d.domain);
                d1 = d1.subSet(lb0, ub0 + 1);
                // return new IntegerDomain(d1);
                return _create(d1);
            }
        }
    }

    private void checkDomain(IntegerDomain domain) throws SugarException {
        if (! (domain instanceof IntegerDomainOld))
            throw new SugarException("Incompatible domain " + this + ", " + domain);
    }
    
    @Override
    public IntegerDomain cup(IntegerDomain domain) throws SugarException {
        checkDomain(domain);
        return cup((IntegerDomainOld)domain);
    }

    @Override
    public IntegerDomain cap(IntegerDomain domain) throws SugarException {
        checkDomain(domain);
        return cap((IntegerDomainOld)domain);
    }

    @Override
    public IntegerDomain add(IntegerDomain domain) throws SugarException {
        checkDomain(domain);
        return add((IntegerDomainOld)domain);
    }

    @Override
    public IntegerDomain sub(IntegerDomain domain) throws SugarException {
        checkDomain(domain);
        return sub((IntegerDomainOld)domain);
    }

    @Override
    public IntegerDomain mul(IntegerDomain domain) throws SugarException {
        checkDomain(domain);
        return mul((IntegerDomainOld)domain);
    }

    @Override
    public IntegerDomain div(IntegerDomain domain) throws SugarException {
        checkDomain(domain);
        return div((IntegerDomainOld)domain);
    }

    @Override
    public IntegerDomain mod(IntegerDomain domain) throws SugarException {
        checkDomain(domain);
        return mod((IntegerDomainOld)domain);
    }

    @Override
    public IntegerDomain min(IntegerDomain domain) throws SugarException {
        checkDomain(domain);
        return min((IntegerDomainOld)domain);
    }

    @Override
    public IntegerDomain max(IntegerDomain domain) throws SugarException {
        checkDomain(domain);
        return max((IntegerDomainOld)domain);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy