Package solver.constraints.nary.cnf

Source Code of solver.constraints.nary.cnf.LogOp

/**
*  Copyright (c) 1999-2014, Ecole des Mines de Nantes
*  All rights reserved.
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions are met:
*
*      * Redistributions of source code must retain the above copyright
*        notice, this list of conditions and the following disclaimer.
*      * Redistributions in binary form must reproduce the above copyright
*        notice, this list of conditions and the following disclaimer in the
*        documentation and/or other materials provided with the distribution.
*      * Neither the name of the Ecole des Mines de Nantes nor the
*        names of its contributors may be used to endorse or promote products
*        derived from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
*  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*  DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
*  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
*  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package solver.constraints.nary.cnf;

import solver.variables.BoolVar;
import util.tools.ArrayUtils;

/**
* Logical Operator, to ease clause definition.
* <br/>
*
* @author Charles Prud'homme
* @since 23 nov. 2010
*/
public final class LogOp implements ILogical {

    public enum Operator {
        OR, AND;

        public static Operator flip(Operator operator) {
            if (Operator.OR.equals(operator)) {
                return Operator.AND;
            } else {
                return Operator.OR;
            }
        }
    }

    public enum Type {
        POSITIVE, NEGATIVE;

        public static Type flip(Type type) {
            if (Type.POSITIVE.equals(type)) {
                return Type.NEGATIVE;
            } else {
                return Type.POSITIVE;
            }
        }
    }

    Type type;

    Operator operator;

    ILogical[] children;

    BoolVar[] varsAsArray;

    protected LogOp(Operator operator, Type type, ILogical... children) {
        this.type = type;
        this.operator = operator;
        if (children == null) {
            this.children = new ILogical[0];
        } else {
            this.children = children;
        }
    }


    public static LogOp and(ILogical... children) {
        return new LogOp(Operator.AND, Type.POSITIVE, children);
    }

    public static LogOp ifOnlyIf(ILogical a, ILogical b) {
        return and(implies(a, b), implies(b, a));
    }

    public static LogOp ifThenElse(ILogical a, ILogical b, ILogical c) {
        try {
            ILogical na = negate(a);
            return or(and(a, b), and(na, c));
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static LogOp implies(ILogical a, ILogical b) {
        try {
            ILogical na = negate(a);
            return or(na, b);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static LogOp reified(BoolVar b, ILogical tree) {
        try {
            BoolVar nb = b.not();
            ILogical ntree = negate(tree);
            return or(and(b, tree), and(nb, ntree));
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static LogOp or(ILogical... children) {
        return new LogOp(Operator.OR, Type.POSITIVE, children);
    }

    public static LogOp nand(ILogical... children) {
        return new LogOp(Operator.AND, Type.NEGATIVE, children);
    }

    public static LogOp nor(ILogical... children) {
        return new LogOp(Operator.OR, Type.NEGATIVE, children);
    }

    public static LogOp xor(ILogical a, ILogical b) {
        try {
            ILogical na = negate(a);
            ILogical nb = negate(b);
            return or(and(a, nb), and(b, na));
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static ILogical negate(ILogical l) throws CloneNotSupportedException {
        if (l.isLit()) {
            return ((BoolVar) l).not();
        } else {
            LogOp n = (LogOp) l;
            LogOp na = n.clone();
            na.type = Type.flip(and().type);
            return na;
        }
    }


    /**
     * Current tree is rooted with the logical operator <code>op</code>
     *
     * @param op operator checked
     * @return <code>true</code> if <code>this</code> is <code>op</code>
     */
    public boolean is(Operator op) {
        return op.equals(operator);
    }

    /**
     * Current tree is rooted with NOT logical operator
     *
     * @return <code>true</code> if <code>this</code> is NOT
     */
    public boolean isNot() {
        return type.equals(Type.NEGATIVE);
    }

    @Override
    public boolean isLit() {
        return false;
    }

  @Override
  public void setNot(boolean isNot){
    throw new UnsupportedOperationException();
  }

    /**
     * Returns the number of direct children of <code>this</code>
     *
     * @return number of children
     */
    int getNbChildren() {
        return children.length;
    }

    /**
     * Check if at least one children is an OR logic tree
     *
     * @return <code>true</code> if <code>this</code> contains one OR logic tree
     */
    boolean hasOrChild() {
        for (int i = 0; i < children.length; i++) {
            if (!children[i].isLit() && ((LogOp) children[i]).is(Operator.OR)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Checks if at least one children is an AND logic tree
     *
     * @return <code>true</code> if <code>this</code> contains one AND logic tree
     */
    boolean hasAndChild() {
        for (int i = 0; i < children.length; i++) {
            if (!children[i].isLit() && ((LogOp) children[i]).is(Operator.AND)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Adds <code>child</code> to the current list of children of <code>this</code>
     *
     * @param child the logic tree to add
     */
    public void addChild(ILogical child) {
        ILogical[] tmp = children;
        children = new ILogical[tmp.length + 1];
        System.arraycopy(tmp, 0, children, 0, tmp.length);
        children[tmp.length] = child;
        varsAsArray = null; // force recomputation of varsArray
    }

    /**
     * Removes <code>child</code> from the current list of children of <code>this</code>
     *
     * @param child the logic tree to remove
     */
    public void removeChild(ILogical child) {
        int i = 0;
        for (; i < children.length && children[i] != child; i++) {
        }
        if (i == children.length) return;
        ILogical[] tmp = children;
        children = new ILogical[tmp.length - 1];
        System.arraycopy(tmp, 0, children, 0, i);
        System.arraycopy(tmp, i + 1, children, i, tmp.length - i - 1);
        varsAsArray = null; // force recomputation of varsArray
    }

    /**
     * Returns the array of children of <code>this</code>.
     * <code>null</code> is a valid return value.
     *
     * @return an array of logic trees, <code>null</code> otherwise
     */
    public ILogical[] getChildren() {
        return children;
    }

    /**
     * Returns the first AND logic tree within the list of children.
     * <code>null</code> is a valid return value.
     *
     * @return a AND logic tree if exists, <code>null</code> otherwise
     */
    public ILogical getAndChild() {
        for (int i = 0; i < children.length; i++) {
            if (!children[i].isLit() && ((LogOp) children[i]).is(Operator.AND)) {
                return children[i];
            }
        }
        return null;
    }

    /**
     * Returns the first child within the list of children, different from <code>child</code>.
     * <code>null</code> is a valid return value.
     *
     * @param child node to avoid
     * @return the first logic tree different from <code>child</code> if exists, <code>null</code> otherwise
     */
    public ILogical getChildBut(ILogical child) {
        for (int i = 0; i < children.length; i++) {
            if (children[i] != child) {
                return children[i];
            }
        }
        return null;
    }

    /**
     * Flip the boolean evaluation of <code>this</code>  (recursive).
     */
    public void flip() {
        type = Type.flip(type);
        operator = Operator.flip(operator);
        for (int i = 0; i < children.length; i++) {
            if (children[i].isLit()) {
                children[i] = ((BoolVar) children[i]).not();
            } else {
                ((LogOp) children[i]).deny();
            }
        }
    }


    /**
     * Flip the boolean operator of <code>this</code> (recursive).
     */
    public void deny() {
        operator = Operator.flip(operator);
        for (int i = 0; i < children.length; i++) {
            if (children[i].isLit()) {
                children[i] = ((BoolVar) children[i]).not();
            } else {
                ((LogOp) children[i]).deny();
            }
        }
    }

    @Override
    public String toString() {
        StringBuilder st = new StringBuilder();
        st.append('(');
//        st.append(Type.POSITIVE.equals(type) ? "(" : "not(");

        String op = (Type.POSITIVE.equals(type) ? "" : "n") + (Operator.AND.equals(operator) ? "and " : "or ");
        for (int i = 0; i < children.length; i++) {
            ILogical child = children[i];
            if (child.isLit()) {
                st.append(((BoolVar) child).getName());
            } else {
                st.append(child.toString());
            }
            st.append(" ").append(op);

        }
        st.replace(st.length() - (op.length() + 1), st.length(), "");
        st.append(')');
        return st.toString();
    }


    @Override
    public LogOp clone() throws CloneNotSupportedException {
        LogOp logOp = (LogOp) super.clone();
        logOp.type = this.type;
        logOp.operator = this.operator;
        logOp.children = new ILogical[this.children.length];
        for (int c = 0; c < children.length; c++) {
            if (children[c].isLit()) {
                logOp.children[c] = children[c];
            } else {
                logOp.children[c] = ((LogOp) children[c]).clone();
            }
        }
        return logOp;
    }

    /**
     * Extracts and returns the flatten array of BoolVar contained in <code>this</code>.
     * WARNING : a variable may appear more than once, redundancy is not checked!
     *
     * @return array of bool variables
     */
    public BoolVar[] flattenBoolVar() {
//        if (varsAsArray == null) {
        buildVarsArray();
//        }
        return varsAsArray;
    }

    public void cleanFlattenBoolVar() {
        for (int i = 0; i < children.length; i++) {
            if (!children[i].isLit()) {
                ((LogOp) children[i]).cleanFlattenBoolVar();
            }
        }
        varsAsArray = null;
    }

    private void buildVarsArray() {
        final BoolVar[][] childrenVars = new BoolVar[children.length][];
        for (int i = 0; i < children.length; i++) {
            if (children[i].isLit()) {
                childrenVars[i] = new BoolVar[]{(BoolVar) children[i]};
            } else {
                childrenVars[i] = ((LogOp) children[i]).flattenBoolVar();
            }
        }
        varsAsArray = ArrayUtils.flatten(childrenVars);
    }
}
TOP

Related Classes of solver.constraints.nary.cnf.LogOp

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.