00001 package edu.tum.cs.srl.bayesnets;
00002
00003 import java.util.Collection;
00004 import java.util.HashMap;
00005 import java.util.HashSet;
00006 import java.util.LinkedList;
00007 import java.util.Map;
00008 import java.util.Vector;
00009
00010 import edu.tum.cs.srl.Database;
00011 import edu.tum.cs.srl.RelationKey;
00012 import edu.tum.cs.srl.Signature;
00013 import edu.tum.cs.srl.taxonomy.Taxonomy;
00014 import edu.tum.cs.util.StringTool;
00015
00020 public class ParentGrounder {
00021
00022 protected class FunctionalLookup {
00023 protected RelationKey key;
00024 protected RelationalNode node;
00025
00026 public FunctionalLookup(RelationKey key, RelationalNode node) {
00027 this.key = key;
00028 this.node = node;
00029 }
00030
00039 public boolean doLookup(Database db, HashMap<String,String> varBindings) throws Exception {
00040
00041 String[] keyValues = new String[key.keyIndices.size()];
00042 int i = 0;
00043 for(Integer idxParam : key.keyIndices)
00044 keyValues[i++] = varBindings.get(node.params[idxParam]);
00045
00046 String[] params = db.getParameterSet(this.key, keyValues);
00047 if(params == null) {
00048
00049
00050 if(this.node.isPrecondition)
00051 return false;
00052
00053
00054 String[] buf = new String[node.params.length];
00055 for(int k = 0; k < node.params.length; k++) buf[k] = "_";
00056 int j = 0;
00057 for(Integer k : key.keyIndices) buf[k] = keyValues[j++];
00058 throw new Exception("Could not perform required lookup for " + Signature.formatVarName(node.getFunctionName(), buf));
00059 }
00060
00061 java.util.Iterator<Integer> iter = key.keyIndices.iterator();
00062 int nextKey = iter.next();
00063 for(i = 0; i < node.params.length; i++) {
00064 if(i == nextKey) {
00065 nextKey = iter.hasNext() ? iter.next() : -1;
00066 continue;
00067 }
00068 varBindings.put(node.params[i], params[i]);
00069 }
00070 return true;
00071 }
00072 }
00073
00074 protected Vector<FunctionalLookup> functionalLookups;
00075 protected RelationalNode mainNode;
00076 protected Collection<RelationalNode> parents;
00080 protected String[] ungroundedParams;
00081 protected String[] ungroundedParamDomains;
00082
00083 public ParentGrounder(RelationalBeliefNetwork bn, RelationalNode child) throws Exception {
00084 functionalLookups = new Vector<FunctionalLookup>();
00085 mainNode = child;
00086 parents = bn.getRelationalParents(child);
00087 ungroundedParams = child.addParams;
00088
00089
00090 HashSet<String> handledVars = new HashSet<String>();
00091
00092 for(String p : mainNode.params)
00093 handledVars.add(p);
00094
00095 if(mainNode.addParams != null)
00096 for(String p : mainNode.addParams)
00097 handledVars.add(p);
00098
00099
00100
00101 Taxonomy taxonomy = bn.getTaxonomy();
00102 if(ungroundedParams != null) {
00103 ungroundedParamDomains = new String[ungroundedParams.length];
00104 for(int i = 0; i < ungroundedParams.length; i++) {
00105 for(RelationalNode parent : parents) {
00106 for(int j = 0; j < parent.params.length; j++) {
00107 if(parent.params[j].equals(ungroundedParams[i])) {
00108 Signature sig = parent.getSignature();
00109 if(sig != null && !parent.isConstant) {
00110 if(sig.argTypes.length != parent.params.length)
00111 throw new Exception(String.format("Parameter count in signature %s (%d) does not match node %s (%d).", sig.toString(), sig.argTypes.length, parent.toString(), parent.params.length));
00112 if(ungroundedParamDomains[i] == null || taxonomy.query_isa(sig.argTypes[j], ungroundedParamDomains[i]))
00113 ungroundedParamDomains[i] = sig.argTypes[j];
00114 }
00115 }
00116 }
00117 }
00118 }
00119 }
00120
00121
00122 Collection<RelationalNode> workingSet = new LinkedList<RelationalNode>();
00123 for(RelationalNode p : parents)
00124 workingSet.add(p);
00125
00126 while(!workingSet.isEmpty()) {
00127 Collection<RelationalNode> newWorkingSet = new LinkedList<RelationalNode>();
00128
00129 int gains = 0;
00130 for(RelationalNode n : workingSet) {
00131 int numHandledParams = 0;
00132 FunctionalLookup flookup = null;
00133 Signature s = bn.getSignature(n);
00134
00135 for(String param : n.params) {
00136
00137 if(!handledVars.contains(param) && !RelationalNode.isConstant(param)) {
00138
00139
00140 if(flookup != null) {
00141 handledVars.add(param);
00142 ++numHandledParams;
00143 ++gains;
00144 }
00145
00146
00147 else {
00148 Collection<RelationKey> keys = bn.getRelationKeys(n.getFunctionName());
00149 if(keys != null) {
00150 for(RelationKey key : keys) {
00151 int c = 0;
00152 for(Integer keyParamIdx : key.keyIndices) {
00153 if(handledVars.contains(n.params[keyParamIdx]))
00154 ++c;
00155 }
00156 if(c == key.keyIndices.size()) {
00157
00158 handledVars.add(param);
00159 flookup = new FunctionalLookup(key, n);
00160 functionalLookups.add(flookup);
00161 ++numHandledParams;
00162 ++gains;
00163 break;
00164 }
00165 }
00166 }
00167 }
00168 }
00169 else
00170 ++numHandledParams;
00171 }
00172
00173 if(numHandledParams != n.params.length)
00174 newWorkingSet.add(n);
00175 }
00176
00177 if(gains == 0 && !newWorkingSet.isEmpty()) {
00178 throw new Exception("Could not determine how to ground parents of " + mainNode + "; some parameters of " + newWorkingSet + " could not be resolved; handled vars: " + handledVars);
00179 }
00180 workingSet = newWorkingSet;
00181 }
00182 }
00183
00184 @Override
00185 public String toString() {
00186 StringBuffer ret = new StringBuffer("<known from main node: ");
00187
00188 ret.append(StringTool.join(", ", mainNode.params));
00189
00190 ret.append("; functional lookups: ");
00191 int i = 0;
00192 for(FunctionalLookup fl : this.functionalLookups) {
00193 if(i++ > 0)
00194 ret.append(", ");
00195 ret.append(fl.key.toString());
00196 }
00197 ret.append(">");
00198 return ret.toString();
00199 }
00200
00208 public Map<Integer, String[]> generateParameterSets(String[] actualParameters, Database db) throws Exception {
00209 HashMap<Integer, String[]> m = new HashMap<Integer, String[]>();
00210 m.put(this.mainNode.index, actualParameters);
00211
00212 HashMap<String, String> varBindings = generateParameterBindings(actualParameters, db);
00213
00214 if(varBindings != null) {
00215 for(RelationalNode parent : this.parents) {
00216 String[] params = new String[parent.params.length];
00217 for(int i = 0; i < params.length; i++)
00218 params[i] = varBindings.get(parent.params[i]);
00219 m.put(parent.index, params);
00220 }
00221 return m;
00222 }
00223 else
00224 return null;
00225 }
00226
00233 public Vector<Map<Integer, String[]>> getGroundings(String[] actualParameters, Database db) throws Exception {
00234
00235 HashMap<String, String> paramBindings = generateParameterBindings(actualParameters, db);
00236 if(paramBindings == null)
00237 return null;
00238
00239 Vector<Map<Integer, String[]>> v = new Vector<Map<Integer, String[]>>();
00240 getCompleteGroundings(actualParameters, db, paramBindings, 0, v);
00241 return v;
00242 }
00243
00253 protected void getCompleteGroundings(String[] mainNodeParams, Database db, HashMap<String, String> paramBindings, int idx, Vector<Map<Integer, String[]>> ret) throws Exception {
00254 if(ungroundedParams == null || idx == ungroundedParams.length) {
00255
00256 HashMap<Integer, String[]> m = new HashMap<Integer, String[]>();
00257 m.put(this.mainNode.index, mainNodeParams);
00258 for(RelationalNode parent : this.parents) {
00259 String[] params = new String[parent.params.length];
00260 for(int i = 0; i < params.length; i++) {
00261 if(RelationalNode.isConstant(parent.params[i]))
00262 params[i] = parent.params[i];
00263 else
00264 params[i] = paramBindings.get(parent.params[i]);
00265 }
00266 m.put(parent.index, params);
00267 }
00268 ret.add(m);
00269 }
00270 else {
00271 String param = ungroundedParams[idx];
00272 Iterable<String> s = db.getDomain(ungroundedParamDomains[idx]);
00273 if(s == null)
00274 throw new Exception("Domain " + ungroundedParamDomains[idx] + " not found!");
00275 for(String constant : s) {
00276 paramBindings.put(param, constant);
00277 getCompleteGroundings(mainNodeParams, db, paramBindings, idx+1, ret);
00278 }
00279 }
00280 }
00281
00289 public HashMap<String, String> generateParameterBindings(String[] actualParameters, Database db) throws Exception {
00290 HashMap<String, String> bindings = new HashMap<String, String>();
00291
00292 for(int i = 0; i < mainNode.params.length; i++)
00293 bindings.put(mainNode.params[i], actualParameters[i]);
00294
00295 for(FunctionalLookup fl : this.functionalLookups)
00296 if(!fl.doLookup(db, bindings))
00297 return null;
00298 return bindings;
00299 }
00300 }