From d5d73003d222dfb71ca8ec38600e25964fa66a46 Mon Sep 17 00:00:00 2001 From: Woody Folsom Date: Sun, 11 Mar 2012 16:49:20 -0400 Subject: [PATCH] Work in progress. --- data/survey.xml | 628 ++++++++++++++++++ ...{survey_dataset.xml => survey_recipes.xml} | 4 +- src/net/woodyfolsom/cs6601/p2/BayesChef.java | 28 + src/net/woodyfolsom/cs6601/p2/Diner.java | 25 + src/net/woodyfolsom/cs6601/p2/Survey.java | 42 ++ .../woodyfolsom/cs6601/p2/SurveyReader.java | 13 + .../woodyfolsom/cs6601/p2/XStreamFactory.java | 6 +- test/dkohl/bayes/example/FoodExampleTest.java | 4 +- .../example/builders/FoodExampleBuilder.java | 32 +- .../cs6601/p2/RecipeBookReaderTest.java | 23 +- .../cs6601/p2/RecipeReaderTest.java | 31 + .../cs6601/p2/SurveyDatasetReaderTest.java | 40 -- .../cs6601/p2/SurveyReaderTest.java | 24 + 13 files changed, 833 insertions(+), 67 deletions(-) create mode 100644 data/survey.xml rename data/{survey_dataset.xml => survey_recipes.xml} (99%) create mode 100644 src/net/woodyfolsom/cs6601/p2/BayesChef.java create mode 100644 src/net/woodyfolsom/cs6601/p2/Diner.java create mode 100644 src/net/woodyfolsom/cs6601/p2/Survey.java create mode 100644 src/net/woodyfolsom/cs6601/p2/SurveyReader.java create mode 100644 test/net/woodyfolsom/cs6601/p2/RecipeReaderTest.java delete mode 100644 test/net/woodyfolsom/cs6601/p2/SurveyDatasetReaderTest.java create mode 100644 test/net/woodyfolsom/cs6601/p2/SurveyReaderTest.java diff --git a/data/survey.xml b/data/survey.xml new file mode 100644 index 0000000..f2f9937 --- /dev/null +++ b/data/survey.xml @@ -0,0 +1,628 @@ + + + + + 0 + Honey cake + + + 1 + Kahlua Cake + + + 2 + Ice Cream, Lowfat + + + 3 + Southwest Smoothie + + + 4 + Margarita Sunrise + + + 5 + Breaded Veal Cutlet ( Weinerschnitzel ) + + + 6 + Blender Double Fudge Cake + + + 7 + Chinese: Cashew Chicken 1 + + + 8 + Bayou Shrimp Creole + + + 9 + Crab Burgers + + + 10 + Broiled Flounder + + + 11 + Coconut Beer Batter Shrimp + + + 12 + Coconut Fish Curry + + + 13 + Catalan Rice + + + 14 + Baked Steak And Lima Beans + + + 15 + Tabasco Classic - Perfect Seared Steaks **** + + + 16 + Salisbury Steak with Mushroom Sauce + + + 17 + Meatless Loaf + + + 18 + Black Bean Soup + + + 29 + Fava Bean Burgers + + + 20 + Angel Hair Pesto Primavera + + + 21 + EGGPLANT LASAGNE + + + + + 0 + + chocolate + + + + 1 + + nuts + + + + 2 + + shellfish + + + + + 0 + + + 0 + 10 + + + 1 + 10 + + + 2 + 10 + + + 3 + 10 + + + 4 + 10 + + + 5 + 10 + + + 6 + 10 + + + 7 + 10 + + + 8 + 10 + + + 9 + 10 + + + 10 + 10 + + + 11 + 10 + + + 12 + 10 + + + 13 + 10 + + + 14 + 10 + + + 15 + 10 + + + 16 + 10 + + + 17 + 10 + + + 18 + 10 + + + 19 + 10 + + + 20 + 10 + + + + + 0 + false + + + 1 + false + + + 2 + false + + + + + 1 + + + 0 + 10 + + + 1 + 10 + + + 2 + 10 + + + 3 + 10 + + + 4 + 10 + + + 5 + 10 + + + 6 + 10 + + + 7 + 10 + + + 8 + 10 + + + 9 + 10 + + + 10 + 10 + + + 11 + 10 + + + 12 + 10 + + + 13 + 10 + + + 14 + 10 + + + 15 + 10 + + + 16 + 10 + + + 17 + 10 + + + 18 + 10 + + + 19 + 10 + + + 20 + 10 + + + + + 0 + false + + + 1 + false + + + 2 + false + + + + + 2 + + + 0 + 10 + + + 1 + 10 + + + 2 + 10 + + + 3 + 10 + + + 4 + 10 + + + 5 + 10 + + + 6 + 10 + + + 7 + 10 + + + 8 + 10 + + + 9 + 10 + + + 10 + 10 + + + 11 + 10 + + + 12 + 10 + + + 13 + 10 + + + 14 + 10 + + + 15 + 10 + + + 16 + 10 + + + 17 + 10 + + + 18 + 10 + + + 19 + 10 + + + 20 + 10 + + + + + 0 + false + + + 1 + false + + + 2 + false + + + + + 3 + + + 0 + 10 + + + 1 + 10 + + + 2 + 10 + + + 3 + 10 + + + 4 + 10 + + + 5 + 10 + + + 6 + 10 + + + 7 + 10 + + + 8 + 10 + + + 9 + 10 + + + 10 + 10 + + + 11 + 10 + + + 12 + 10 + + + 13 + 10 + + + 14 + 10 + + + 15 + 10 + + + 16 + 10 + + + 17 + 10 + + + 18 + 10 + + + 19 + 10 + + + 20 + 10 + + + + + 0 + false + + + 1 + false + + + 2 + false + + + + + 4 + + + 0 + 10 + + + 1 + 10 + + + 2 + 10 + + + 3 + 10 + + + 4 + 10 + + + 5 + 10 + + + 6 + 10 + + + 7 + 10 + + + 8 + 10 + + + 9 + 10 + + + 10 + 10 + + + 11 + 10 + + + 12 + 10 + + + 13 + 10 + + + 14 + 10 + + + 15 + 10 + + + 16 + 10 + + + 17 + 10 + + + 18 + 10 + + + 19 + 10 + + + 20 + 10 + + + + + 0 + false + + + 1 + false + + + 2 + false + + + + \ No newline at end of file diff --git a/data/survey_dataset.xml b/data/survey_recipes.xml similarity index 99% rename from data/survey_dataset.xml rename to data/survey_recipes.xml index 8179dba..74ace57 100644 --- a/data/survey_dataset.xml +++ b/data/survey_recipes.xml @@ -1,5 +1,7 @@ - + + Honey cake diff --git a/src/net/woodyfolsom/cs6601/p2/BayesChef.java b/src/net/woodyfolsom/cs6601/p2/BayesChef.java new file mode 100644 index 0000000..80c0d8a --- /dev/null +++ b/src/net/woodyfolsom/cs6601/p2/BayesChef.java @@ -0,0 +1,28 @@ +package net.woodyfolsom.cs6601.p2; + +import java.io.File; + +public class BayesChef { + + public static void main(String... args) { + System.out.println("Reading recipe book."); + RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/survey_recipes.xml")); + + System.out.println("Read data for " + recipeBook.getSize() + " recipes."); + + System.out.println("Reading survey data."); + Survey survey = SurveyReader.readSurvey(new File("data/survey.xml")); + + System.out.println("Read data for " + survey.getDinerCount() + " diner(s)."); + + System.out.println("Setting evidence for first 11 recipes."); + + System.out.println("Evaluating preference for remaining recipes."); + + System.out.println("RMSE for recipes #12-22 (calculated vs. surveyed preference):"); + + for (int dinerIndex = 0; dinerIndex < survey.getDinerCount(); dinerIndex++) { + System.out.println("Diner # " + (dinerIndex + 1) + "..."); + } + } +} diff --git a/src/net/woodyfolsom/cs6601/p2/Diner.java b/src/net/woodyfolsom/cs6601/p2/Diner.java new file mode 100644 index 0000000..2b70f7c --- /dev/null +++ b/src/net/woodyfolsom/cs6601/p2/Diner.java @@ -0,0 +1,25 @@ +package net.woodyfolsom.cs6601.p2; + +import java.util.HashMap; +import java.util.Map; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("diner") +public class Diner { + private int id; + private Map ratings = new HashMap(); + private Map allergies = new HashMap(); + + public int getId() { + return id; + } + + public int getRating(int dishId) { + return ratings.get(dishId); + } + + public boolean isAllergic(int categoryId) { + return allergies.get(categoryId); + } +} diff --git a/src/net/woodyfolsom/cs6601/p2/Survey.java b/src/net/woodyfolsom/cs6601/p2/Survey.java new file mode 100644 index 0000000..877c872 --- /dev/null +++ b/src/net/woodyfolsom/cs6601/p2/Survey.java @@ -0,0 +1,42 @@ +package net.woodyfolsom.cs6601.p2; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamImplicit; + +@XStreamAlias("survey") +public class Survey { + private Map dishes = new HashMap(); + private Map categories = new HashMap(); + + @XStreamImplicit(itemFieldName="diner") + private List diners = new ArrayList(); + + public Diner getDiner(int dinerIndex) { + return diners.get(dinerIndex); + } + + public int getDinerCount() { + return diners.size(); + } + + public String getDish(int dishId) { + return dishes.get(dishId); + } + + public int getDishCount() { + return dishes.size(); + } + + public String getCategory(int catId) { + return categories.get(catId); + } + + public int getCategoryCount() { + return categories.size(); + } +} diff --git a/src/net/woodyfolsom/cs6601/p2/SurveyReader.java b/src/net/woodyfolsom/cs6601/p2/SurveyReader.java new file mode 100644 index 0000000..f1c6be2 --- /dev/null +++ b/src/net/woodyfolsom/cs6601/p2/SurveyReader.java @@ -0,0 +1,13 @@ +package net.woodyfolsom.cs6601.p2; + +import java.io.File; + +import com.thoughtworks.xstream.XStream; + +public class SurveyReader { + private static XStream xstream = XStreamFactory.getInstance(); + + public static Survey readSurvey(File surveyFile) { + return (Survey) xstream.fromXML(surveyFile); + } +} diff --git a/src/net/woodyfolsom/cs6601/p2/XStreamFactory.java b/src/net/woodyfolsom/cs6601/p2/XStreamFactory.java index ba58bf5..de72af6 100644 --- a/src/net/woodyfolsom/cs6601/p2/XStreamFactory.java +++ b/src/net/woodyfolsom/cs6601/p2/XStreamFactory.java @@ -10,9 +10,9 @@ public class XStreamFactory { public static XStream getInstance() { XStream xstream = new XStream(new DomDriver()); + ///RecipeBook xstream.processAnnotations(RecipeBook.class); - xstream.processAnnotations(Recipe.class); xstream.omitField(Recipe.class, "directions"); @@ -32,6 +32,10 @@ public class XStreamFactory { xstream.omitField(Ingredient.class, "amt"); xstream.omitField(Ingredient.class, "prep"); + ///Survey + xstream.processAnnotations(Survey.class); + xstream.processAnnotations(Diner.class); + return xstream; } } diff --git a/test/dkohl/bayes/example/FoodExampleTest.java b/test/dkohl/bayes/example/FoodExampleTest.java index 11519be..b75ac77 100644 --- a/test/dkohl/bayes/example/FoodExampleTest.java +++ b/test/dkohl/bayes/example/FoodExampleTest.java @@ -34,9 +34,9 @@ public class FoodExampleTest { + table.getAssignments().get(assignment).getProbability()); } - System.out.println("MEET: "); + System.out.println("MEAT: "); table = (ProbabilityTable) net.getNodes().get( - FoodExampleBuilder.CONTAINS_MEET); + FoodExampleBuilder.CONTAINS_MEAT); for (String name : table.getNames()) { System.out.print(name + " "); } diff --git a/test/dkohl/bayes/example/builders/FoodExampleBuilder.java b/test/dkohl/bayes/example/builders/FoodExampleBuilder.java index ddf6424..b3b100f 100644 --- a/test/dkohl/bayes/example/builders/FoodExampleBuilder.java +++ b/test/dkohl/bayes/example/builders/FoodExampleBuilder.java @@ -19,7 +19,7 @@ public class FoodExampleBuilder { public static final String TASTE = "Taste"; public static final String SOMEONE_VEGETARIAN = "Vegetarian"; - public static final String CONTAINS_MEET = "Meet"; + public static final String CONTAINS_MEAT = "Meat"; public static final String CONTAINS_VEGETABLE = "Vegetable"; public static final String CONTAINS_BEEF = "Beef"; public static final String CONTAINS_PORK = "Pork"; @@ -35,7 +35,7 @@ public class FoodExampleBuilder { "6", "7", "8", "9", "10" }; private static final String[] VARIABLES = { SOMEONE_VEGETARIAN, - CONTAINS_BEEF, CONTAINS_MEET, CONTAINS_PORK, CONTAINS_POTATOS, + CONTAINS_BEEF, CONTAINS_MEAT, CONTAINS_PORK, CONTAINS_POTATOS, CONTAINS_TOMATOS, CONTAINS_VEGETABLE, TASTE }; private static final String[] OBSERVED = { CONTAINS_BEEF, CONTAINS_PORK, @@ -59,13 +59,13 @@ public class FoodExampleBuilder { return new LinkedList(assignment); } - public static Ontology onto() { + public static Ontology createOntology() { HashSet classes = new HashSet(); - classes.add(CONTAINS_MEET); + classes.add(CONTAINS_MEAT); classes.add(CONTAINS_VEGETABLE); Ontology onthology = new Ontology(classes); - onthology.define(CONTAINS_PORK, CONTAINS_MEET); - onthology.define(CONTAINS_BEEF, CONTAINS_MEET); + onthology.define(CONTAINS_PORK, CONTAINS_MEAT); + onthology.define(CONTAINS_BEEF, CONTAINS_MEAT); onthology.define(CONTAINS_TOMATOS, CONTAINS_VEGETABLE); onthology.define(CONTAINS_POTATOS, CONTAINS_VEGETABLE); @@ -146,7 +146,7 @@ public class FoodExampleBuilder { public static DataSet examples() { DataSet data = new DataSet(); - Ontology onto = onto(); + Ontology onto = createOntology(); // user one ratings data.add(normalize(porkTomatoDish(10), onto)); data.add(normalize(porkPotatoDish(9), onto)); @@ -184,19 +184,19 @@ public class FoodExampleBuilder { } public static ProbabilityDistribution beef() { - String names[] = { CONTAINS_MEET, CONTAINS_BEEF }; + String names[] = { CONTAINS_MEAT, CONTAINS_BEEF }; ProbabilityTable table = new ProbabilityTable(names); return table; } public static ProbabilityDistribution pork() { - String names[] = { CONTAINS_MEET, CONTAINS_PORK }; + String names[] = { CONTAINS_MEAT, CONTAINS_PORK }; ProbabilityTable table = new ProbabilityTable(names); return table; } public static ProbabilityDistribution meet() { - String names[] = { SOMEONE_VEGETARIAN, CONTAINS_MEET }; + String names[] = { SOMEONE_VEGETARIAN, CONTAINS_MEAT }; ProbabilityTable table = new ProbabilityTable(names); return table; } @@ -229,7 +229,7 @@ public class FoodExampleBuilder { public static BayesNet dishNet() { BayesNet net = new BayesNet(VARIABLES); net.setDistribution(new Variable(SOMEONE_VEGETARIAN, DOMAIN), vegi()); - net.setDistribution(new Variable(CONTAINS_MEET, DOMAIN), meet()); + net.setDistribution(new Variable(CONTAINS_MEAT, DOMAIN), meet()); net.setDistribution(new Variable(CONTAINS_VEGETABLE, DOMAIN), vegetables()); net.setDistribution(new Variable(CONTAINS_BEEF, DOMAIN), beef()); @@ -238,19 +238,19 @@ public class FoodExampleBuilder { net.setDistribution(new Variable(CONTAINS_TOMATOS, DOMAIN), tomatos()); net.setDistribution(new Variable(TASTE, RATING_DOMAIN), taste()); - Ontology onthology = onto(); - for (String category : onthology.getClasses()) { + Ontology ontology = createOntology(); + for (String category : ontology.getClasses()) { net.connect(category, SOMEONE_VEGETARIAN); } for (String thing : OBSERVED) { - net.connect(thing, onthology.getInheritance().get(thing)); + net.connect(thing, ontology.getInheritance().get(thing)); net.connect(TASTE, thing); } - for (String category : onthology.getClasses()) { + for (String category : ontology.getClasses()) { MaximumLikelihoodEstimation.estimate(examples(), net, category); - for (String thing : onthology.getClasses2thing().get(category)) { + for (String thing : ontology.getClasses2thing().get(category)) { MaximumLikelihoodEstimation.estimate(examples(), net, thing); } } diff --git a/test/net/woodyfolsom/cs6601/p2/RecipeBookReaderTest.java b/test/net/woodyfolsom/cs6601/p2/RecipeBookReaderTest.java index 804d463..a5af10c 100644 --- a/test/net/woodyfolsom/cs6601/p2/RecipeBookReaderTest.java +++ b/test/net/woodyfolsom/cs6601/p2/RecipeBookReaderTest.java @@ -8,6 +8,7 @@ import static org.hamcrest.CoreMatchers.*; import java.io.File; +import net.woodyfolsom.cs6601.p2.Ingredient.TYPE; import net.woodyfolsom.cs6601.p2.Recipe; import net.woodyfolsom.cs6601.p2.RecipeBook; import net.woodyfolsom.cs6601.p2.RecipeBookReader; @@ -17,15 +18,23 @@ import org.junit.Test; public class RecipeBookReaderTest { @Test - public void testReadRecipeBook() { - RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/PastelVasco.xml")); + public void testReadSurveyDataset() { + RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/survey_recipes.xml")); assertNotNull(recipeBook); - assertThat(recipeBook.getSize(), is(equalTo(1))); + assertThat(recipeBook.getSize(), is(equalTo(22))); Recipe recipe = recipeBook.getRecipe(0); - assertThat(recipe.getHead().getTitle(), is(equalTo("Gateau Basque / Pastel Vasco"))); - assertTrue(recipe.getHead().isCategoryMatch("Desserts")); - assertTrue(recipe.getHead().isCategoryMatch("Sweets")); - assertFalse(recipe.getHead().isCategoryMatch("Meat")); + System.out.println(recipe.getHead().getTitle()); + assertThat(recipe.getHead().getTitle(), is(equalTo("Honey cake"))); + assertTrue(recipe.getIngredients().contains(TYPE.EGGS)); + assertTrue(recipe.getIngredients().contains(TYPE.GLUTEN)); + assertTrue(recipe.getIngredients().contains(TYPE.SPICE)); + assertFalse(recipe.getIngredients().contains(TYPE.RED_MEAT)); + assertFalse(recipe.getIngredients().contains(TYPE.POULTRY)); + assertFalse(recipe.getIngredients().contains(TYPE.SHELLFISH)); + + for (int rIndex = 0; rIndex < recipeBook.getSize(); rIndex++) { + System.out.println(recipeBook.getRecipe(rIndex).getHead().getTitle()); + } } } diff --git a/test/net/woodyfolsom/cs6601/p2/RecipeReaderTest.java b/test/net/woodyfolsom/cs6601/p2/RecipeReaderTest.java new file mode 100644 index 0000000..42adacd --- /dev/null +++ b/test/net/woodyfolsom/cs6601/p2/RecipeReaderTest.java @@ -0,0 +1,31 @@ +package net.woodyfolsom.cs6601.p2; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.hamcrest.CoreMatchers.*; + +import java.io.File; + +import net.woodyfolsom.cs6601.p2.Recipe; +import net.woodyfolsom.cs6601.p2.RecipeBook; +import net.woodyfolsom.cs6601.p2.RecipeBookReader; + +import org.junit.Test; + +public class RecipeReaderTest { + + @Test + public void testReadRecipeBook() { + RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/PastelVasco.xml")); + assertNotNull(recipeBook); + assertThat(recipeBook.getSize(), is(equalTo(1))); + + Recipe recipe = recipeBook.getRecipe(0); + assertThat(recipe.getHead().getTitle(), is(equalTo("Gateau Basque / Pastel Vasco"))); + assertTrue(recipe.getHead().isCategoryMatch("Desserts")); + assertTrue(recipe.getHead().isCategoryMatch("Sweets")); + assertFalse(recipe.getHead().isCategoryMatch("Meat")); + } +} diff --git a/test/net/woodyfolsom/cs6601/p2/SurveyDatasetReaderTest.java b/test/net/woodyfolsom/cs6601/p2/SurveyDatasetReaderTest.java deleted file mode 100644 index 18fe860..0000000 --- a/test/net/woodyfolsom/cs6601/p2/SurveyDatasetReaderTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.woodyfolsom.cs6601.p2; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.hamcrest.CoreMatchers.*; - -import java.io.File; - -import net.woodyfolsom.cs6601.p2.Ingredient.TYPE; -import net.woodyfolsom.cs6601.p2.Recipe; -import net.woodyfolsom.cs6601.p2.RecipeBook; -import net.woodyfolsom.cs6601.p2.RecipeBookReader; - -import org.junit.Test; - -public class SurveyDatasetReaderTest { - - @Test - public void testReadSurveyDataset() { - RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/survey_dataset.xml")); - assertNotNull(recipeBook); - assertThat(recipeBook.getSize(), is(equalTo(22))); - - Recipe recipe = recipeBook.getRecipe(0); - System.out.println(recipe.getHead().getTitle()); - assertThat(recipe.getHead().getTitle(), is(equalTo("Honey cake"))); - assertTrue(recipe.getIngredients().contains(TYPE.EGGS)); - assertTrue(recipe.getIngredients().contains(TYPE.GLUTEN)); - assertTrue(recipe.getIngredients().contains(TYPE.SPICE)); - assertFalse(recipe.getIngredients().contains(TYPE.RED_MEAT)); - assertFalse(recipe.getIngredients().contains(TYPE.POULTRY)); - assertFalse(recipe.getIngredients().contains(TYPE.SHELLFISH)); - - for (int rIndex = 0; rIndex < recipeBook.getSize(); rIndex++) { - System.out.println(recipeBook.getRecipe(rIndex).getHead().getTitle()); - } - } -} diff --git a/test/net/woodyfolsom/cs6601/p2/SurveyReaderTest.java b/test/net/woodyfolsom/cs6601/p2/SurveyReaderTest.java new file mode 100644 index 0000000..c000c97 --- /dev/null +++ b/test/net/woodyfolsom/cs6601/p2/SurveyReaderTest.java @@ -0,0 +1,24 @@ +package net.woodyfolsom.cs6601.p2; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.Is.*; + +import java.io.File; + +import org.junit.Test; + +public class SurveyReaderTest { + + @Test + public void testReadSurveyDataset() { + Survey survey = SurveyReader.readSurvey(new File("data/survey.xml")); + assertNotNull(survey); + + assertThat(survey.getDinerCount(), equalTo(5)); + + Diner diner = survey.getDiner(0); + assertThat(diner.isAllergic(0), is(false)); + } +}