You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

340 lines
9.3 KiB

//==============================================================================
//
// Copyright (c) 2013-
// Authors:
// * Ernst Moritz Hahn <emhahn@cs.ox.ac.uk> (University of Oxford)
//
//------------------------------------------------------------------------------
//
// This file is part of PRISM.
//
// PRISM is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// PRISM is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with PRISM; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//==============================================================================
package param;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Random;
/**
* @author Ernst Moritz Hahn <emhahn@cs.ox.ac.uk> (University of Oxford)
* TODO complete once needed
*/
class DagFunctionFactory extends FunctionFactory {
private class Number extends DagOperator {
private BigInteger number;
Number(BigInteger number) {
super(number);
this.number = number;
}
BigInteger getNumber() {
return number;
}
@Override
public String toString() {
return number.toString();
}
}
private class Variable extends DagOperator {
private int variable;
Variable(int variable) {
super(randomPosition.getDimension(variable).getNum());
this.variable = variable;
}
int getVariable() {
return variable;
}
@Override
public String toString() {
return parameterNames[variable];
}
}
private class Negate extends DagOperator {
private DagOperator what;
Negate(DagOperator what) {
super(what.getCValue().negate());
this.what = what;
}
DagOperator getWhat() {
return what;
}
@Override
public String toString() {
return "-(" + what.toString() + ")";
}
}
private class Add extends DagOperator {
private DagOperator op1;
private DagOperator op2;
Add(DagOperator op1, DagOperator op2) {
super(op1.getCValue().add(op2.getCValue()));
this.op1 = op1;
this.op2 = op2;
}
DagOperator getOp1() {
return op1;
}
DagOperator getOp2() {
return op2;
}
@Override
public String toString() {
return "(" + op1.toString() + "+" + op2.toString() + ")";
}
}
private class Multiply extends DagOperator {
private DagOperator op1;
private DagOperator op2;
Multiply(DagOperator op1, DagOperator op2) {
super(op1.getCValue().multiply(op2.getCValue()));
this.op1 = op1;
this.op2 = op2;
}
DagOperator getOp1() {
return op1;
}
DagOperator getOp2() {
return op2;
}
@Override
public String toString() {
return "(" + op1.toString() + "*" + op2.toString() + ")";
}
}
private Point randomPosition;
private HashMap<DagOperator,DagOperator> polynomials;
private DagOperator zeroOp;
private DagOperator oneOp;
private DagFunction[] parameters;
private DagFunction zero;
private DagFunction one;
private DagFunction nan;
private DagFunction inf;
private DagFunction minf;
private HashMap<DagFunction,DagFunction> functions;
// private boolean negateToInner;
DagFunctionFactory(String[] parameterNames, BigRational[] lowerBounds, BigRational[] upperBounds, double maxProbWrong, boolean negateToInner) {
super(parameterNames, lowerBounds, upperBounds);
Random random = new Random();
BigRational[] randomPosArr = new BigRational[parameterNames.length];
int numRandomBits = (int) Math.ceil(Math.log(parameterNames.length / maxProbWrong) / Math.log(2));
for (int dim = 0; dim < parameterNames.length; dim++) {
BigInteger num = new BigInteger(numRandomBits, random);
randomPosArr[dim] = new BigRational(num, BigInteger.ONE);
}
randomPosition = new Point(randomPosArr);
polynomials = new HashMap<DagOperator,DagOperator>();
functions = new HashMap<DagFunction,DagFunction>();
zeroOp = new Number(BigInteger.ZERO);
polynomials.put(zeroOp,zeroOp);
oneOp = new Number(BigInteger.ONE);
polynomials.put(oneOp,oneOp);
zero = new DagFunction(this, zeroOp, oneOp);
functions.put(zero,zero);
one = new DagFunction(this, oneOp, oneOp);
functions.put(one,one);
nan = new DagFunction(this, DagFunction.NAN);
functions.put(nan,nan);
inf = new DagFunction(this, DagFunction.INF);
functions.put(inf,inf);
minf = new DagFunction(this, DagFunction.MINF);
functions.put(minf,minf);
parameters = new DagFunction[parameterNames.length];
for (int varNr = 0; varNr < parameterNames.length; varNr++) {
DagOperator paramOp = new Variable(varNr);
polynomials.put(paramOp,paramOp);
parameters[varNr] = new DagFunction(this, paramOp, oneOp);
functions.put(parameters[varNr],parameters[varNr]);
}
// this.negateToInner = negateToInner;
}
@Override
Function getZero() {
return zero;
}
@Override
Function getOne() {
return one;
}
@Override
Function getNaN() {
return nan;
}
@Override
Function getInf() {
return inf;
}
@Override
Function getMInf() {
return minf;
}
private DagOperator makeUnique(DagOperator op) {
DagOperator foundOp = polynomials.get(op);
if (foundOp == null) {
foundOp = op;
polynomials.put(foundOp, foundOp);
}
return foundOp;
}
private DagFunction makeUnique(DagFunction fn) {
DagFunction foundFn = functions.get(fn);
if (foundFn == null) {
foundFn = fn;
functions.put(foundFn, foundFn);
}
return foundFn;
}
@Override
Function fromBigRational(BigRational bigRat) {
bigRat = bigRat.cancel();
DagOperator num = new Number(bigRat.getNum());
num = makeUnique(num);
DagOperator den = new Number(bigRat.getDen());
den = makeUnique(den);
DagFunction result = new DagFunction(this, num, den);
return makeUnique(result);
}
@Override
Function getVar(int var) {
return parameters[var];
}
private DagOperator opMultiply(DagOperator op1, DagOperator op2) {
return makeUnique(new Multiply(op1, op2));
}
private DagOperator opAdd(DagOperator op1, DagOperator op2) {
return makeUnique(new Add(op1, op2));
}
private DagOperator opNegate(DagOperator op) {
return makeUnique(new Negate(op));
}
public Function add(DagFunction op1, DagFunction op2) {
DagOperator num = opAdd(opMultiply(op1.getNum(), op2.getDen()),
opMultiply(op1.getDen(), op2.getNum()));
DagOperator den = opMultiply(op1.getDen(), op2.getDen());
return makeUnique(new DagFunction(this, num, den));
}
public DagFunction negate(DagFunction dagFunction) {
DagOperator neg = opNegate(dagFunction.getNum());
return makeUnique(new DagFunction(this, neg, dagFunction.getDen()));
}
public Function subtract(DagFunction op1, DagFunction op2) {
DagFunction negOther = negate(op2);
return add(op1, negOther);
}
public Function multiply(DagFunction op1, DagFunction op2) {
DagOperator num = opMultiply(op1.getNum(), op2.getNum());
DagOperator den = opMultiply(op1.getDen(), op2.getDen());
return makeUnique(new DagFunction(this, num, den));
}
public Function divide(DagFunction op1, DagFunction op2) {
DagOperator num = opMultiply(op1.getNum(), op2.getDen());
DagOperator den = opMultiply(op1.getDen(), op2.getNum());
return makeUnique(new DagFunction(this, num, den));
}
public Function star(DagFunction op) {
DagOperator num = op.getDen();
DagOperator den = opAdd(op.getDen(), opNegate(op.getNum()));
return makeUnique(new DagFunction(this, num, den));
}
// TODO fix following
public Function toConstraint(DagFunction op) {
DagOperator num = op.getNum();
DagOperator den = oneOp;
return makeUnique(new DagFunction(this, num, den));
}
// TODO use cache for faster evaluation
private BigRational evaluate(DagOperator op, Point point) {
if (op instanceof Number) {
Number opNum = (Number) op;
return new BigRational(opNum.getNumber());
} else if (op instanceof Variable) {
Variable opVar = (Variable) op;
return point.getDimension(opVar.getVariable());
} else if (op instanceof Negate) {
Negate opNegate = (Negate) op;
return evaluate(opNegate.getWhat(), point).negate();
} else if (op instanceof Add) {
Add opAdd = (Add) op;
return evaluate(opAdd.getOp1(), point).add(evaluate(opAdd.getOp2(), point));
} else if (op instanceof Multiply) {
Multiply opMultiply = (Multiply) op;
return evaluate(opMultiply.getOp1(), point).multiply(evaluate(opMultiply.getOp2(), point));
} else {
throw new RuntimeException("invalid operator");
}
}
public BigRational evaluate(DagFunction op, Point point, boolean cancel) {
if (op.getType() == DagFunction.NAN) {
return BigRational.NAN;
}
return evaluate(op.getNum(), point).divide(evaluate(op.getDen(), point));
}
public BigRational asBigRational(DagFunction op) {
BigRational[] point = new BigRational[parameterNames.length];
for (int i = 0; i < parameterNames.length; i++) {
point[i] = BigRational.ZERO;
}
return evaluate(op, new Point(point), true);
}
public boolean isOne(DagFunction op) {
return op == one;
}
public boolean isZero(DagFunction op) {
return op == zero;
}
public String toString(DagFunction op) {
return "(" + op.getNum().toString() + ")/(" + op.getDen().toString() + ")";
}
}