/* * 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.NoSuchElementException; import java.util.Set; /** * A logic gate with two inputs. * @invariant #this.inputs = 2 * @invariant digest = sum(inputs.digest(this.op)) */ final class BinaryGate extends MultiGate { private final BooleanFormula low, high; /** * Constructs a new binary gate with the given operator, label, and inputs. * @requires components.h = components.l && l.label < h.label * @ensures this.op' = op && this.inputs' = l + h && this.label' = label */ BinaryGate(Operator.Nary op, int label, int hashcode, BooleanFormula l, BooleanFormula h) { super(op, label, hashcode); assert l.label() < h.label(); this.low = l; this.high = h; } /** * 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 */ @Override int contains(Operator op, int f, int k) { assert k > 0; if (f==label()) return 1; else if (this.op != op || k < 2 || f>label() || -f>label()) return -1; else { final int l = low.contains(op, f, k-1); if (l > 0) return l; else { final int h = high.contains(op, f, k - l); return h > 0 ? h - l : h + l; } } } /** * 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']]) */ @Override void flatten(Operator op, Set<BooleanFormula> flat, int k) { assert k > 0; if (this.op==op && k > 1) { final int oldsize = flat.size(); low.flatten(op, flat, k-1); high.flatten(op, flat, k - (flat.size()-oldsize)); } else { flat.add(this); } } /** * Returns 2. * @return 2 */ @Override public int size() { return 2; } /** * Returns an iterator over the inputs to this gate, in * the increasing label order. * @return an iterator over this.inputs. */ @Override public Iterator<BooleanFormula> iterator() { return new Iterator<BooleanFormula>() { int next = 0; public boolean hasNext() { return next < 2; } public BooleanFormula next() { if (!hasNext()) throw new NoSuchElementException(); return (next++ == 0 ? low : high); } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Returns the ith input to this gate. * @return this.inputs[i] * @requires 0 <= i < size * @throws IndexOutOfBoundsException i < 0 || i >= #this.inputs */ @Override public BooleanFormula input(int i) { switch(i) { case 0 : return low; case 1 : return high; default: throw new IndexOutOfBoundsException(); } } }