00001 package edu.tum.cs.srl.bayesnets;
00002
00003 import java.io.PrintStream;
00004 import java.util.Collection;
00005 import java.util.HashMap;
00006 import java.util.HashSet;
00007 import java.util.Map;
00008 import java.util.Set;
00009 import java.util.Vector;
00010
00011 import edu.ksu.cis.bnj.ver3.core.BeliefNode;
00012 import edu.ksu.cis.bnj.ver3.core.CPF;
00013 import edu.ksu.cis.bnj.ver3.core.Discrete;
00014 import edu.ksu.cis.bnj.ver3.core.Domain;
00015 import edu.ksu.cis.bnj.ver3.core.values.ValueDouble;
00016 import edu.tum.cs.bayesnets.core.BeliefNetworkEx;
00017 import edu.tum.cs.logic.Formula;
00018 import edu.tum.cs.logic.GroundAtom;
00019 import edu.tum.cs.srl.RelationKey;
00020 import edu.tum.cs.srl.RelationalModel;
00021 import edu.tum.cs.srl.Signature;
00022 import edu.tum.cs.srl.bayesnets.RelationalNode.Aggregator;
00023 import edu.tum.cs.srl.mln.MLNWriter;
00024 import edu.tum.cs.srl.taxonomy.Taxonomy;
00025 import edu.tum.cs.srldb.Database;
00026 import edu.tum.cs.util.StringTool;
00027 import edu.tum.cs.util.datastruct.CollectionFilter;
00028 import edu.tum.cs.util.datastruct.MultiIterator;
00029
00030 public class RelationalBeliefNetwork extends BeliefNetworkEx implements RelationalModel {
00034 protected HashMap<Integer,ExtendedNode> extNodesByIdx;
00038 protected Map<String, Signature> signatures;
00042 protected HashMap<String, String[]> guaranteedDomElements;
00046 protected Map<String, Collection<RelationKey>> relationKeys;
00050 protected Map<String, CombiningRule> combiningRules = new HashMap<String, CombiningRule>();
00051
00055 protected HashSet<String> evidenceFunctions = new HashSet<String>();
00056 protected Taxonomy taxonomy = null;
00057 protected Vector<String> prologRules = new Vector<String>();
00058
00059 public Collection<RelationKey> getRelationKeys(String relation) {
00060 return relationKeys.get(relation.toLowerCase());
00061 }
00062
00063 public RelationalBeliefNetwork(String networkFile) throws Exception {
00064 super(networkFile);
00065 extNodesByIdx = new HashMap<Integer, ExtendedNode>();
00066 signatures = new HashMap<String, Signature>();
00067 relationKeys = new HashMap<String, Collection<RelationKey>>();
00068 guaranteedDomElements = new HashMap<String, String[]>();
00069
00070 BeliefNode[] nodes = bn.getNodes();
00071 for(int i = 0; i < nodes.length; i++) {
00072 ExtendedNode n = createNode(nodes[i]);
00073 addExtendedNode(n);
00074 }
00075 }
00076
00083 protected ExtendedNode createNode(BeliefNode node) throws Exception {
00084 switch(node.getType()) {
00085 case BeliefNode.NODE_CHANCE:
00086 return new RelationalNode(this, node);
00087 case BeliefNode.NODE_DECISION:
00088 return new DecisionNode(this, node);
00089 default:
00090 throw new Exception("Don't know how to treat node " + node.getName() + " of type " + node.getType());
00091 }
00092 }
00093
00094 public void addExtendedNode(ExtendedNode node) {
00095 extNodesByIdx.put(node.index, node);
00096 }
00097
00103 public RelationalNode getRelationalNode(String name) {
00104 BeliefNode node = this.getNode(name);
00105 if(node == null)
00106 return null;
00107 return getRelationalNode(this.getNodeIndex(node));
00108 }
00109
00110 public RelationalNode getRelationalNode(int idx) {
00111 return (RelationalNode)getExtendedNode(idx);
00112 }
00113
00114 public RelationalNode getRelationalNode(BeliefNode node) {
00115 return (RelationalNode)getExtendedNode(node);
00116 }
00117
00118 public ExtendedNode getExtendedNode(int idx) {
00119 return extNodesByIdx.get(new Integer(idx));
00120 }
00121
00122 public ExtendedNode getExtendedNode(BeliefNode node) {
00123 return getExtendedNode(this.getNodeIndex(node));
00124 }
00125
00126 public Collection<ExtendedNode> getExtendedNodes() {
00127 return extNodesByIdx.values();
00128 }
00129
00130 public Iterable<RelationalNode> getRelationalNodes() {
00131 return new CollectionFilter<RelationalNode, ExtendedNode>(getExtendedNodes(), RelationalNode.class);
00132 }
00133
00134 public static boolean isBooleanDomain(Domain domain) {
00135 if(!(domain instanceof Discrete))
00136 return false;
00137 int order = domain.getOrder();
00138 if(order > 2 || order <= 0)
00139 return false;
00140 if(domain.getOrder() == 1) {
00141 if(domain.getName(0).equalsIgnoreCase("true") || domain.getName(0).equalsIgnoreCase("false"))
00142 return true;
00143 return false;
00144 }
00145 if(domain.getName(0).equalsIgnoreCase("true") || domain.getName(1).equalsIgnoreCase("true"))
00146 return true;
00147 return false;
00148 }
00149
00158 public String[] getParentVariableNames(RelationalNode node, String[] actualArgs) throws Exception {
00159 RelationalNode child = node;
00160 BeliefNode[] parents = bn.getParents(child.node);
00161 String[] ret = new String[parents.length];
00162 for(int i = 0; i < parents.length; i++) {
00163 RelationalNode parent = getRelationalNode(getNodeIndex(parents[i].getName()));
00164 StringBuffer varName = new StringBuffer(parent.getFunctionName() + "(");
00165 String param = null;
00166 for(int iCur = 0; iCur < parent.params.length; iCur++) {
00167 for(int iMain = 0; iMain < child.params.length; iMain++) {
00168 if(child.params[iMain].equals(parent.params[iCur])) {
00169 param = actualArgs[iMain];
00170 break;
00171 }
00172 }
00173 if(param == null)
00174 throw new Exception(String.format("Could not determine parameters of parent '%s' for node '%s'", parent.getFunctionName(), node.getFunctionName() + actualArgs.toString()));
00175 varName.append(param);
00176 if(iCur < parent.params.length-1)
00177 varName.append(",");
00178 }
00179 varName.append(")");
00180 ret[i] = varName.toString();
00181 }
00182 return ret;
00183 }
00184
00185 public void addSignature(String predicateName, Signature sig) {
00186
00187 String key = predicateName;
00188 signatures.put(predicateName, sig);
00189 }
00190
00191 public void addSignature(RelationalNode node, Signature sig) {
00192 addSignature(node.getFunctionName(), sig);
00193 }
00194
00200 public Signature getSignature(String functionName) {
00201 return signatures.get(functionName);
00202 }
00203
00204 public Signature getSignature(RelationalNode node) {
00205 return signatures.get(node.getFunctionName());
00206 }
00207
00208 public Collection<Signature> getSignatures() {
00209 return signatures.values();
00210 }
00211
00217 public void replaceType(String oldType, String newType) {
00218 for(Signature sig : getSignatures())
00219 sig.replaceType(oldType, newType);
00220 }
00221
00228 public void guessSignatures() throws Exception {
00229 for(RelationalNode node : getRelationalNodes()) {
00230 if(node.isConstant)
00231 continue;
00232 String[] argTypes = new String[node.params.length];
00233 for(int i = 0; i < node.params.length; i++) {
00234 String param = node.params[i].replaceAll("\\d+", "");
00235 argTypes[i] = "objType_" + param;
00236 }
00237 String retType = isBooleanDomain(((Discrete)node.node.getDomain())) ? "Boolean" : "dom" + node.getFunctionName();
00238 Signature sig = new Signature(node.getFunctionName(), retType, argTypes);
00239 addSignature(node.getFunctionName(), sig);
00240 }
00241 checkSignatures();
00242 }
00243
00248 protected void checkSignatures() throws Exception {
00249 for(RelationalNode node : getRelationalNodes()) {
00250 if(node.isFragment()) {
00251 MultiIterator<RelationalNode> relevantNodes = new MultiIterator<RelationalNode>();
00252 relevantNodes.add(node);
00253 relevantNodes.add(getRelationalParents(node));
00254 checkFragment(node, relevantNodes);
00255 }
00256 }
00257 }
00258
00259 protected void checkFragment(RelationalNode fragment, Iterable<RelationalNode> relevantNodes) throws Exception {
00260 HashMap<String,String> types = new HashMap<String,String>();
00261 for(RelationalNode node : relevantNodes) {
00262 if(node.isBuiltInPred())
00263 continue;
00264 if(node.isConstant) {
00265
00266 String type = types.get(node.getFunctionName());
00267 if(type == null)
00268 throw new Exception("Constant " + node + " not referenced and therefore not typed.");
00269 Signature sig = new Signature(node.getFunctionName(), type, new String[0]);
00270 addSignature(node, sig);
00271 }
00272 else {
00273 Signature sig = getSignature(node);
00274 if(sig == null) {
00275 throw new Exception("Node " + node + " has no signature!");
00276 }
00277
00278 if(sig.argTypes.length != node.params.length)
00279 throw new Exception(String.format("Signature of '%s' does not match node definition: It contains %d elements vs. %d elements in the node definition.", node.toString(), sig.argTypes.length, node.params.length));
00280 for(int i = 0; i < node.params.length; i++) {
00281 String key = node.params[i];
00282 String prevType = types.get(key);
00283 if(prevType == null)
00284 types.put(key, sig.argTypes[i]);
00285 else {
00286 if(!prevType.equals(sig.argTypes[i])) {
00287 boolean error = true;
00288 if(taxonomy != null && taxonomy.query_isa(prevType, sig.argTypes[i]))
00289 error = false;
00290 if(error)
00291 throw new Exception(String.format("Type mismatch while processing fragment '%s': '%s' has incompatible types '%s' and '%s'", fragment.getName(), key, prevType, sig.argTypes[i]));
00292 }
00293 }
00294 }
00295 }
00296 }
00297 }
00298
00304 public Vector<RelationalNode> getRelationalParents(RelationalNode node) {
00305 BeliefNode[] p = this.bn.getParents(node.node);
00306 Vector<RelationalNode> ret = new Vector<RelationalNode>();
00307 for(int i = 0; i < p.length; i++) {
00308 ExtendedNode n = getExtendedNode(p[i]);
00309 if(n instanceof RelationalNode)
00310 ret.add((RelationalNode)n);
00311 }
00312 return ret;
00313 }
00314
00323 public void toMLN(PrintStream out, boolean declarationsOnly, boolean compactFormulas, boolean numericWeights) throws Exception {
00324 MLNWriter writer = new MLNWriter(out);
00325
00326
00327 out.println("// domain declarations");
00328 HashSet<String> handled = new HashSet<String>();
00329 HashMap<String, Vector<String>> domains = new HashMap<String,Vector<String>>();
00330 for(RelationalNode node : getRelationalNodes()) {
00331 Signature sig = getSignature(node.getFunctionName());
00332 if(sig == null)
00333 continue;
00334 if(sig.returnType.equals("Boolean"))
00335 continue;
00336 if(handled.contains(sig.returnType))
00337 continue;
00338 handled.add(sig.returnType);
00339 Vector<String> d = new Vector<String>();
00340 out.printf("%s = {", Database.lowerCaseString(sig.returnType));
00341 String[] dom = getDiscreteDomainAsArray(node.node);
00342 for(int i = 0; i < dom.length; i++) {
00343 if(i > 0) out.print(", ");
00344 String elem = Database.upperCaseString(dom[i]);
00345 out.print(elem);
00346 d.add(elem);
00347 }
00348 out.println("}");
00349 domains.put(sig.returnType, d);
00350 }
00351 out.println();
00352
00353
00354
00355 out.println("// predicate declarations");
00356 Set<Signature> handledSigs = new HashSet<Signature>();
00357 for(RelationalNode node : getRelationalNodes()) {
00358 if(node.isConstant)
00359 continue;
00360 Signature sig = node.getSignature();
00361 if(sig == null) continue;
00362 if(handledSigs.contains(sig))
00363 continue;
00364 handledSigs.add(sig);
00365 String[] argTypes;
00366 if(sig.returnType.equals("Boolean"))
00367 argTypes = new String[sig.argTypes.length];
00368 else {
00369 argTypes = new String[sig.argTypes.length + 1];
00370 argTypes[argTypes.length-1] = Database.lowerCaseString(sig.returnType);
00371 }
00372 for(int i = 0; i < sig.argTypes.length; i++) {
00373 if(sig.argTypes[i].length() == 0)
00374 throw new Exception("Parameter " + i + " of " + sig.functionName + " has empty type: " + sig);
00375 argTypes[i] = Database.lowerCaseString(sig.argTypes[i]);
00376 }
00377 out.printf("%s(%s)\n", Database.lowerCaseString(sig.functionName), StringTool.join(", ", argTypes));
00378 }
00379 out.println();
00380
00381
00382
00383 out.println("// mutual exclusiveness and exhaustiveness");
00384
00385 for(RelationalNode node : getRelationalNodes()) {
00386 if(node.isConstant || node.isAuxiliary)
00387 continue;
00388 if(!node.isBoolean()) {
00389 out.print(Database.lowerCaseString(node.getFunctionName()));
00390 out.print('(');
00391 for(int i = 0; i <= node.params.length; i++) {
00392 if(i > 0) out.print(", ");
00393 out.printf("a%d", i);
00394 if(i == node.params.length) out.print('!');
00395 }
00396 out.println(")");
00397 }
00398 }
00399
00400 out.println();
00401
00402 if(declarationsOnly)
00403 return;
00404
00405
00406 int[] order = getTopologicalOrder();
00407 for(int i = 0; i < order.length; i++) {
00408 RelationalNode node = getRelationalNode(order[i]);
00409 if(node.isConstant || node.isAuxiliary)
00410 continue;
00411 CPT2MLNFormulas converter = new CPT2MLNFormulas(node);
00412
00413
00414 if(node.aggregator != null && node.parentMode != null) {
00415 if(node.aggregator == Aggregator.Average && node.parentMode.equals("CP")) {
00416
00417 RelationalNode rel = node.getFreeParamGroundingParent();
00418 if(rel == null)
00419 throw new Exception("Could not determine relevant relational parent");
00420
00421 String influenceRelation = String.format("inflfac_%s_%s", node.getFunctionName(), rel.getFunctionName());
00422 Signature sig = rel.getSignature();
00423 writer.writePredicateDecl(influenceRelation, sig.argTypes, null);
00424
00425 writer.writeMutexDecl(influenceRelation, rel.params, node.addParams);
00426
00427 converter.addPrecondition(Signature.formatVarName(influenceRelation, rel.params));
00428
00429 out.println("!" + rel.getCleanName() + " => !" + Signature.formatVarName(influenceRelation, rel.params) + ".");
00430 }
00431 else if(node.aggregator == Aggregator.NoisyOr) {
00432
00433 }
00434 }
00435
00436
00437 if(node.hasCPT()) {
00438 out.println("// CPT for " + node.getName());
00439 out.println("// <group>");
00440
00441 if(compactFormulas) {
00442
00443 converter.convert(out);
00444 }
00445 else {
00446
00447 CPF cpf = node.node.getCPF();
00448 int[] addr = new int[cpf.getDomainProduct().length];
00449 walkCPD_MLNformulas(out, cpf, addr, 0, converter.getPrecondition(), numericWeights);
00450 }
00451
00452 out.println("// </group>\n");
00453 }
00454 else {
00455 if(node.aggregator == Aggregator.NoisyOr) {
00456 out.print(writer.formatAsAtom(node.getCleanName()) + " <=> ");
00457 int k = 0;
00458 for(RelationalNode parent : node.getParents()) {
00459
00460 Vector<String> freeparams = new Vector<String>();
00461 for(String p : node.addParams)
00462 if(parent.hasParam(p))
00463 freeparams.add(p);
00464 if(freeparams.isEmpty())
00465 continue;
00466
00467 if(k++ > 0)
00468 out.print(" v ");
00469 out.print("EXIST " + StringTool.join(",", freeparams.toArray(new String[0])) + " " + writer.formatAsAtom(parent.toAtom()));
00470 }
00471 if(k == 0)
00472 throw new Exception("None of the parents of OR-node " + node + " handle any of the free parameters.");
00473 out.println();
00474 }
00475 }
00476 }
00477 }
00478
00486 public void toMLN(MLNConverter converter, boolean declarationsOnly, boolean compactFormulas) throws Exception {
00487
00488
00489 for(java.util.Map.Entry<String, String[]> e : this.getGuaranteedDomainElements().entrySet()) {
00490 converter.addGuaranteedDomainElements(e.getKey(), e.getValue());
00491 }
00492
00493
00494 for(Signature sig : this.getSignatures()) {
00495 Signature mlnSig = sig;
00496 if(!mlnSig.isBoolean()) {
00497 String[] argTypes = new String[sig.argTypes.length+1];
00498 for(int i = 0; i < sig.argTypes.length; i++)
00499 argTypes[i] = sig.argTypes[i];
00500 argTypes[argTypes.length-1] = sig.returnType;
00501 mlnSig = new Signature(sig.functionName, "Boolean", argTypes);
00502 converter.addFunctionalDependency(sig.functionName, argTypes.length-1);
00503 }
00504 converter.addSignature(mlnSig);
00505 }
00506
00507 if(declarationsOnly)
00508 return;
00509
00510
00511 int[] order = getTopologicalOrder();
00512 for(int i = 0; i < order.length; i++) {
00513 ExtendedNode extNode = getExtendedNode(order[i]);
00514 if(!(extNode instanceof RelationalNode))
00515 continue;
00516 RelationalNode node = (RelationalNode) extNode;
00517
00518 if(!node.isFragment())
00519 continue;
00520
00521
00522
00523
00524 if(!node.hasAggregator()) {
00525 converter.beginCPT(node);
00526
00527 CPT2MLNFormulas cptconverter = new CPT2MLNFormulas(node);
00528 if(compactFormulas) {
00529
00530 throw new RuntimeException("Compact formulas not yet supported");
00531 }
00532 else {
00533
00534 CPF cpf = node.node.getCPF();
00535 int[] addr = new int[cpf.getDomainProduct().length];
00536 walkCPD_MLNformulas(converter, cpf, addr, 0, cptconverter.getPrecondition(), true);
00537 }
00538
00539 converter.endCPT();
00540 }
00541
00542 else {
00543 Formula f = node.toFormula(null);
00544 if(f == null)
00545 throw new Exception("Don't know how to generate a formula for " + node);
00546 converter.addHardFormula(f);
00547 }
00548 }
00549 }
00550
00551 protected void walkCPD_MLNformulas(MLNConverter converter, CPF cpf, int[] addr, int i, String precondition, boolean numericWeights) throws Exception {
00552 BeliefNode[] nodes = cpf.getDomainProduct();
00553 if(i == addr.length) {
00554
00555 HashMap<String,String> constantValues = new HashMap<String,String>();
00556 for(int j = 0; j < addr.length; j++) {
00557 ExtendedNode extNode = getExtendedNode(nodes[j]);
00558 if(extNode instanceof RelationalNode) {
00559 RelationalNode rn = getRelationalNode(nodes[j]);
00560 if(rn.isConstant) {
00561 String value = ((Discrete)rn.node.getDomain()).getName(addr[j]);
00562 constantValues.put(rn.functionName, value);
00563 }
00564 }
00565 }
00566
00567 StringBuffer sb = new StringBuffer();
00568 for(int j = 0; j < addr.length; j++) {
00569 String conjunct = null;
00570 ExtendedNode extNode = getExtendedNode(nodes[j]);
00571 if(extNode instanceof DecisionNode) {
00572 conjunct = extNode.toString();
00573 }
00574 else {
00575 RelationalNode rn = (RelationalNode)extNode;
00576 if(!rn.isConstant)
00577 conjunct = rn.toLiteralString(addr[j], constantValues);
00578 }
00579 if(conjunct != null) {
00580 if(sb.length() > 0)
00581 sb.append(" ^ ");
00582 sb.append(conjunct);
00583 }
00584 }
00585 if(precondition != null) {
00586 sb.append(" ^ " + precondition);
00587 }
00588
00589 double weight = Math.log(cpf.getDouble(addr));
00590 if(Double.isInfinite(weight)) weight = -100.0;
00591
00592 Formula f;
00593 try {
00594 f = Formula.fromString(sb.toString());
00595 }
00596 catch(Error e) {
00597 System.err.println("Error parsing formula: " + sb.toString());
00598 throw e;
00599 }
00600 catch(Exception e) {
00601 System.err.println("Error parsing formula: " + sb.toString());
00602 throw e;
00603 }
00604 converter.addFormula(f, weight);
00605 }
00606 else {
00607
00608 boolean isPrecondition = false;
00609 ExtendedNode extNode = getExtendedNode(nodes[i]);
00610 RelationalNode node;
00611 if(extNode instanceof DecisionNode)
00612 isPrecondition = true;
00613 else {
00614 node = (RelationalNode) extNode;
00615 isPrecondition = node.isPrecondition;
00616 }
00617 Discrete dom = (Discrete)extNode.node.getDomain();
00618 if(isPrecondition) {
00619 addr[i] = dom.findName("True");
00620 if(addr[i] == -1)
00621 addr[i] = dom.findName("true");
00622 if(addr[i] == -1)
00623 throw new Exception("Domain of necessary precondition " + extNode + " must contain either 'True' or 'true'!");
00624 walkCPD_MLNformulas(converter, cpf, addr, i+1, precondition, numericWeights);
00625 }
00626
00627 else {
00628 for(int j = 0; j < dom.getOrder(); j++) {
00629 addr[i] = j;
00630 walkCPD_MLNformulas(converter, cpf, addr, i+1, precondition, numericWeights);
00631 }
00632 }
00633 }
00634 }
00635
00646 protected void walkCPD_MLNformulas(PrintStream out, CPF cpf, int[] addr, int i, String precondition, boolean numericWeights) throws Exception {
00647 BeliefNode[] nodes = cpf.getDomainProduct();
00648 if(i == addr.length) {
00649
00650 HashMap<String,String> constantValues = new HashMap<String,String>();
00651 for(int j = 0; j < addr.length; j++) {
00652 RelationalNode rn = getRelationalNode(nodes[j]);
00653 if(rn.isConstant) {
00654 String value = ((Discrete)rn.node.getDomain()).getName(addr[j]);
00655 constantValues.put(rn.functionName, value);
00656 }
00657 }
00658
00659 StringBuffer sb = new StringBuffer();
00660 for(int j = 0; j < addr.length; j++) {
00661 RelationalNode rn = getRelationalNode(nodes[j]);
00662 if(!rn.isConstant) {
00663 if(j > 0)
00664 sb.append(" ^ ");
00665 sb.append(rn.toLiteralString(addr[j], constantValues));
00666 }
00667 }
00668 if(precondition != null) {
00669 sb.append(" ^ " + precondition);
00670 }
00671
00672 int realAddr = cpf.addr2realaddr(addr);
00673 double value = ((ValueDouble)cpf.get(realAddr)).getValue();
00674 double weight = Math.log(value);
00675 if(Double.isInfinite(weight)) weight = -100.0;
00676
00677 if(numericWeights)
00678 out.printf("%f %s\n", weight, sb.toString());
00679 else
00680 out.printf("logx(%f) %s\n", value, sb.toString());
00681 }
00682 else {
00683
00684 RelationalNode node = getRelationalNode(nodes[i]);
00685 Discrete dom = (Discrete)node.node.getDomain();
00686 if(node.isPrecondition) {
00687 addr[i] = dom.findName("True");
00688 if(addr[i] == -1)
00689 addr[i] = dom.findName("true");
00690 if(addr[i] == -1)
00691 throw new Exception("Domain of necessary precondition " + node + " must contain either 'True' or 'true'!");
00692 walkCPD_MLNformulas(out, cpf, addr, i+1, precondition, numericWeights);
00693 }
00694
00695 else {
00696 for(int j = 0; j < dom.getOrder(); j++) {
00697 addr[i] = j;
00698 walkCPD_MLNformulas(out, cpf, addr, i+1, precondition, numericWeights);
00699 }
00700 }
00701 }
00702 }
00703
00704 public ParentGrounder getParentGrounder(RelationalNode node) throws Exception {
00705 return node.getParentGrounder();
00706 }
00707
00708 public void addRelationKey(RelationKey k) {
00709 Collection<RelationKey> list = relationKeys.get(k.relation.toLowerCase());
00710 if(list == null) {
00711 list = new Vector<RelationKey>();
00712 relationKeys.put(k.relation.toLowerCase(), list);
00713 }
00714 list.add(k);
00715
00716
00717 }
00718
00723 public void prepareForLearning() throws Exception {
00724 for(RelationalNode node : getRelationalNodes()) {
00725 if(node.parentMode != null && node.parentMode.equals("AUX")) {
00726
00727 String[] params = new String[node.params.length + node.addParams.length];
00728 int i = 0;
00729 for(int j = 0; j < node.params.length; j++)
00730 params[i++] = node.params[j];
00731 for(int j = 0; j < node.addParams.length; j++)
00732 params[i++] = node.addParams[j];
00733 String fullName = Signature.formatVarName(node.getFunctionName() + "_" + StringTool.join("", node.addParams), params);
00734 BeliefNode fullyGroundedNode = this.addNode(fullName);
00735 fullyGroundedNode.setDomain(node.node.getDomain());
00736
00737 RelationalNode fullyGroundedRelNode = new RelationalNode(this, fullyGroundedNode);
00738 addExtendedNode(fullyGroundedRelNode);
00739
00740 String[] argTypes = new String[params.length];
00741 Signature origSig = node.getSignature();
00742 Vector<RelationalNode> relParents = getRelationalParents(node);
00743 for(int j = 0; j < params.length; j++) {
00744 if(j < node.params.length)
00745 argTypes[j] = origSig.argTypes[j];
00746 else {
00747 boolean haveType = false;
00748 for(int k = 0; k < relParents.size() && !haveType; k++) {
00749 RelationalNode parent = relParents.get(k);
00750 Signature sig = parent.getSignature();
00751 for(int l = 0; l < parent.params.length; l++) {
00752 if(parent.params[l].equals(params[j])) {
00753 argTypes[j] = sig.argTypes[l];
00754 haveType = true;
00755 break;
00756 }
00757 }
00758 }
00759 if(!haveType)
00760 throw new Exception("Could not determine type of free parameter " + params[j]);
00761 }
00762 }
00763
00764 addSignature(fullyGroundedRelNode, new Signature(fullyGroundedRelNode.getFunctionName(), origSig.returnType, argTypes));
00765
00766 BeliefNode[] parents = this.bn.getParents(node.node);
00767 for(BeliefNode parent : parents) {
00768 this.bn.disconnect(parent, node.node);
00769 this.bn.connect(parent, fullyGroundedNode);
00770 }
00771
00772 this.bn.connect(fullyGroundedNode, node.node);
00773
00774 node.parentMode = "";
00775 node.setLabel();
00776
00777 }
00778 }
00779
00780 }
00781
00782 public HashMap<String, String[]> getGuaranteedDomainElements() {
00783 return guaranteedDomElements;
00784 }
00785
00790 public String gndAtom2VarName(GroundAtom ga) {
00791 if(getSignature(ga.predicate).isBoolean())
00792 return ga.toString();
00793 else {
00794 StringBuffer s = new StringBuffer(ga.predicate + "(");
00795 for(int i = 0; i < ga.args.length-1; i++) {
00796 if(i > 0)
00797 s.append(',');
00798 s.append(ga.args);
00799 }
00800 s.append(')');
00801 return s.toString();
00802 }
00803 }
00804
00805 @Override
00806 public BeliefNode getNode(String name) {
00807 throw new RuntimeException("This method should never be called in relational networks because they may contain several nodes with the same name, so the mapping may not be well-defined.");
00808 }
00809
00810 @Override
00811 public int getNodeIndex(String nodeName) {
00812 throw new RuntimeException("This method should never be called in relational networks because they may contain several nodes with the same name.");
00813 }
00814
00815 public boolean isBoolean(String functionName) {
00816 return getSignature(functionName).isBoolean();
00817 }
00818
00823 public void setEvidenceFunction(String functionName) {
00824 this.evidenceFunctions.add(functionName);
00825 }
00826
00827 public boolean isEvidenceFunction(String functionName) {
00828 return evidenceFunctions.contains(functionName);
00829 }
00830
00831 public Taxonomy getTaxonomy() {
00832 return taxonomy;
00833 }
00834
00835 @Override
00836 public Collection<String> getPrologRules() {
00837 return prologRules;
00838 }
00839
00840 public CombiningRule getCombiningRule(String function) {
00841 return this.combiningRules.get(function);
00842 }
00843 }
00844
00845