/*
* Kodkod -- Copyright (c) 2005-present, Emina Torlak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package kodkod.engine.bool;
import java.util.Iterator;
import java.util.Set;
/**
* A non-constant boolean value with zero or more inputs.
* @specfield op: Operator
* @specfield size: int
* @specfield inputs: [0..size) -> one BooleanFormula
* @invariant size >= 0
* @author Emina Torlak
*/
public abstract class BooleanFormula extends BooleanValue implements Iterable<BooleanFormula> {
private BooleanFormula negation;
/**
* Constructs a boolean formula with the given negation.
*/
BooleanFormula(BooleanFormula negation) {
this.negation = negation;
}
/**
* Returns an integer hash of this formula, used
* to compute the hash of the composition of this and
* some other formula with the given operator.
* @return an integer hash of this formula when acting
* as an input to a multigate with the given operator.
*/
abstract int hash(Operator op);
/**
* Returns an integer k' such that 0 < |k'| < k and |k'| is the number of flattening
* steps that need to be taken to determine that this circuit has (or does not have)
* an input with the given label.
* A positive k' indicates that f is found to be an input to this circuit in k' steps.
* A negative k' indicates that f is not an input to this circuit, when it is flattened
* using at most k steps.
* @requires k > 0
* @return the number of flattening
* steps that need to be taken to determine that f is (not) an input to this circuit
*/
int contains(Operator op, int f, int k) {
return f==label() ? 1 : -1;
}
/**
* Flattens this circuit with respect to the given operator into
* the provided set.
* Specifically, the method modifies the set so that it contains
* the elements f_0, ..., f_k' where k' <= k elements and
* [[this]] = op(f_0, ..., f_k').
* The default implementation simply adds this to the set.
* @requires k > 0
* @ensures 1 <= k' <= k && some f_0,..., f_k' : flat.elts' |
* [[this]] = op([[f_0]], ..., [[f_k']])
*/
void flatten(Operator op, Set<BooleanFormula> flat, int k) {
assert k > 0;
flat.add(this);
}
/**
* Returns the negation of this formula if it has already been computed.
* Otherwise, computes, caches and returns the negation of this formula.
* @return !this
* @see kodkod.engine.bool.BooleanValue#negation()
*/
final BooleanFormula negation() {
if (negation==null) {
negation = new NotGate(this);
}
return negation;
}
/**
* Returns true if the negation of this formula
* has already been computed.
* @return true if the negation of this formula has already been computed.
*/
final boolean hasNegation() { return negation != null; }
/**
* Passes this value and the given
* argument value to the visitor, and returns the resulting value.
* @return the value produced by the visitor when visiting this node
* with the given argument.
*/
public abstract <T, A> T accept(BooleanVisitor<T, A> visitor, A arg);
/**
* Returns an iterator over the inputs to this gate.
* @return an iterator over this.inputs.
*/
public abstract Iterator<BooleanFormula> iterator();
/**
* Returns the number of inputs to this gate.
* @return #this.inputs
*/
public abstract int size();
/**
* Returns the ith input to this gate.
* @return this.inputs[i]
* @requires 0 <= i < size
* @throws IndexOutOfBoundsException i < 0 || i >= #this.inputs
*/
public abstract BooleanFormula input(int i);
}