00001 package edu.tum.cs.ias.knowrob.mod_dialog.queries;
00002
00003 import java.io.IOException;
00004 import java.util.Arrays;
00005 import java.util.HashMap;
00006 import java.util.Vector;
00007
00008 import edu.tum.cs.ias.knowrob.mod_dialog.DialogModule;
00009 import edu.tum.cs.logic.parser.ParseException;
00010 import edu.tum.cs.probcog.InferenceResult;
00011 import edu.tum.cs.probcog.Model;
00012 import edu.tum.cs.probcog.ModelPool;
00013 import edu.tum.cs.util.StringTool;
00014
00015 public class SetTable extends DialogQuery {
00016
00017 protected int participants;
00018 protected String mealType;
00019 protected String[] people;
00020 protected HashMap<Integer,String> participant2name = new HashMap<Integer,String>();
00021 protected HashMap<String,Integer> name2participant = new HashMap<String,Integer>();
00022 protected Vector<String[]> evidence = new Vector<String[]>();
00023 protected ModelPool pool;
00024 protected Model model;
00025 protected String regexUtensil, regexGood;
00026 protected HashMap<String,String> utensils = new HashMap<String,String>();
00027 protected HashMap<String,String> goods = new HashMap<String,String>();
00028
00029 public SetTable(DialogModule mod) throws IOException, ParseException, Exception {
00030 super(mod);
00031 registerStates();
00032 pool = new ModelPool(DialogModule.findRosPackage("srldb") + "/models/models.xml");
00033 model = pool.getModel("tableSetting_fall09");
00034
00035
00036 Vector<String[]> doms = model.getDomains();
00037 for(String[] dom : doms) {
00038 if(dom[0].equals("domutensilT")) {
00039 for(int i = 1; i < dom.length; i++)
00040 utensils.put(dom[i].toLowerCase(), dom[i]);
00041 regexUtensil = "(?:" + StringTool.join("|", utensils.keySet()) + ")";
00042 }
00043 if(dom[0].equals("objType_g")) {
00044 for(int i = 1; i < dom.length; i++)
00045 goods.put(dom[i].toLowerCase(), dom[i]);
00046 regexGood = "(?:" + StringTool.join("|", goods.keySet()) + ")";
00047 }
00048 }
00049 System.out.println("consumables: " + StringTool.join("|", goods.values()));
00050 System.out.println("usables: " + StringTool.join("|", utensils.values()));
00051 }
00052
00053 private void registerStates() {
00054 this.dialog_module.registerState("set_table_num_participants");
00055 this.dialog_module.registerState("set_table_family_members");
00056 this.dialog_module.registerState("set_table_meal_type");
00057 this.dialog_module.registerState("hypo_meal");
00058 }
00059
00060 public static String capitalize(String s) {
00061 return s.substring(0, 1).toUpperCase() + s.substring(1);
00062 }
00063
00064 @Override
00065 public String process(String q) throws IOException, ParseException, Exception {
00066 q = q.toLowerCase().replace(".", "").replace("?", "");
00067
00068 String regexPersonName = "(?:anna|bert|dorothy|emily|charly)";
00069 String regexMealType = "(?:breakfast|lunch|dinner)";
00070 String regexNumber = "(?:one|two|three|four)";
00071 String regexGeneralParticipant = String.format("(?:%s|participant %s)", regexPersonName, regexNumber);
00072
00073 if(match("start over", q)) {
00074 setTopLevelState();
00075 return "OK.";
00076 }
00077
00078 if(this.haveState(DialogModule.TOP_LEVEL_STATE)) {
00079 evidence.clear();
00080
00081
00082 if(match("(?:please )?set the table", q)) {
00083 setState("set_table_meal_type");
00084 return "OK. What kind of meal will it be?";
00085 }
00086
00087
00088 if(match(String.format("what does (%s) like to have for (%s)", regexPersonName, regexMealType), q)) {
00089 addEvidence("takesPartIn", "P1", "M");
00090 String name = capitalize(matcher.group(1));
00091 addEvidence("name", "P1", name);
00092 addEvidence("mealT", "M", capitalize(matcher.group(2)));
00093 Vector<InferenceResult> res = query("consumesAnyIn");
00094 String[] phrases = new String[]{"Almost always", "Quite often", "Sometimes"};
00095 Double[] probs = new Double[]{0.85, 0.5, 0.00001};
00096 String text = "";
00097 for(int i = 0; i < phrases.length; i++) {
00098 Vector<String> v = new Vector<String>();
00099 for(InferenceResult r : res) {
00100 double upper = i == 0 ? 1.0 : probs[i-1];
00101 if(r.probability >= probs[i] && r.probability < upper) {
00102 v.add(r.params[1]);
00103 }
00104 }
00105 if(!v.isEmpty()) {
00106 if(text != "") text += " ";
00107 text += phrases[i] + ", " + name + " likes to have " + StringTool.join(", ", v) + ".";
00108 }
00109 }
00110 return text;
00111 }
00112
00113
00114 if(match("suppose there was a meal", q)) {
00115 setState("hypo_meal");
00116 participants = 0;
00117 return "OK. How many participants were there?";
00118 }
00119 }
00120
00121 if(haveState("hypo_meal")) {
00122 if(participants == 0) {
00123 if(match(regexNumber, q)) {
00124 participants = parseNumber(matcher.group());
00125 if(participants > 0) {
00126 for(int i = 1; i <= participants; i++)
00127 addEvidence("takesPartIn", "P" + i, "M");
00128 return "OK. What else do we know about the meal?";
00129 }
00130 return "I don't understand. How many participants were there?";
00131 }
00132 return "I don't understand. How many participants were there?";
00133 }
00134 else {
00135 System.out.println("participants = " + participants);
00136 if(match("participant (" + regexNumber + ") was (" + regexPersonName + ")", q)) {
00137 int no = parseNumber(matcher.group(1));
00138 String name = matcher.group(2);
00139 this.name2participant.put(name, no);
00140 name = capitalize(name);
00141 addEvidence("name", "P" + no, name);
00142 this.participant2name.put(no, name);
00143 return "OK. Anything else?";
00144 }
00145 else if(match("(" + regexGeneralParticipant + ") used (?:an? )?(" + regexUtensil + ")", q)) {
00146 Integer no = getGeneralParticipant(matcher.group(1));
00147 if(no == null)
00148 return "I wasn't told that " + matcher.group(1) + " is one of the participants.";
00149 String utensil = utensils.get(matcher.group(2));
00150 addEvidence("usesAnyIn", "P" + no, utensil, "M");
00151 return "OK. Anything else?";
00152 }
00153 else if(match("(" + regexGeneralParticipant + ") consumed (?:an? )?(" + regexGood + ")", q)) {
00154 Integer no = getGeneralParticipant(matcher.group(1));
00155 if(no == null)
00156 return "I wasn't told that " + matcher.group(1) + " is one of the participants.";
00157 String good = goods.get(matcher.group(2));
00158 addEvidence("consumesAnyIn", "P" + no, good, "M");
00159 return "OK. Anything else?";
00160 }
00161 else if(match("the type of the meal was (" + regexMealType + ")", q)) {
00162 String type = capitalize(matcher.group(1));
00163 addEvidence("mealT", "M", type);
00164 return "OK. Anything else?";
00165 }
00166 else if(match("what type of meal was it", q)) {
00167 Vector<InferenceResult> res = query("mealT");
00168 return this.extractResults(res, 1);
00169 }
00170 else if(match("what time was it", q)) {
00171 Vector<InferenceResult> res = query("timeT");
00172 return this.extractResults(res, 1);
00173 }
00174 else if(match("who was participant (" + regexNumber + ")", q)) {
00175 int no = parseNumber(matcher.group(1));
00176 Vector<InferenceResult> res = query("name(P" + no + ")");
00177 return this.extractResults(res, 1);
00178 }
00179 else if(match(String.format("what did (%s) consume", regexGeneralParticipant), q)) {
00180 Integer no = getGeneralParticipant(matcher.group(1));
00181 if(no == null)
00182 return "I wasn't told that " + matcher.group(1) + " is one of the participants.";
00183 Vector<InferenceResult> res = query("consumesAnyIn(P" + no + ",x,M)");
00184 return this.extractResults(res, 1);
00185 }
00186 else if(match("what did (" + regexGeneralParticipant + ") use", q)) {
00187 Integer no = getGeneralParticipant(matcher.group(1));
00188 if(no == null)
00189 return "I wasn't told that " + matcher.group(1) + " is one of the participants.";
00190 Vector<InferenceResult> res = query("usesAnyIn(P" + no + ",x,M)");
00191 return this.extractResults(res, 1);
00192 }
00193 else
00194 return "I don't understand. What else do we know about the meal?";
00195 }
00196 }
00197
00198 if(haveState("set_table_meal_type")) {
00199 if(match(regexMealType, q)) {
00200 regexMealType = capitalize(matcher.group());
00201 setState("set_table_num_participants");
00202 return "OK. How many people will participate?";
00203 }
00204 }
00205
00206 if(haveState("set_table_num_participants")) {
00207 if(match("one|two|three|four", q)) {
00208 participants = parseNumber(matcher.group());
00209 setState("set_table_family_members");
00210 return "OK. Anyone family members I know?";
00211 }
00212 else {
00213 return "I don't understand. How many people will participate?";
00214 }
00215 }
00216
00217 if(haveState("set_table_family_members")) {
00218 people = null;
00219 String connect = "(?: and |,\\s?)";
00220 if(match(String.format("(%s(?:%s%s)*)", regexPersonName, connect, regexPersonName), q)) {
00221 people = matcher.group(1).split(connect);
00222 for(int i = 0; i < people.length; i++)
00223 people[i] = capitalize(people[i]);
00224 }
00225 else if(match("no|none", q)) {
00226 people = null;
00227 }
00228 else {
00229 return "I don't understand. Please name the family members or say 'none' if none will participate?";
00230 }
00231
00232 setTopLevelState();
00233
00234 return querySetTable();
00235 }
00236
00237 System.out.println("No match in SetTable");
00238
00239 return null;
00240 }
00241
00242 protected Integer getGeneralParticipant(String s) {
00243 if(s.startsWith("participant")) {
00244 int no = parseNumber(s.substring("participant ".length()));
00245 if(no == 0) {
00246 return null;
00247 }
00248 return no;
00249 }
00250 Integer no = name2participant.get(s);
00251 if(no == null)
00252 System.out.println("tried to retrieve '" + s + "' from " + StringTool.join(",", name2participant.keySet()));
00253 return no;
00254 }
00255
00256 protected String extractResults(Vector<InferenceResult> vres, int argNo) {
00257 StringBuffer ret = new StringBuffer();
00258 int i = 0;
00259 for(InferenceResult res : vres) {
00260 if(i++ > 0)
00261 ret.append(", ");
00262 ret.append(res.params[argNo] + " " + String.format("%.2f", res.probability));
00263 }
00264 return ret.toString();
00265 }
00266
00267 protected static int parseNumber(String no) {
00268 if(no.equals("one"))
00269 return 1;
00270 if(no.equals("two"))
00271 return 2;
00272 if(no.equals("three"))
00273 return 3;
00274 if(no.equals("four"))
00275 return 4;
00276 return 0;
00277 }
00278
00279 protected String querySetTable() {
00280
00281
00282
00283
00284 for(int i = 1; i <= this.participants; i++) {
00285 String person = "P" + i;
00286 addEvidence("takesPartIn", person, "M");
00287 if(people != null && i <= people.length)
00288 addEvidence("name", person, people[i-1]);
00289 }
00290 addEvidence("mealT", "M", mealType);
00291
00292
00293 Vector<InferenceResult> res;
00294 try {
00295 res = query("usesAnyIn");
00296 }
00297 catch (Exception e) {
00298 e.printStackTrace();
00299 return null;
00300 }
00301
00302 String text = "I will provide ";
00303 int cnt = 0;
00304 double threshold = 0.4;
00305 for(InferenceResult r : res) {
00306 r.print(System.out);
00307 if(r.probability > threshold) {
00308 String name;
00309 int i = Integer.parseInt(r.params[0].substring(1));
00310 if(people != null && i <= people.length)
00311 name = people[i-1];
00312 else
00313 name = "Participant " + i;
00314 String object = r.params[1];
00315 if(cnt++ > 0)
00316 text += ", ";
00317 text += String.format("a %s for %s", object, name);
00318 }
00319 }
00320
00321 return text;
00322 }
00323
00324 protected void addEvidence(String... items) {
00325 evidence.add(items);
00326 }
00327
00328 protected Vector<InferenceResult> query(String... queries) throws IOException, ParseException, Exception { System.out.println("evidence: " + evidence);
00329 Model m = this.model;
00330 m.setEvidence(evidence);
00331 m.instantiate();
00332 Vector<InferenceResult> res = m.infer(Arrays.asList(queries));
00333
00334 return res;
00335 }
00336 }