/** * Code by Daniel Rinehart * Created for CSG260 Fall 2006 with Karl Lieberherr */ import java.util.Iterator; /** * Utility class that provides methods for creating an updating a polynomial * which is used to determine biased coin values. */ public class SATSolverUtil { /** * Private constructor to force utility class usage. */ private SATSolverUtil() { } /** * Given an initial state of relation numbers and fractions compute the * maximum bias. * * @param inputInitial * Initial input * @return Bias and polynomial * @throws IllegalArgumentException * If the PairI fractions do not add to 1.0, any PairI relation * number is outside the range 0 to 255 inclusive, or any PairI * fraction is outside the range 0.0 to 1.0 inclusive. */ public static OutputI calculateBias(InputInitialI inputInitial) { PolynomialSum polynomialSum = createPolynomialSum(inputInitial.getPairs().iterator()); if (!Polynomial.equal(1.0, polynomialSum.sum)) { throw new IllegalArgumentException( "InputInitial's pair fractions do not add to 1.0 +/-" + Polynomial.DELTA + ". Got: " + polynomialSum.sum); } return new Output(polynomialSum.polynomial); } /** * Given a previously generated polynomial, compute an updated maximum bias * based on adding and subtracting the given relation numbers and fractions. * * @param inputUpdate * Updated input * @return Bias and polynomial * @throws IllegalArgumentException * If the PairI added fractions do not equals the subtracted * fractions, any PairI relation number is outside the range 0 * to 255 inclusive, or any PairI fraction is outside the range * 0.0 to 1.0 inclusive. */ public static OutputI updateBias(InputUpdateI inputUpdate) { Polynomial initialPolynomial = createInitialPolynomial(inputUpdate); PolynomialSum addPolynomialSum = createPolynomialSum(inputUpdate.getAddedPairs().iterator()); PolynomialSum subtractPolynomialSum = createPolynomialSum(inputUpdate.getSubtractedPairs() .iterator()); if (!Polynomial.equal(addPolynomialSum.sum, subtractPolynomialSum.sum)) { throw new IllegalArgumentException( "InputUpdate's added and subtracted pair fractions do not add to the same value +/-" + Polynomial.DELTA + ". Got: " + addPolynomialSum.sum + " and " + subtractPolynomialSum.sum); } return new Output(initialPolynomial.add(addPolynomialSum.polynomial).subtract( subtractPolynomialSum.polynomial)); } /** * For the update operation, extract out the base polynomial to be modified. * * @param inputUpdate * Updated input * @return Polynomial */ private static Polynomial createInitialPolynomial(InputUpdateI inputUpdate) { if (inputUpdate.getPolynomialBefore() instanceof Polynomial) { return (Polynomial) inputUpdate.getPolynomialBefore(); } PolynomialI polynomial = inputUpdate.getPolynomialBefore(); return new Polynomial(polynomial.getCoefficient(3), polynomial.getCoefficient(2), polynomial.getCoefficient(1), polynomial.getCoefficient(0)); } /** * Given a list of PairI objects compute the polynomial and total fractional * sum of the PairI objects found. * * @param iterator * PairI list * @return Polynomial and sum */ private static PolynomialSum createPolynomialSum(Iterator iterator) { int relationsSeen[] = new int[256]; Polynomial result = null; double sum = 0.0; while (iterator.hasNext()) { PairI pair = (PairI) iterator.next(); verifyPair(pair); if (relationsSeen[pair.getRelationNumber()] != 0) { throw new IllegalArgumentException("Relation number " + pair.getRelationNumber() + " appears twice in the set."); } relationsSeen[pair.getRelationNumber()] = 1; Polynomial next = AppSAT.appSAT(pair.getRelationNumber()).multiply(pair.getFraction()); sum += pair.getFraction(); if (result == null) { result = next; } else { result = result.add(next); } } return new PolynomialSum(result, sum); } /** * Verify that a PairI object has valid values. * * @param pair * PairI object to verify */ private static void verifyPair(PairI pair) { if ((pair.getRelationNumber() < 0) || (pair.getRelationNumber() > 255)) { throw new IllegalArgumentException( "Pair's relation number must be between 0 and 255 inclusive. Got: " + pair.getRelationNumber()); } if ((pair.getFraction() < 0.0) || (pair.getFraction() > 1.0)) { throw new IllegalArgumentException( "Pair's fraction must be between 0.0 and 1.0 inclusive. Got: " + pair.getFraction()); } } /** * Private class used to return both the generated polynomial and sum of the * fractions generated from a list of PairI objects. */ private static class PolynomialSum { /** * Generated polynomial. */ public Polynomial polynomial; /** * Sum of PairI fractions */ public double sum; /** * Create a new result object. * * @param polynomial * Generated polynomial * @param sum * Sum of fractions */ public PolynomialSum(Polynomial polynomial, double sum) { this.polynomial = polynomial; this.sum = sum; } } }