/** * computes the value of a variable via Prolog and adds it to the database * * @param sig * @param args * @return * @throws Exception */ protected boolean getPrologValue(Signature sig, String[] args, boolean forceAddToDatabase) throws Exception { String[] prologArgs = new String[args.length]; for (int j = 0; j < args.length; j++) prologArgs[j] = args[j].substring(0, 1).toLowerCase() + args[j].substring(1); boolean value = prolog.ask(Signature.formatVarName(sig.functionName, prologArgs)); VariableType var = makeVar(sig.functionName, args, value ? "True" : "False"); if (cachePrologValues || forceAddToDatabase) { boolean added = addVariable(var, false, false); if (added && debug) System.out.println("Prolog: computed " + var); } return value; }
/** * constructs an empty database for the given model * * @param model * @throws Exception */ public GenericDatabase(RelationalModel model) throws Exception { this.model = model; entries = new HashMap<String, VariableType>(); domains = new HashMap<String, HashSet<String>>(); functionalDependencies = new HashMap<RelationKey, HashMap<String, String[]>>(); taxonomy = model.getTaxonomy(); paramHandler = new ParameterHandler(this); paramHandler.add("debug", "setDebug"); paramHandler.add("debug", "setVerbose"); // initialize domains if (taxonomy != null) { entity2type = new HashMap<String, String>(); multiDomains = new HashMap<String, MultiIterator<String>>(); for (Concept c : model.getTaxonomy().getConcepts()) { domains.put(c.name, new HashSet<String>()); } } // fill domains with guaranteed domain elements for (Entry<String, ? extends Collection<String>> e : model.getGuaranteedDomainElements().entrySet()) { for (String element : e.getValue()) fillDomain(e.getKey(), element); } Collection<String> prologRules = model.getPrologRules(); prolog = new PrologKnowledgeBase(); if (prologRules != null && !prologRules.isEmpty()) { System.out.println("building Prolog knowledge base... "); for (String rule : prologRules) { try { System.out.println("telling " + rule); prolog.tell(rule); } catch (Throwable e) { System.out.println("DID catch"); throw new Exception("Error processing rule '" + rule + "'", e); } } } }
protected boolean addVariable( VariableType var, boolean ignoreUndefinedFunctions, boolean doPrologAssertions) throws Exception { if (immutable) throw new Exception("Tried to add a value to an immutable database"); boolean ret = false; String entryKey = var.getKeyString().toLowerCase(); if (entries.containsKey(entryKey)) return ret; // if(debug) System.out.println("adding var " + var); // fill domains Signature sig = model.getSignature(var.functionName); if (sig == null) { // if the predicate is not in the model, end here if (ignoreUndefinedFunctions) return ret; else throw new Exception( String.format( "Function %s appears in the data but is not declared in the model.", var.functionName)); } if (sig.isLogical && doPrologAssertions) { // for logically determined functions, assert any true instances to // the Prolog KB if (var.isTrue()) { String func = var.functionName; func = func.substring(0, 1).toLowerCase() + func.substring(1); String line = func + "("; for (String par : var.params) { line += par.substring(0, 1).toLowerCase() + par.substring(1) + ","; } line = line.substring(0, line.length() - 1) + ")"; if (debug) System.out.println("Prolog: asserted " + line); prolog.tell(line + "."); } } if (sig.argTypes.length != var.params.length) throw new Exception( "The database entry '" + var.getKeyString() + "' is not compatible with the signature definition of the corresponding function: expected " + sig.argTypes.length + " parameters as per the signature, got " + var.params.length + "."); // if(domains.get(sig.returnType) == null || !domains.get(sig.returnType).contains(var.value)) // System.out.println("adding " + var.value + " to " + sig.returnType + " because of " + var); if (!sig.isBoolean()) fillDomain(sig.returnType, var); for (int i = 0; i < sig.argTypes.length; i++) { // if(domains.get(sig.argTypes[i]) == null || // !domains.get(sig.argTypes[i]).contains(var.params[i])) // System.out.println("adding " + var.params[i] + " to " + sig.argTypes[i] + " because of " // + var); fillDomain(sig.argTypes[i], var.params[i]); } // add the entry to the main store entries.put(entryKey, var); ret = true; // update lookup tables for keys // (but only if value is true) Collection<RelationKey> keys = this.model.getRelationKeys(var.functionName); if (keys != null) { // add lookup entry if the variable value is true if (!var.isTrue()) return ret; // update all keys for (RelationKey key : keys) { // compute key for map entry StringBuffer sb = new StringBuffer(); int i = 0; for (Integer paramIdx : key.keyIndices) { if (i++ > 0) sb.append(','); sb.append(var.params[paramIdx]); } // add HashMap<String, String[]> hm = functionalDependencies.get(key); if (hm == null) { hm = new HashMap<String, String[]>(); functionalDependencies.put(key, hm); } hm.put(sb.toString(), var.params); } } return ret; }