package gve.calc.logic;
import java.util.Hashtable;
import gve.calc.formula.*;
public final class LogicFunctions implements Function {
public LogicFunctions() {}
public Part call(String funcname,Part args,Evaluator eval) {
if (funcname.equals("freevar"))
return new Brackets(freevar(args),Brackets.CURLY);
else if (funcname.equals("subst")) {
args = Brackets.unbracket(args);
if (args instanceof OperatorComma) {
Part arg1 = ((OperatorComma)args).left;
args = ((OperatorComma)args).right;
if (args instanceof OperatorComma) {
Part arg2 = ((OperatorComma)args).left;
Part arg3 = ((OperatorComma)args).right;
arg3 = (Part)arg3.clone(); // substitute on a clone of the input formula
if (arg2 instanceof Identifier)
return subst(arg1,((Identifier)arg2).getString(),arg3);
}
}
}
return null;
}
Replace all *free* occurrences of a variable in a formula by a term
PENDING: rotate inserted terms! |
public static final Part subst(Part term,String varname,Part formula) {
Formula f = new Formula(formula);
subst(term,varname,f);
return f.getRootPart();
}
public static final void subst(Part term,String varname,Formula f) {
subst(term,varname,f,f.getRootPart(),new Hashtable());
}
public static final void subst(Part term,String varname,Formula f,Part p,Hashtable gebonden) {
if (p instanceof Identifier) {
Identifier ident = (Identifier)p;
if (gebonden.get(ident.getString()) != null)
// deze variabele is gebonden
return;
if (ident.getString().equals(varname)) f.replace(p,(Part)term.clone());
else f.replace(p,(Identifier)p.clone());
return;
}
if (p instanceof OperatorQuantor) {
OperatorQuantor quantor = (OperatorQuantor)p;
if (quantor.child instanceof OperatorColon) {
// quantor met gebonden variabele
OperatorColon colon = (OperatorColon)quantor.child;
Part varpart = colon.left;
// Either Qvar:formula or Qvar in set:formula
if (varpart instanceof OperatorSet && ((OperatorSet)varpart).getKind()==OperatorSet.IN)
varpart = ((OperatorSet)varpart).left;
// Name of bounded var is in varpart now
if (varpart instanceof Identifier) {
String varnam = ((Identifier)varpart).getString();
gebonden.put(varnam,varnam);
Part result = freevar(colon.right,gebonden);
subst(term,varname,f,colon.right,gebonden);
gebonden.remove(varnam);
}
}
return;
}
// Default case
for (int i = 0; ;i++) {
Part child = p.getChild(i);
if (child == null) break;
subst(term,varname,f,child,gebonden);
}
}
Return a formula containing comma-delimited list of free variables inside
a formula |
public static final Part freevar(Part p) {
return freevar(p,new Hashtable());
}
private static Part freevar(Part p,Hashtable gebonden) {
if (p instanceof Identifier) {
Identifier ident = (Identifier)p;
if (gebonden.get(ident.getString()) != null)
// deze variabele is gebonden
return new Identifier("");
if (ident.isNumeric()) return new Identifier(""); // numerieke constante telt niet mee
return (Part)p.clone();
}
if (p instanceof OperatorQuantor) {
OperatorQuantor quantor = (OperatorQuantor)p;
if (quantor.child instanceof OperatorColon) {
// quantor met gebonden variabele
OperatorColon colon = (OperatorColon)quantor.child;
Part varpart = colon.left;
// Either Qvar:formula or Qvar in set:formula
if (varpart instanceof OperatorSet && ((OperatorSet)varpart).getKind()==OperatorSet.IN)
varpart = ((OperatorSet)varpart).left;
// Name of bounded var is in varpart now
if (varpart instanceof Identifier) {
String varname = ((Identifier)varpart).getString();
gebonden.put(varname,varname);
Part result = freevar(colon.right,gebonden);
gebonden.remove(varname);
return result;
}
}
}
// Default case: freevars of p is union of freevars of all children of p
Part result = null;
for (int i = 0; ;i++) {
Part child = p.getChild(i);
if (child == null) break;
Part fv = freevar(child,gebonden);
if (fv instanceof Identifier) {
Identifier fvIdent = (Identifier)fv;
if (fvIdent.getString().equals("")) continue; // fv is empty
// fv is one element; add to front of result
if (result == null) result = fv;
else result = new OperatorComma(fv,result);
} else if (fv instanceof OperatorComma) {
OperatorComma comma = (OperatorComma)fv;
if (result == null) result = comma;
else {
// Add result to end of fv
OperatorComma scan = comma;
while (true) {
if (scan.right instanceof OperatorComma)
scan = (OperatorComma)scan.right;
else {
scan.right = new OperatorComma(scan.right,result);
scan.right.setParent(scan);
result = fv;
break;
}
}
}
}
}
if (result == null) return new Identifier("");
else return result;
}
}