/******************************************************************************* * Copyright (C) 2008-2012 Dominik Jain. * * This file is part of ProbCog. * * ProbCog 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 3 of the License, or * (at your option) any later version. * * ProbCog 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 ProbCog. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package probcog.service; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; import probcog.logic.parser.ParseException; /** * Serves a pool of models (base class for specialized server interfaces); * the implementation here uses a dummy command pipe interface * @author Dominik Jain */ public class Server { ModelPool modelPool; public Server(String modelPoolFile) throws IOException, ParseException, Exception { modelPool = new ModelPool(modelPoolFile); } protected static Vector<String[]> readListOfLispTuples(String s) { Vector<String[]> ret = new Vector<String[]>(); s = s.substring(2, s.length()-2); // remove leading and trailing braces String[] tuples = s.split("\\)\\s*\\("); for(String tuple : tuples) ret.add(tuple.split("\\s+")); return ret; } /** * @deprecated * @param request * @return * @throws IOException * @throws ParseException * @throws Exception */ public Vector<InferenceResult> query(String request) throws IOException, ParseException, Exception { // get request components String[] qs = request.split(";"); String query = qs[0]; String evidence = qs[1]; // read queries Collection<String[]> queryTuples = readListOfLispTuples(query); Vector<String> queries = queriesFromTuples(queryTuples); // read evidence Collection<String[]> evidenceTuples = readListOfLispTuples(evidence); return query("tableSetting", queries, evidenceTuples); } public Vector<String[]> getPredicates(String modelName) { return modelPool.getModel(modelName).getPredicates(); } public Vector<String[]> getDomains(String modelName) { return modelPool.getModel(modelName).getDomains(); } public Model getModel(String modelName) { return modelPool.getModel(modelName); } /** * translates a list of LISP-style tuples, such as (sitsAtIn ?PERSON ?SEATING-LOCATION M), * to regular query strings, such as "sitsAtIn(a1,a2,M)" * @param queryTuples * @return collection of query strings */ protected static Vector<String> queriesFromTuples(Collection<String[]> queryTuples) { Vector<String> queries = new Vector<String>(); for(String[] tuple : queryTuples) { //System.out.println("tuple: (" + StringTool.join("," , tuple) + ")"); StringBuffer sb = new StringBuffer(tuple[0] + "("); for(int i = 1; i < tuple.length; i++) { if(i > 1) sb.append(','); if(tuple[i].charAt(0) == '?') sb.append("a" + i); else sb.append(tuple[i]); } sb.append(')'); System.out.println("query: " + sb.toString()); queries.add(sb.toString()); } return queries; } /** * processes a query by setting the evidence, instantiating the model and running the inference procedure * @param modelName the model to use * @param queries a collection of queries, i.e. either predicate/function names, partially grounded predicates/terms (variables in lower-case) or fully grounded predicates/terms * @param evidence a collection of arrays, where each array contains a predicate/function name followed by some arguments and finally the value. For a Boolean function, the value can be omitted (True is default). * @return a vector of inference results with constants already mapped * @throws Exception */ public Vector<InferenceResult> query(String modelName, Collection<String> queries, Collection<String[]> evidence) throws Exception { // get model Model model = modelPool.getModel(modelName); // set evidence model.setEvidence(evidence); // instantiate model and perform inference System.out.printf("instantiating model from %s\n", model.toString()); model.instantiate(); Vector<InferenceResult> results = model.infer(queries); // output evidence and results boolean verbose = true; if(verbose) { System.out.println("\nEvidence:"); for(String[] e : evidence) System.out.println(Arrays.toString(e)); System.out.println("\nResults:"); LinkedList<InferenceResult> sortedres = new LinkedList<InferenceResult>(results); Collections.sort(sortedres); for(InferenceResult r : sortedres) r.print(System.out); } // return results return results; } /** * processes a query by setting the evidence, instantiating the model and running the inference procedure * @param modelName * @param queries * @param evidence a list of evidence atoms, e.g. "foo(bar,baz)"; use an atom even if the variable is actually non-boolean, i.e. use "foo(bar,baz)" for "foo(bar)=baz" * @return a vector of inference results with constants already mapped * @throws Exception */ public Vector<InferenceResult> query(String modelName, Collection<String> queries, Iterable<String> evidence) throws Exception { // process the evidence Pattern atom = Pattern.compile("(\\w+)\\((.*?)\\)"); Vector<String[]> newEv = new Vector<String[]>(); for(String var : evidence) { Matcher m = atom.matcher(var); if(!m.matches()) throw new IllegalArgumentException("Evidence variable formatted incorrectly: " + var); String fName = m.group(1); String[] params = m.group(2).split("\\s*,\\s*"); String[] seq = new String[params.length+1]; seq[0] = fName; for(int i = 0; i < params.length; i++) seq[i+1] = params[i]; newEv.add(seq); } // call other query method return query(modelName, queries, newEv); } protected static String inferenceResults2LispTuples(Vector<InferenceResult> results) { StringBuffer sb = new StringBuffer('('); for(InferenceResult res : results) { sb.append('('); sb.append(res.functionName).append(' '); for(int i = 0; i < res.params.length; i++) sb.append(res.params[i]).append(' '); sb.append(res.probability); sb.append(')'); } sb.append(')'); return sb.toString(); } public static void main(String[] args) { try { Server server = new Server("/usr/wiss/jain/work/code/SRLDB/models/models.xml"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.err.println("ProbCog Server Test"); // test cases boolean testKnowRob = true; boolean testLISP = false; if(testKnowRob) { String modelName = "tableSetting_fall09"; Model model = server.getModel(modelName); // * evidence Vector<String> evidence = new Vector<String>(); evidence.add("takesPartIn(person1,meal1)"); evidence.add("mealT(meal1,Breakfast)"); boolean autoUsage = false; if(!autoUsage) { evidence.add("consumesAnyIn(person1,CowsMilk-Product,meal1)"); //evidence.add("consumesAnyIn(person1,Cereals,meal1)"); } else { String[] observedClasses = new String[]{"Milk", "Cereals"}; for(String instance : observedClasses) { String objType = instance; String constantType = model.getConstantType(objType); String predicate = null; if(constantType != null) { if(constantType.equalsIgnoreCase("domUtensilT")) predicate = "usesAnyIn"; else if(constantType.equalsIgnoreCase("objType_g")) predicate = "consumesAnyIn"; if(predicate != null) { String evidenceAtom = String.format("%s(P,%s,M)", predicate, objType); evidence.add(evidenceAtom); } else System.err.println("Warning: Evidence on instance '" + instance + "' not considered because it is neither a utensil nor a consumable object known to the model."); } else System.err.println("Warning: Evidence on instance '" + instance + "' not considered because its type is not known to the model."); } } // * queries Vector<String> queries = new Vector<String>(); queries.add("usesAnyIn"); queries.add("consumesAnyIn"); // * run inference Vector<InferenceResult> results = server.query(modelName, queries, evidence); System.out.println(); for(InferenceResult res : results) { res.print(System.out); } } if(testLISP) { String input = "((sitsAtIn ?PERSON ?SEATING-LOCATION M) (usesAnyIn ?PERSON ?UTENSIL M));((takesPartIn P1 M) (name P1 Anna) (takesPartIn P2 M) (name P2 Bert) (takesPartIn P3 M) (name P3 Dorothy) (mealT M Breakfast))"; String output = inferenceResults2LispTuples(server.query(input)); System.out.println(output); } // server loop while(true) { System.err.println("Waiting for Input"); String line = br.readLine(); if(line.equals("close")) { System.err.println("ProbCog Server closed"); break; } System.err.println("Received query: " + line); String result = inferenceResults2LispTuples(server.query(line)); System.out.println(result); } } catch(Exception e) { e.printStackTrace(); } } }