Work in progress.

This commit is contained in:
Woody Folsom
2012-03-12 14:33:41 -04:00
parent c1f68f6f5c
commit 16a97ba39a
15 changed files with 1424 additions and 753 deletions

Binary file not shown.

View File

@@ -452,7 +452,7 @@ on high speed until foamy.</step>
</recipe> </recipe>
<recipe> <recipe>
<head> <head>
<title>Breaded Veal Cutlet ( Weinerschnitzel )</title> <title>Weinerschnitzel</title>
<source/> <source/>
<categories> <categories>
<cat>Veal</cat> <cat>Veal</cat>
@@ -673,7 +673,7 @@ baking powder and salt.</step>
</recipe> </recipe>
<recipe> <recipe>
<head> <head>
<title>Chinese: Cashew Chicken 1</title> <title>Cashew Chicken</title>
<source/> <source/>
<categories> <categories>
<cat>Cashews</cat> <cat>Cashews</cat>
@@ -2829,4 +2829,329 @@ Carbs 36 g.
FROM: MADELINE HIMY (NFBH49A)</step> FROM: MADELINE HIMY (NFBH49A)</step>
</directions> </directions>
</recipe> </recipe>
<recipe>
<head>
<title>Hamburger Steak</title>
<source/>
<categories>
<cat>Beef</cat>
<cat>Penndutch</cat>
</categories>
<yield>1<unit>servings</unit>
</yield>
<preptime type="Total">
<time>
<qty>0</qty>
<timeunit>minutes</timeunit>
</time>
</preptime>
</head>
<ingredients>
<ing>
<amt>
<qty>1</qty>
<unit>pound</unit>
</amt>
<item>Beef</item>
<prep>ground</prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>teaspoon</unit>
</amt>
<item>salt</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit></unit>
</amt>
<item>onion</item>
<prep>minced</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit></unit>
</amt>
<item>egg</item>
<prep>well beaten</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>dash</unit>
</amt>
<item>pepper</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.25</qty>
<unit>cup</unit>
</amt>
<item>bread crumbs</item>
<prep></prep>
</ing>
</ingredients>
<directions>
<step>Mix in order given and shape into round cakes. Fry in butter until
nicely browned. Source: Pennsylvania Dutch Cook Book - Fine Old
Recipes, Culinary Arts Press, 1936.</step>
</directions>
</recipe>
<recipe>
<head>
<title>Potatoes in a Thick Sauce</title>
<source/>
<categories>
<cat>Main dish</cat>
<cat>Potatoes</cat>
<cat>Indian</cat>
<cat>Vegetarian</cat>
</categories>
<yield>6<unit>servings</unit>
</yield>
<preptime type="Total">
<time>
<qty>0</qty>
<timeunit>minutes</timeunit>
</time>
</preptime>
</head>
<ingredients>
<ing>
<amt>
<qty>5</qty>
<unit>medium</unit>
</amt>
<item>potatoes</item>
<prep>cubed &amp; cooked</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>slice</unit>
</amt>
<item>ginger</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>tablespoon</unit>
</amt>
<item>Coriander</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>cumin</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>6</qty>
<unit>tablespoons</unit>
</amt>
<item>tomato sauce</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>6</qty>
<unit>tablespoons</unit>
</amt>
<item>vegetable oil</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>Fennel</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>Fenugreek</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>teaspoon</unit>
</amt>
<item>Black mustard seeds</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>3</qty>
<unit></unit>
</amt>
<item>Whole dried red chilies</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>salt</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1.5</qty>
<unit>teaspoons</unit>
</amt>
<item>lemon juice</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>Garam masala</item>
<prep></prep>
</ing>
</ingredients>
<directions>
<step>Place ginger, coriander, cumin, tomato sauce &amp; 3 tb water in a
blender &amp; blend till smooth.
Break potatoes into bite sized pieces.
Heat oil (I use ghee) in a large pot. When hot, throw in fennel,
fenugreek &amp; mustard seeds. After 20 seconds, add red chilies. As
they darken, put in paste from blender. Fry for 5 minutes, stirring
frequently. Put in the potato pieces &amp; fry for 3 to 5 minutes. Add 1
1/2 c warm water. Bring to a boil. Add salt &amp; lemon juice. Simmer
for 20 minutes.
Before serving, sprinkle with garam masala.
Madhur Jaffrey, "An Invitation to Indian Cooking.</step>
</directions>
</recipe>
<recipe>
<head>
<title>Tomato-Zucchini Casserole</title>
<source/>
<categories>
<cat>Vegetarian</cat>
<cat>Casseroles</cat>
</categories>
<yield>4<unit>servings</unit>
</yield>
<preptime type="Total">
<time>
<qty>0</qty>
<timeunit>minutes</timeunit>
</time>
</preptime>
</head>
<ingredients>
<ing>
<amt>
<qty>1.5</qty>
<unit>teaspoons</unit>
</amt>
<item>chili powder</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>tablespoon</unit>
</amt>
<item>parsley flakes</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>teaspoon</unit>
</amt>
<item>garlic powder</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>teaspoon</unit>
</amt>
<item>onion powder</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.125</qty>
<unit>teaspoon</unit>
</amt>
<item>salt</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.125</qty>
<unit>teaspoon</unit>
</amt>
<item>black pepper</item>
<prep>ground</prep>
</ing>
<ing>
<amt>
<qty>3</qty>
<unit>cups</unit>
</amt>
<item>zucchini</item>
<prep>thinly sliced,fresh</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>pound</unit>
</amt>
<item>tomatoes</item>
<prep>fresh,sliced</prep>
</ing>
<ing>
<amt>
<qty>0.25</qty>
<unit>cup</unit>
</amt>
<item>bread crumbs</item>
<prep>white,fresh</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>tablespoon</unit>
</amt>
<item>vegetable oil</item>
<prep></prep>
</ing>
</ingredients>
<directions>
<step>1. Combine chili powder, 1 1/2 teaspooons parsley flakes, garlic and
onion powders, salt and pepper in a small bowl.~ 2. Place half the
zucchini in a lightly greased 6-cup casserole, or layer with half the
tomatoes.~ 3. Sprinkle with half the seasoning mixture.~ 4. Repeat
the layers.~ 5. Combine bread crumbs, oil and remaining parsley
flakes; sprinkle over vegetables.~ 6. Bake, uncovered, in preheated
375'F. oven, until vegetables are tender, about 40 minutes.~</step>
</directions>
</recipe>
</recipeml> </recipeml>

275
data/long_survey.xml Normal file
View File

@@ -0,0 +1,275 @@
<?xml version="1.0" encoding="UTF-8" ?>
<survey>
<dishes>
<entry>
<int>0</int>
<string>Catalan Rice</string>
</entry>
<entry>
<int>1</int>
<string>Hamburger Steak</string>
</entry>
<entry>
<int>2</int>
<string>Potatoes in a Thick Sauce</string>
</entry>
<entry>
<int>3</int>
<string>Tomato-Zucchini Casserole</string>
</entry>
<entry>
<int>4</int>
<string>Honey Cake</string>
</entry>
<entry>
<int>5</int>
<string>Cashew Chicken</string>
</entry>
<entry>
<int>6</int>
<string>Kahlua Cake</string>
</entry>
<entry>
<int>7</int>
<string>Ice Cream, Lowfat</string>
</entry>
<entry>
<int>8</int>
<string>Blender Double Fudge Cake</string>
</entry>
<entry>
<int>9</int>
<string>Weinerschnitzel</string>
</entry>
</dishes>
<categories>
<entry>
<int>0</int>
<string>vegetarian</string>
</entry>
<entry>
<int>1</int>
<string>allergic-nuts</string>
</entry>
</categories>
<diner>
<id>0</id>
<ratings>
<entry>
<int>0</int>
<int>10</int>
</entry>
<entry>
<int>1</int>
<int>2</int>
</entry>
<entry>
<int>2</int>
<int>5</int>
</entry>
<entry>
<int>3</int>
<int>5</int>
</entry>
<entry>
<int>4</int>
<int>5</int>
</entry>
<entry>
<int>5</int>
<int>5</int>
</entry>
<entry>
<int>6</int>
<int>5</int>
</entry>
<entry>
<int>7</int>
<int>5</int>
</entry>
<entry>
<int>8</int>
<int>5</int>
</entry>
<entry>
<int>9</int>
<int>5</int>
</entry>
</ratings>
<categories>
<entry>
<int>0</int>
<boolean>false</boolean>
</entry>
<entry>
<int>1</int>
<boolean>false</boolean>
</entry>
</categories>
</diner>
<diner>
<id>1</id>
<ratings>
<entry>
<int>0</int>
<int>0</int>
</entry>
<entry>
<int>1</int>
<int>0</int>
</entry>
<entry>
<int>2</int>
<int>5</int>
</entry>
<entry>
<int>3</int>
<int>6</int>
</entry>
<entry>
<int>4</int>
<int>5</int>
</entry>
<entry>
<int>5</int>
<int>5</int>
</entry>
<entry>
<int>6</int>
<int>5</int>
</entry>
<entry>
<int>7</int>
<int>5</int>
</entry>
<entry>
<int>8</int>
<int>5</int>
</entry>
<entry>
<int>9</int>
<int>5</int>
</entry>
</ratings>
<categories>
<entry>
<int>0</int>
<boolean>true</boolean>
</entry>
<entry>
<int>1</int>
<boolean>false</boolean>
</entry>
</categories>
</diner>
<diner>
<id>2</id>
<ratings>
<entry>
<int>0</int>
<int>9</int>
</entry>
<entry>
<int>1</int>
<int>2</int>
</entry>
<entry>
<int>2</int>
<int>2</int>
</entry>
<entry>
<int>3</int>
<int>2</int>
</entry>
<entry>
<int>4</int>
<int>5</int>
</entry>
<entry>
<int>5</int>
<int>0</int>
</entry>
<entry>
<int>6</int>
<int>5</int>
</entry>
<entry>
<int>7</int>
<int>5</int>
</entry>
<entry>
<int>8</int>
<int>5</int>
</entry>
<entry>
<int>9</int>
<int>5</int>
</entry>
</ratings>
<categories>
<entry>
<int>0</int>
<boolean>false</boolean>
</entry>
<entry>
<int>1</int>
<boolean>true</boolean>
</entry>
</categories>
</diner>
<diner>
<id>3</id>
<ratings>
<entry>
<int>0</int>
<int>9</int>
</entry>
<entry>
<int>1</int>
<int>2</int>
</entry>
<entry>
<int>2</int>
<int>2</int>
</entry>
<entry>
<int>3</int>
<int>2</int>
</entry>
<entry>
<int>4</int>
<int>5</int>
</entry>
<entry>
<int>5</int>
<int>7</int>
</entry>
<entry>
<int>6</int>
<int>5</int>
</entry>
<entry>
<int>7</int>
<int>5</int>
</entry>
<entry>
<int>8</int>
<int>5</int>
</entry>
<entry>
<int>9</int>
<int>5</int>
</entry>
</ratings>
<categories>
<entry>
<int>0</int>
<boolean>false</boolean>
</entry>
<entry>
<int>1</int>
<boolean>false</boolean>
</entry>
</categories>
</diner>
</survey>

521
data/medium_recipebook.xml Normal file
View File

@@ -0,0 +1,521 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE recipeml PUBLIC "-//FormatData//DTD RecipeML 0.5//EN" "http://www.formatdata.com/recipeml/recipeml.dtd"><recipeml version="0.5" generator="Krecipes v2.0-beta1">
<recipe>
<head>
<title>Catalan Rice</title>
<source/>
<categories>
<cat>Fish</cat>
<cat>Casserole</cat>
<cat>Main dish</cat>
<cat>Pork</cat>
<cat>Clams</cat>
</categories>
<yield>6<unit>servings</unit>
</yield>
<preptime type="Total">
<time>
<qty>0</qty>
<timeunit>minutes</timeunit>
</time>
</preptime>
</head>
<ingredients>
<ing>
<amt>
<qty>2.5</qty>
<unit>cups</unit>
</amt>
<item>Fish stock</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.25</qty>
<unit>teaspoon</unit>
</amt>
<item>Saffron Threads</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.25</qty>
<unit>cup</unit>
</amt>
<item>Dry white wine</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>6</qty>
<unit>tablespoons</unit>
</amt>
<item>Lard</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>pound</unit>
</amt>
<item>Chorizo</item>
<prep>Sliced 1/4"</prep>
</ing>
<ing>
<amt>
<qty>1.5</qty>
<unit>pounds</unit>
</amt>
<item>Pork Loin</item>
<prep>1" Cubes</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit></unit>
</amt>
<item>onion</item>
<prep>thinly sliced</prep>
</ing>
<ing>
<amt>
<qty>2</qty>
<unit></unit>
</amt>
<item>Bell peppers</item>
<prep>julienned</prep>
</ing>
<ing>
<amt>
<qty>2</qty>
<unit></unit>
</amt>
<item>tomatoes</item>
<prep>peeled,seeded</prep>
</ing>
<ing>
<amt>
<qty>3</qty>
<unit></unit>
</amt>
<item>Large Squid</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>2</qty>
<unit>cups</unit>
</amt>
<item>Long-Grained Rice</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.75</qty>
<unit>cup</unit>
</amt>
<item>Blanched almonds</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.333333</qty>
<unit>cup</unit>
</amt>
<item>Pine Nuts</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>3</qty>
<unit></unit>
</amt>
<item>garlic cloves</item>
<prep>minced</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>cup</unit>
</amt>
<item>Artichoke hearts</item>
<prep>drained</prep>
</ing>
<ing>
<amt>
<qty>18</qty>
<unit></unit>
</amt>
<item>Clams Or Mussels</item>
<prep>scrubbed</prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>cup</unit>
</amt>
<item>Peas</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.25</qty>
<unit>cup</unit>
</amt>
<item>Pimientos</item>
<prep>julienned</prep>
</ing>
<ing>
<amt>
<qty>2</qty>
<unit>tablespoons</unit>
</amt>
<item>Fresh parsley</item>
<prep>minced</prep>
</ing>
</ingredients>
<directions>
<step>Clean squid and cut body sacs into rings. Cut tentacles in half. In
a small saucepan, bring stock to a bare simmer. Crush saffron and
combine it with wine in a small bowl. In a flameproof casserole or
paella pan, heat the lard over moderately high heat. Saute the
chorizo and pork, turning them until they are browned. Add the
onion, bell peppers, tomatoes, and squid and cook the mixture over
moderate heat, stirring, for 15 minutes. Stir in the rice and cook
for 1 minute, stirring. Stir in almonds, pine nuts, garlic, saffron
mixture, and artichoke hearts. Ladle in enough stock to just cover
the rice mixture. Bring to a boil and simmer it, covered, for 20
minutes. Arrange the clams in the rice, add the peas, and simmer for
10-15 minutes, or until the rice is just tender and the clams open.
Discard any clams that do not open. Garnish with pimientos and
parsley. This is a recipe by Elizabeth David, appearing in an article
in 1972 by James Beard. It originated on Spain's Costa Brava. "not a
true paella, but it is quite good." A 1972 Gourmet Magazine Favorite.</step>
</directions>
</recipe>
<recipe>
<head>
<title>Hamburger Steak</title>
<source/>
<categories>
<cat>Beef</cat>
<cat>Penndutch</cat>
</categories>
<yield>1<unit>servings</unit>
</yield>
<preptime type="Total">
<time>
<qty>0</qty>
<timeunit>minutes</timeunit>
</time>
</preptime>
</head>
<ingredients>
<ing>
<amt>
<qty>1</qty>
<unit>pound</unit>
</amt>
<item>Beef</item>
<prep>ground</prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>teaspoon</unit>
</amt>
<item>salt</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit></unit>
</amt>
<item>onion</item>
<prep>minced</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit></unit>
</amt>
<item>egg</item>
<prep>well beaten</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>dash</unit>
</amt>
<item>pepper</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.25</qty>
<unit>cup</unit>
</amt>
<item>bread crumbs</item>
<prep></prep>
</ing>
</ingredients>
<directions>
<step>Mix in order given and shape into round cakes. Fry in butter until
nicely browned. Source: Pennsylvania Dutch Cook Book - Fine Old
Recipes, Culinary Arts Press, 1936.</step>
</directions>
</recipe>
<recipe>
<head>
<title>Potatoes in a Thick Sauce</title>
<source/>
<categories>
<cat>Main dish</cat>
<cat>Potatoes</cat>
<cat>Indian</cat>
<cat>Vegetarian</cat>
</categories>
<yield>6<unit>servings</unit>
</yield>
<preptime type="Total">
<time>
<qty>0</qty>
<timeunit>minutes</timeunit>
</time>
</preptime>
</head>
<ingredients>
<ing>
<amt>
<qty>5</qty>
<unit>medium</unit>
</amt>
<item>potatoes</item>
<prep>cubed &amp; cooked</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>slice</unit>
</amt>
<item>ginger</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>tablespoon</unit>
</amt>
<item>Coriander</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>cumin</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>6</qty>
<unit>tablespoons</unit>
</amt>
<item>tomato sauce</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>6</qty>
<unit>tablespoons</unit>
</amt>
<item>vegetable oil</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>Fennel</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>Fenugreek</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>teaspoon</unit>
</amt>
<item>Black mustard seeds</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>3</qty>
<unit></unit>
</amt>
<item>Whole dried red chilies</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>salt</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1.5</qty>
<unit>teaspoons</unit>
</amt>
<item>lemon juice</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>teaspoon</unit>
</amt>
<item>Garam masala</item>
<prep></prep>
</ing>
</ingredients>
<directions>
<step>Place ginger, coriander, cumin, tomato sauce &amp; 3 tb water in a
blender &amp; blend till smooth.
Break potatoes into bite sized pieces.
Heat oil (I use ghee) in a large pot. When hot, throw in fennel,
fenugreek &amp; mustard seeds. After 20 seconds, add red chilies. As
they darken, put in paste from blender. Fry for 5 minutes, stirring
frequently. Put in the potato pieces &amp; fry for 3 to 5 minutes. Add 1
1/2 c warm water. Bring to a boil. Add salt &amp; lemon juice. Simmer
for 20 minutes.
Before serving, sprinkle with garam masala.
Madhur Jaffrey, "An Invitation to Indian Cooking.</step>
</directions>
</recipe>
<recipe>
<head>
<title>Tomato-Zucchini Casserole</title>
<source/>
<categories>
<cat>Vegetarian</cat>
<cat>Casseroles</cat>
</categories>
<yield>4<unit>servings</unit>
</yield>
<preptime type="Total">
<time>
<qty>0</qty>
<timeunit>minutes</timeunit>
</time>
</preptime>
</head>
<ingredients>
<ing>
<amt>
<qty>1.5</qty>
<unit>teaspoons</unit>
</amt>
<item>chili powder</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>tablespoon</unit>
</amt>
<item>parsley flakes</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>teaspoon</unit>
</amt>
<item>garlic powder</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.5</qty>
<unit>teaspoon</unit>
</amt>
<item>onion powder</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.125</qty>
<unit>teaspoon</unit>
</amt>
<item>salt</item>
<prep></prep>
</ing>
<ing>
<amt>
<qty>0.125</qty>
<unit>teaspoon</unit>
</amt>
<item>black pepper</item>
<prep>ground</prep>
</ing>
<ing>
<amt>
<qty>3</qty>
<unit>cups</unit>
</amt>
<item>zucchini</item>
<prep>thinly sliced,fresh</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>pound</unit>
</amt>
<item>tomatoes</item>
<prep>fresh,sliced</prep>
</ing>
<ing>
<amt>
<qty>0.25</qty>
<unit>cup</unit>
</amt>
<item>bread crumbs</item>
<prep>white,fresh</prep>
</ing>
<ing>
<amt>
<qty>1</qty>
<unit>tablespoon</unit>
</amt>
<item>vegetable oil</item>
<prep></prep>
</ing>
</ingredients>
<directions>
<step>1. Combine chili powder, 1 1/2 teaspooons parsley flakes, garlic and
onion powders, salt and pepper in a small bowl.~ 2. Place half the
zucchini in a lightly greased 6-cup casserole, or layer with half the
tomatoes.~ 3. Sprinkle with half the seasoning mixture.~ 4. Repeat
the layers.~ 5. Combine bread crumbs, oil and remaining parsley
flakes; sprinkle over vegetables.~ 6. Bake, uncovered, in preheated
375'F. oven, until vegetables are tender, about 40 minutes.~</step>
</directions>
</recipe>
</recipeml>

81
data/medium_survey.xml Normal file
View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" ?>
<survey>
<dishes>
<entry>
<int>0</int>
<string>Catalan Rice</string>
</entry>
<entry>
<int>1</int>
<string>Hamburger Steak</string>
</entry>
<entry>
<int>2</int>
<string>Potatoes in a Thick Sauce</string>
</entry>
<entry>
<int>3</int>
<string>Tomato-Zucchini Casserole</string>
</entry>
</dishes>
<categories>
<entry>
<int>0</int>
<string>vegan</string>
</entry>
</categories>
<diner>
<id>0</id>
<ratings>
<entry>
<int>0</int>
<int>10</int>
</entry>
<entry>
<int>1</int>
<int>2</int>
</entry>
<entry>
<int>2</int>
<int>5</int>
</entry>
<entry>
<int>3</int>
<int>5</int>
</entry>
</ratings>
<categories>
<entry>
<int>0</int>
<boolean>false</boolean>
</entry>
</categories>
</diner>
<diner>
<id>1</id>
<ratings>
<entry>
<int>0</int>
<int>0</int>
</entry>
<entry>
<int>1</int>
<int>0</int>
</entry>
<entry>
<int>2</int>
<int>5</int>
</entry>
<entry>
<int>3</int>
<int>6</int>
</entry>
</ratings>
<categories>
<entry>
<int>0</int>
<boolean>true</boolean>
</entry>
</categories>
</diner>
</survey>

View File

@@ -21,19 +21,7 @@
<categories> <categories>
<entry> <entry>
<int>0</int> <int>0</int>
<string> <string>vegan</string>
chocolate
</string>
</entry>
<entry>
<int>1</int>
<string>
nuts
</string>
</entry>
<entry>
<int>2</int>
<string>shellfish</string>
</entry> </entry>
</categories> </categories>
<diner> <diner>
@@ -56,20 +44,12 @@
<int>5</int> <int>5</int>
</entry> </entry>
</ratings> </ratings>
<allergies> <categories>
<entry> <entry>
<int>0</int> <int>0</int>
<boolean>false</boolean> <boolean>false</boolean>
</entry> </entry>
<entry> </categories>
<int>1</int>
<boolean>false</boolean>
</entry>
<entry>
<int>2</int>
<boolean>false</boolean>
</entry>
</allergies>
</diner> </diner>
<diner> <diner>
<id>1</id> <id>1</id>
@@ -91,19 +71,11 @@
<int>5</int> <int>5</int>
</entry> </entry>
</ratings> </ratings>
<allergies> <categories>
<entry> <entry>
<int>0</int> <int>0</int>
<boolean>false</boolean> <boolean>false</boolean>
</entry> </entry>
<entry> </categories>
<int>1</int>
<boolean>false</boolean>
</entry>
<entry>
<int>2</int>
<boolean>false</boolean>
</entry>
</allergies>
</diner> </diner>
</survey> </survey>

View File

@@ -1,628 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<survey>
<dishes>
<entry>
<int>0</int>
<string>Honey cake</string>
</entry>
<entry>
<int>1</int>
<string>Kahlua Cake</string>
</entry>
<entry>
<int>2</int>
<string>Ice Cream, Lowfat</string>
</entry>
<entry>
<int>3</int>
<string>Southwest Smoothie</string>
</entry>
<entry>
<int>4</int>
<string>Margarita Sunrise</string>
</entry>
<entry>
<int>5</int>
<string>Breaded Veal Cutlet ( Weinerschnitzel )</string>
</entry>
<entry>
<int>6</int>
<string>Blender Double Fudge Cake</string>
</entry>
<entry>
<int>7</int>
<string>Chinese: Cashew Chicken 1</string>
</entry>
<entry>
<int>8</int>
<string>Bayou Shrimp Creole</string>
</entry>
<entry>
<int>9</int>
<string>Crab Burgers</string>
</entry>
<entry>
<int>10</int>
<string>Broiled Flounder</string>
</entry>
<entry>
<int>11</int>
<string>Coconut Beer Batter Shrimp</string>
</entry>
<entry>
<int>12</int>
<string>Coconut Fish Curry</string>
</entry>
<entry>
<int>13</int>
<string>Catalan Rice</string>
</entry>
<entry>
<int>14</int>
<string>Baked Steak And Lima Beans</string>
</entry>
<entry>
<int>15</int>
<string>Tabasco Classic - Perfect Seared Steaks ****</string>
</entry>
<entry>
<int>16</int>
<string>Salisbury Steak with Mushroom Sauce</string>
</entry>
<entry>
<int>17</int>
<string>Meatless Loaf</string>
</entry>
<entry>
<int>18</int>
<string>Black Bean Soup</string>
</entry>
<entry>
<int>29</int>
<string>Fava Bean Burgers</string>
</entry>
<entry>
<int>20</int>
<string>Angel Hair Pesto Primavera</string>
</entry>
<entry>
<int>21</int>
<string>EGGPLANT LASAGNE</string>
</entry>
</dishes>
<categories>
<entry>
<int>0</int>
<string>
chocolate
</string>
</entry>
<entry>
<int>1</int>
<string>
nuts
</string>
</entry>
<entry>
<int>2</int>
<string>
shellfish
</string>
</entry>
</categories>
<diner>
<id>0</id>
<ratings>
<entry>
<int>0</int>
<int>10</int>
</entry>
<entry>
<int>1</int>
<int>10</int>
</entry>
<entry>
<int>2</int>
<int>10</int>
</entry>
<entry>
<int>3</int>
<int>10</int>
</entry>
<entry>
<int>4</int>
<int>10</int>
</entry>
<entry>
<int>5</int>
<int>10</int>
</entry>
<entry>
<int>6</int>
<int>10</int>
</entry>
<entry>
<int>7</int>
<int>10</int>
</entry>
<entry>
<int>8</int>
<int>10</int>
</entry>
<entry>
<int>9</int>
<int>10</int>
</entry>
<entry>
<int>10</int>
<int>10</int>
</entry>
<entry>
<int>11</int>
<int>10</int>
</entry>
<entry>
<int>12</int>
<int>10</int>
</entry>
<entry>
<int>13</int>
<int>10</int>
</entry>
<entry>
<int>14</int>
<int>10</int>
</entry>
<entry>
<int>15</int>
<int>10</int>
</entry>
<entry>
<int>16</int>
<int>10</int>
</entry>
<entry>
<int>17</int>
<int>10</int>
</entry>
<entry>
<int>18</int>
<int>10</int>
</entry>
<entry>
<int>19</int>
<int>10</int>
</entry>
<entry>
<int>20</int>
<int>10</int>
</entry>
</ratings>
<allergies>
<entry>
<int>0</int>
<boolean>false</boolean>
</entry>
<entry>
<int>1</int>
<boolean>false</boolean>
</entry>
<entry>
<int>2</int>
<boolean>false</boolean>
</entry>
</allergies>
</diner>
<diner>
<id>1</id>
<ratings>
<entry>
<int>0</int>
<int>10</int>
</entry>
<entry>
<int>1</int>
<int>10</int>
</entry>
<entry>
<int>2</int>
<int>10</int>
</entry>
<entry>
<int>3</int>
<int>10</int>
</entry>
<entry>
<int>4</int>
<int>10</int>
</entry>
<entry>
<int>5</int>
<int>10</int>
</entry>
<entry>
<int>6</int>
<int>10</int>
</entry>
<entry>
<int>7</int>
<int>10</int>
</entry>
<entry>
<int>8</int>
<int>10</int>
</entry>
<entry>
<int>9</int>
<int>10</int>
</entry>
<entry>
<int>10</int>
<int>10</int>
</entry>
<entry>
<int>11</int>
<int>10</int>
</entry>
<entry>
<int>12</int>
<int>10</int>
</entry>
<entry>
<int>13</int>
<int>10</int>
</entry>
<entry>
<int>14</int>
<int>10</int>
</entry>
<entry>
<int>15</int>
<int>10</int>
</entry>
<entry>
<int>16</int>
<int>10</int>
</entry>
<entry>
<int>17</int>
<int>10</int>
</entry>
<entry>
<int>18</int>
<int>10</int>
</entry>
<entry>
<int>19</int>
<int>10</int>
</entry>
<entry>
<int>20</int>
<int>10</int>
</entry>
</ratings>
<allergies>
<entry>
<int>0</int>
<boolean>false</boolean>
</entry>
<entry>
<int>1</int>
<boolean>false</boolean>
</entry>
<entry>
<int>2</int>
<boolean>false</boolean>
</entry>
</allergies>
</diner>
<diner>
<id>2</id>
<ratings>
<entry>
<int>0</int>
<int>10</int>
</entry>
<entry>
<int>1</int>
<int>10</int>
</entry>
<entry>
<int>2</int>
<int>10</int>
</entry>
<entry>
<int>3</int>
<int>10</int>
</entry>
<entry>
<int>4</int>
<int>10</int>
</entry>
<entry>
<int>5</int>
<int>10</int>
</entry>
<entry>
<int>6</int>
<int>10</int>
</entry>
<entry>
<int>7</int>
<int>10</int>
</entry>
<entry>
<int>8</int>
<int>10</int>
</entry>
<entry>
<int>9</int>
<int>10</int>
</entry>
<entry>
<int>10</int>
<int>10</int>
</entry>
<entry>
<int>11</int>
<int>10</int>
</entry>
<entry>
<int>12</int>
<int>10</int>
</entry>
<entry>
<int>13</int>
<int>10</int>
</entry>
<entry>
<int>14</int>
<int>10</int>
</entry>
<entry>
<int>15</int>
<int>10</int>
</entry>
<entry>
<int>16</int>
<int>10</int>
</entry>
<entry>
<int>17</int>
<int>10</int>
</entry>
<entry>
<int>18</int>
<int>10</int>
</entry>
<entry>
<int>19</int>
<int>10</int>
</entry>
<entry>
<int>20</int>
<int>10</int>
</entry>
</ratings>
<allergies>
<entry>
<int>0</int>
<boolean>false</boolean>
</entry>
<entry>
<int>1</int>
<boolean>false</boolean>
</entry>
<entry>
<int>2</int>
<boolean>false</boolean>
</entry>
</allergies>
</diner>
<diner>
<id>3</id>
<ratings>
<entry>
<int>0</int>
<int>10</int>
</entry>
<entry>
<int>1</int>
<int>10</int>
</entry>
<entry>
<int>2</int>
<int>10</int>
</entry>
<entry>
<int>3</int>
<int>10</int>
</entry>
<entry>
<int>4</int>
<int>10</int>
</entry>
<entry>
<int>5</int>
<int>10</int>
</entry>
<entry>
<int>6</int>
<int>10</int>
</entry>
<entry>
<int>7</int>
<int>10</int>
</entry>
<entry>
<int>8</int>
<int>10</int>
</entry>
<entry>
<int>9</int>
<int>10</int>
</entry>
<entry>
<int>10</int>
<int>10</int>
</entry>
<entry>
<int>11</int>
<int>10</int>
</entry>
<entry>
<int>12</int>
<int>10</int>
</entry>
<entry>
<int>13</int>
<int>10</int>
</entry>
<entry>
<int>14</int>
<int>10</int>
</entry>
<entry>
<int>15</int>
<int>10</int>
</entry>
<entry>
<int>16</int>
<int>10</int>
</entry>
<entry>
<int>17</int>
<int>10</int>
</entry>
<entry>
<int>18</int>
<int>10</int>
</entry>
<entry>
<int>19</int>
<int>10</int>
</entry>
<entry>
<int>20</int>
<int>10</int>
</entry>
</ratings>
<allergies>
<entry>
<int>0</int>
<boolean>false</boolean>
</entry>
<entry>
<int>1</int>
<boolean>false</boolean>
</entry>
<entry>
<int>2</int>
<boolean>false</boolean>
</entry>
</allergies>
</diner>
<diner>
<id>4</id>
<ratings>
<entry>
<int>0</int>
<int>10</int>
</entry>
<entry>
<int>1</int>
<int>10</int>
</entry>
<entry>
<int>2</int>
<int>10</int>
</entry>
<entry>
<int>3</int>
<int>10</int>
</entry>
<entry>
<int>4</int>
<int>10</int>
</entry>
<entry>
<int>5</int>
<int>10</int>
</entry>
<entry>
<int>6</int>
<int>10</int>
</entry>
<entry>
<int>7</int>
<int>10</int>
</entry>
<entry>
<int>8</int>
<int>10</int>
</entry>
<entry>
<int>9</int>
<int>10</int>
</entry>
<entry>
<int>10</int>
<int>10</int>
</entry>
<entry>
<int>11</int>
<int>10</int>
</entry>
<entry>
<int>12</int>
<int>10</int>
</entry>
<entry>
<int>13</int>
<int>10</int>
</entry>
<entry>
<int>14</int>
<int>10</int>
</entry>
<entry>
<int>15</int>
<int>10</int>
</entry>
<entry>
<int>16</int>
<int>10</int>
</entry>
<entry>
<int>17</int>
<int>10</int>
</entry>
<entry>
<int>18</int>
<int>10</int>
</entry>
<entry>
<int>19</int>
<int>10</int>
</entry>
<entry>
<int>20</int>
<int>10</int>
</entry>
</ratings>
<allergies>
<entry>
<int>0</int>
<boolean>false</boolean>
</entry>
<entry>
<int>1</int>
<boolean>false</boolean>
</entry>
<entry>
<int>2</int>
<boolean>false</boolean>
</entry>
</allergies>
</diner>
</survey>

View File

@@ -23,14 +23,19 @@ import dkohl.onthology.Ontology;
public class FoodNetBuilder { public class FoodNetBuilder {
public static final String TASTE = "Taste"; public static final String TASTE = "Taste";
public static final String SOMEONE_VEGETARIAN = "Vegetarian";
public static final String SOMEONE_VEGETARIAN = "vegetarian";
public static final String SOMEONE_ALLERGIC_NUTS = "allergic-nuts";
public static final String CONTAINS_MEAT = "Meat"; public static final String CONTAINS_MEAT = "Meat";
public static final String CONTAINS_VEGETABLE = "Vegetable"; public static final String CONTAINS_VEGETABLE = "Vegetable";
public static final String CONTAINS_BEEF = TYPE.BEEF.toString(); public static final String CONTAINS_BEEF = TYPE.BEEF.toString();
public static final String CONTAINS_PORK = TYPE.PORK.toString(); public static final String CONTAINS_PORK = TYPE.PORK.toString();
public static final String CONTAINS_TOMATOS = TYPE.TOMATO.toString(); public static final String CONTAINS_TOMATOS = TYPE.TOMATO.toString();
public static final String CONTAINS_POTATOS = TYPE.POTATO.toString(); public static final String CONTAINS_POTATOS = TYPE.POTATO.toString();
public static final String CONTAINS_NUTS = "Nuts";
public static final String CONTAINS_GENERIC_NUTS = TYPE.GENERIC_NUTS.toString();
public static final String TRUE_VALUE = "true"; public static final String TRUE_VALUE = "true";
public static final String FALSE_VALUE = "false"; public static final String FALSE_VALUE = "false";
@@ -39,27 +44,30 @@ public class FoodNetBuilder {
public static final String RATING_DOMAIN[] = { "1", "2", "3", "4", "5", public static final String RATING_DOMAIN[] = { "1", "2", "3", "4", "5",
"6", "7", "8", "9", "10" }; "6", "7", "8", "9", "10" };
private static final String[] VARIABLES = { SOMEONE_VEGETARIAN, private static final String[] VARIABLES = { SOMEONE_VEGETARIAN, SOMEONE_ALLERGIC_NUTS,
CONTAINS_BEEF, CONTAINS_MEAT, CONTAINS_PORK, CONTAINS_POTATOS, CONTAINS_BEEF, CONTAINS_MEAT, CONTAINS_PORK, CONTAINS_POTATOS,
CONTAINS_TOMATOS, CONTAINS_VEGETABLE, TASTE }; CONTAINS_TOMATOS, CONTAINS_VEGETABLE, CONTAINS_NUTS, CONTAINS_GENERIC_NUTS, TASTE };
private static final String[] OBSERVED = { CONTAINS_BEEF, CONTAINS_PORK, private static final String[] OBSERVED = { CONTAINS_BEEF, CONTAINS_PORK,
CONTAINS_POTATOS, CONTAINS_TOMATOS, }; CONTAINS_POTATOS, CONTAINS_TOMATOS, CONTAINS_GENERIC_NUTS};
public static Ontology createOntology() { public static Ontology createOntology() {
HashSet<String> classes = new HashSet<String>(); HashSet<String> classes = new HashSet<String>();
classes.add(CONTAINS_MEAT); classes.add(CONTAINS_MEAT);
classes.add(CONTAINS_NUTS);
classes.add(CONTAINS_VEGETABLE); classes.add(CONTAINS_VEGETABLE);
Ontology onthology = new Ontology(classes); Ontology ontology = new Ontology(classes);
onthology.define(CONTAINS_PORK, CONTAINS_MEAT); ontology.define(CONTAINS_PORK, CONTAINS_MEAT);
onthology.define(CONTAINS_BEEF, CONTAINS_MEAT); ontology.define(CONTAINS_BEEF, CONTAINS_MEAT);
onthology.define(CONTAINS_TOMATOS, CONTAINS_VEGETABLE); ontology.define(CONTAINS_GENERIC_NUTS, CONTAINS_NUTS);
onthology.define(CONTAINS_POTATOS, CONTAINS_VEGETABLE);
return onthology; ontology.define(CONTAINS_TOMATOS, CONTAINS_VEGETABLE);
ontology.define(CONTAINS_POTATOS, CONTAINS_VEGETABLE);
return ontology;
} }
private static Assignment build(String varible, String value) { private static Assignment build(String varible, String value) {
@@ -86,14 +94,13 @@ public class FoodNetBuilder {
return normPoint; return normPoint;
} }
public static DataSet getSurveyDataSet(Survey survey, RecipeBook recipeBook) { public static DataSet getSurveyDataSet(Survey survey, RecipeBook recipeBook, int startIndex, int endIndex) {
DataSet data = FoodExampleBuilder.examples(); DataSet data = FoodExampleBuilder.examples();
Ontology onto = createOntology(); Ontology onto = createOntology();
int nDishes = survey.getDishCount();
for (int dinerIndex = 0; dinerIndex < survey.getDinerCount(); dinerIndex++) { for (int dinerIndex = 0; dinerIndex < survey.getDinerCount(); dinerIndex++) {
Diner diner = survey.getDiner(dinerIndex); Diner diner = survey.getDiner(dinerIndex);
for (int dishIndex = 0; dishIndex < nDishes; dishIndex++) { for (int dishIndex = startIndex; dishIndex < endIndex; dishIndex++) {
data.add(normalize(createDataPoint(recipeBook, survey.getDish(dishIndex), diner.getRating(dishIndex)),onto)); data.add(normalize(createDataPoint(recipeBook, survey.getDish(dishIndex), diner.getRating(dishIndex)),onto));
} }
} }
@@ -118,20 +125,41 @@ public class FoodNetBuilder {
if (ingredients.contains(TYPE.TOMATO)) { if (ingredients.contains(TYPE.TOMATO)) {
point.add(build(CONTAINS_TOMATOS, TRUE_VALUE)); point.add(build(CONTAINS_TOMATOS, TRUE_VALUE));
} }
if (ingredients.contains(TYPE.GENERIC_NUTS)) {
point.add(build(CONTAINS_GENERIC_NUTS, TRUE_VALUE));
}
point.add(build(TASTE, "" + weight)); point.add(build(TASTE, "" + weight));
return point; return point;
} }
public static ProbabilityDistribution vegi() { public static ProbabilityDistribution vegi(Survey survey) {
String names[] = { SOMEONE_VEGETARIAN }; String names[] = { SOMEONE_VEGETARIAN };
ProbabilityTable table = new ProbabilityTable(names); ProbabilityTable table = new ProbabilityTable(names);
table.setProbabilityForAssignment("true;", new Probability(0)); if (survey.isDiner("vegetarian")) {
table.setProbabilityForAssignment("false;", new Probability(1)); table.setProbabilityForAssignment("true;", new Probability(1));
table.setProbabilityForAssignment("false;", new Probability(0));
} else {
table.setProbabilityForAssignment("true;", new Probability(0));
table.setProbabilityForAssignment("false;", new Probability(1));
}
return table; return table;
} }
public static ProbabilityDistribution allergicNuts(Survey survey) {
String names[] = { SOMEONE_ALLERGIC_NUTS };
ProbabilityTable table = new ProbabilityTable(names);
if (survey.isDiner("allergic-nuts")) {
table.setProbabilityForAssignment("true;", new Probability(1));
table.setProbabilityForAssignment("false;", new Probability(0));
} else {
table.setProbabilityForAssignment("true;", new Probability(0));
table.setProbabilityForAssignment("false;", new Probability(1));
}
return table;
}
public static ProbabilityDistribution beef() { public static ProbabilityDistribution beef() {
String names[] = { CONTAINS_MEAT, CONTAINS_BEEF }; String names[] = { CONTAINS_MEAT, CONTAINS_BEEF };
ProbabilityTable table = new ProbabilityTable(names); ProbabilityTable table = new ProbabilityTable(names);
@@ -143,13 +171,25 @@ public class FoodNetBuilder {
ProbabilityTable table = new ProbabilityTable(names); ProbabilityTable table = new ProbabilityTable(names);
return table; return table;
} }
public static ProbabilityDistribution meet() { public static ProbabilityDistribution meat() {
String names[] = { SOMEONE_VEGETARIAN, CONTAINS_MEAT }; String names[] = { SOMEONE_VEGETARIAN, CONTAINS_MEAT };
ProbabilityTable table = new ProbabilityTable(names); ProbabilityTable table = new ProbabilityTable(names);
return table; return table;
} }
public static ProbabilityDistribution genericNuts() {
String names[] = { CONTAINS_NUTS, CONTAINS_GENERIC_NUTS };
ProbabilityTable table = new ProbabilityTable(names);
return table;
}
public static ProbabilityDistribution nuts() {
String names[] = { SOMEONE_ALLERGIC_NUTS, CONTAINS_NUTS };
ProbabilityTable table = new ProbabilityTable(names);
return table;
}
public static ProbabilityDistribution tomatos() { public static ProbabilityDistribution tomatos() {
String names[] = { CONTAINS_VEGETABLE, CONTAINS_TOMATOS }; String names[] = { CONTAINS_VEGETABLE, CONTAINS_TOMATOS };
ProbabilityTable table = new ProbabilityTable(names); ProbabilityTable table = new ProbabilityTable(names);
@@ -170,27 +210,34 @@ public class FoodNetBuilder {
public static ProbabilityDistribution taste() { public static ProbabilityDistribution taste() {
String names[] = { TASTE, CONTAINS_BEEF, CONTAINS_PORK, String names[] = { TASTE, CONTAINS_BEEF, CONTAINS_PORK,
CONTAINS_POTATOS, CONTAINS_TOMATOS }; CONTAINS_POTATOS, CONTAINS_TOMATOS, CONTAINS_GENERIC_NUTS };
ContinousDistribution distribution = new ContinousDistribution(names, 0); ContinousDistribution distribution = new ContinousDistribution(names, 0);
return distribution; return distribution;
} }
public static BayesNet createDishNet(Survey survey, RecipeBook recipeBook) { public static BayesNet createDishNet(Survey survey, RecipeBook recipeBook, int startIndex, int endIndex) {
BayesNet net = new BayesNet(VARIABLES); BayesNet net = new BayesNet(VARIABLES);
net.setDistribution(new Variable(SOMEONE_VEGETARIAN, DOMAIN), vegi()); net.setDistribution(new Variable(SOMEONE_VEGETARIAN, DOMAIN), vegi(survey));
net.setDistribution(new Variable(CONTAINS_MEAT, DOMAIN), meet()); net.setDistribution(new Variable(SOMEONE_ALLERGIC_NUTS, DOMAIN), allergicNuts(survey));
net.setDistribution(new Variable(CONTAINS_MEAT, DOMAIN), meat());
net.setDistribution(new Variable(CONTAINS_NUTS, DOMAIN), nuts());
net.setDistribution(new Variable(CONTAINS_VEGETABLE, DOMAIN), net.setDistribution(new Variable(CONTAINS_VEGETABLE, DOMAIN),
vegetables()); vegetables());
net.setDistribution(new Variable(CONTAINS_BEEF, DOMAIN), beef()); net.setDistribution(new Variable(CONTAINS_BEEF, DOMAIN), beef());
net.setDistribution(new Variable(CONTAINS_PORK, DOMAIN), pork()); net.setDistribution(new Variable(CONTAINS_PORK, DOMAIN), pork());
net.setDistribution(new Variable(CONTAINS_POTATOS, DOMAIN), potatos()); net.setDistribution(new Variable(CONTAINS_POTATOS, DOMAIN), potatos());
net.setDistribution(new Variable(CONTAINS_TOMATOS, DOMAIN), tomatos()); net.setDistribution(new Variable(CONTAINS_TOMATOS, DOMAIN), tomatos());
net.setDistribution(new Variable(CONTAINS_GENERIC_NUTS, DOMAIN), genericNuts());
net.setDistribution(new Variable(TASTE, RATING_DOMAIN), taste()); net.setDistribution(new Variable(TASTE, RATING_DOMAIN), taste());
Ontology ontology = createOntology(); Ontology ontology = createOntology();
for (String category : ontology.getClasses()) { for (String category : ontology.getClasses()) {
net.connect(category, SOMEONE_VEGETARIAN); net.connect(category, SOMEONE_VEGETARIAN);
net.connect(category, SOMEONE_ALLERGIC_NUTS);
} }
for (String thing : OBSERVED) { for (String thing : OBSERVED) {
@@ -198,7 +245,7 @@ public class FoodNetBuilder {
net.connect(TASTE, thing); net.connect(TASTE, thing);
} }
DataSet dataSet = getSurveyDataSet(survey, recipeBook); DataSet dataSet = getSurveyDataSet(survey, recipeBook, startIndex, endIndex);
for (String category : ontology.getClasses()) { for (String category : ontology.getClasses()) {
MaximumLikelihoodEstimation.estimate(dataSet, net, category); MaximumLikelihoodEstimation.estimate(dataSet, net, category);

View File

@@ -4,32 +4,27 @@ import java.util.LinkedList;
public class RootMeanSquareError { public class RootMeanSquareError {
private LinkedList<Double> expected; private LinkedList<Double> expected;
private LinkedList<Double> groundTruth; private LinkedList<Double> groundTruth;
public RootMeanSquareError() { public RootMeanSquareError() {
expected = new LinkedList<Double>(); expected = new LinkedList<Double>();
groundTruth = new LinkedList<Double>(); groundTruth = new LinkedList<Double>();
}
public void push(double predicted, double actual) {
expected.add(predicted);
groundTruth.add(actual);
}
public double error() {
double mean = 0.0;
for(Double val : groundTruth) {
mean += val;
} }
mean /= groundTruth.size();
public void push(double predicted, double actual) {
double err = 0.0; expected.add(predicted);
for(Double val : expected) { groundTruth.add(actual);
err += Math.pow(mean - val, 2);
} }
return Math.sqrt(err);
} public double error() {
double mean = 0.0;
for (int i = 0; i < expected.size(); i++){
mean += Math.pow(expected.get(i) - groundTruth.get(i), 2);
}
mean /= groundTruth.size();
return Math.sqrt(mean);
}
} }

View File

@@ -6,24 +6,22 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import net.woodyfolsom.cs6601.p2.Ingredient.TYPE; import net.woodyfolsom.cs6601.p2.Ingredient.TYPE;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import dkohl.bayes.bayesnet.BayesNet; import dkohl.bayes.bayesnet.BayesNet;
import dkohl.bayes.builders.FoodNetBuilder; import dkohl.bayes.builders.FoodNetBuilder;
import dkohl.bayes.inference.EnumerateAll; import dkohl.bayes.inference.EnumerateAll;
import dkohl.bayes.probability.Assignment; import dkohl.bayes.probability.Assignment;
import dkohl.bayes.probability.ProbabilityAssignment; import dkohl.bayes.probability.ProbabilityAssignment;
import dkohl.bayes.probability.Variable; import dkohl.bayes.probability.Variable;
import dkohl.util.RootMeanSquareError;
public class BayesChef { public class BayesChef {
public static void main(String... args) { public static void main(String... args) {
System.out.println("Reading recipe book."); System.out.println("Reading recipe book.");
RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/short_recipebook.xml")); RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/long_recipebook.xml"));
System.out.println("Reading survey data."); System.out.println("Reading survey data.");
Survey survey = SurveyReader.readSurvey(new File("data/short_survey.xml")); Survey survey = SurveyReader.readSurvey(new File("data/long_survey.xml"));
new BayesChef().reportBestMeal(recipeBook,survey); new BayesChef().reportBestMeal(recipeBook,survey);
} }
@@ -36,29 +34,39 @@ public class BayesChef {
System.out.println("Read data for " + numDiners + " diner(s)."); System.out.println("Read data for " + numDiners + " diner(s).");
System.out.println("Creating Bayes net for survey dataset..."); System.out.println("Creating Bayes net for survey dataset...");
BayesNet net = FoodNetBuilder.createDishNet(survey, recipeBook);
System.out.println("Querying Bayes net for individual flavor preferences: "); int numSurveyDishes = survey.getDishCount();
double[][] flavorPrefs = new double[4][]; int bayesNetIndexStart = 0;
int bayesNetIndexEnd = numSurveyDishes / 2;
flavorPrefs[0] = new double[] {0.0,printPreference(net, TYPE.PORK)}; int comparisonIndexStart = bayesNetIndexEnd;
flavorPrefs[1] = new double[] {1.0,printPreference(net, TYPE.BEEF)}; int comparisonIndexEnd = numSurveyDishes;
flavorPrefs[2] = new double[] {2.0,printPreference(net, TYPE.POTATO)};
flavorPrefs[3] = new double[] {3.0,printPreference(net, TYPE.TOMATO)};
SimpleRegression simpleRegression = new SimpleRegression(); //TODO change this to include min/max recipe indices for building the net
simpleRegression.addData(flavorPrefs); BayesNet net = FoodNetBuilder.createDishNet(survey, recipeBook, bayesNetIndexStart, bayesNetIndexEnd);
System.out.println("Individual flavor pref MSE: " + simpleRegression.getMeanSquareError()); System.out.println("Querying Bayes net for predicted flavor preferences: ");
simpleRegression.clear(); //TODO change this to query actual flavor combos from latter half of survey
double[] predictedRating = new double[numSurveyDishes - bayesNetIndexEnd];
System.out.println("Querying Bayes net for recipe flavor preferences: "); for (int i = comparisonIndexStart; i < comparisonIndexEnd; i++) {
flavorPrefs = new double[recipeBook.getSize()][]; predictedRating[i - comparisonIndexStart] = printPreference(net, recipeBook.getRecipe(survey.getDish(i)));
for (int i = 0; i < recipeBook.getSize(); i++) {
simpleRegression.addData(i,printPreference(net, recipeBook.getRecipe(i)));
} }
System.out.println("Recipe flavor pref MSE: " + simpleRegression.getMeanSquareError());
System.out.println("Querying survey dataset for actual recipe flavor preferences: ");
double[] actualRating = new double[predictedRating.length];
for (int i = comparisonIndexStart; i < comparisonIndexEnd; i++) {
actualRating[i - comparisonIndexStart] = survey.getAverageRating(i);
System.out.println("Actual average rating for " + survey.getDish(i) + ": " + actualRating[i - comparisonIndexStart]);
}
RootMeanSquareError rmse = new RootMeanSquareError();
for (int i = 0; i < actualRating.length; i++) {
rmse.push(predictedRating[i], actualRating[i]);
}
System.out.println("Root Mean Squared Error (predicted vs. actual): " + rmse.error());
} }
int printPreference(BayesNet net, Recipe recipe) { int printPreference(BayesNet net, Recipe recipe) {
@@ -69,7 +77,7 @@ public class BayesChef {
net, createQuery(ingredientTypes.toArray(new TYPE[ingredientTypes.size()]))); net, createQuery(ingredientTypes.toArray(new TYPE[ingredientTypes.size()])));
double max_val = 0.0; double max_val = 0.0;
String max_arg = "N/A"; String max_arg = "0";
for (ProbabilityAssignment p : probs) { for (ProbabilityAssignment p : probs) {
if (p.getProbability() > max_val) { if (p.getProbability() > max_val) {
max_val = p.getProbability(); max_val = p.getProbability();
@@ -106,6 +114,7 @@ public class BayesChef {
case BEEF: case BEEF:
case POTATO: case POTATO:
case TOMATO: case TOMATO:
case GENERIC_NUTS:
assignment.add(new Assignment(new Variable(type.toString(), FoodNetBuilder.DOMAIN), assignment.add(new Assignment(new Variable(type.toString(), FoodNetBuilder.DOMAIN),
FoodNetBuilder.TRUE_VALUE)); FoodNetBuilder.TRUE_VALUE));
break; break;

View File

@@ -9,7 +9,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
public class Diner { public class Diner {
private int id; private int id;
private Map<Integer,Integer> ratings = new HashMap<Integer,Integer>(); private Map<Integer,Integer> ratings = new HashMap<Integer,Integer>();
private Map<Integer,Boolean> allergies = new HashMap<Integer,Boolean>(); private Map<Integer,Boolean> categories = new HashMap<Integer,Boolean>();
public int getId() { public int getId() {
return id; return id;
@@ -19,7 +19,7 @@ public class Diner {
return ratings.get(dishId); return ratings.get(dishId);
} }
public boolean isAllergic(int categoryId) { public boolean isCategory(int categoryId) {
return allergies.get(categoryId); return categories.get(categoryId);
} }
} }

View File

@@ -1,15 +1,13 @@
package net.woodyfolsom.cs6601.p2; package net.woodyfolsom.cs6601.p2;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("ing") @XStreamAlias("ing")
public class Ingredient { public class Ingredient {
public enum TYPE { ALCOHOL, BEEF, DAIRY, EGGS, FISH, GLUTEN, GRAIN, NUTS, PORK, POULTRY, POTATO, SHELLFISH, SPICE, SUGAR, TOMATO} public enum TYPE { ALCOHOL, BEEF, DAIRY, EGGS, FISH, GENERIC_NUTS, GLUTEN, GRAIN, PORK, POULTRY, POTATO, SHELLFISH, SPICE, SUGAR, TOMATO}
private String item; private String item;
@@ -30,11 +28,15 @@ public class Ingredient {
public boolean isType(TYPE type) { public boolean isType(TYPE type) {
switch (type) { switch (type) {
case BEEF : case BEEF :
return item.contains("beef"); //For our purposes, veal is just expensive beef
return item.contains("beef") || item.contains("veal");
case DAIRY : case DAIRY :
return item.contains("margarine"); return item.contains("margarine") || item.contains("milk");
case EGGS : case EGGS :
return item.equals("egg") || item.equals("eggs"); return item.equals("egg") || item.equals("eggs");
case GENERIC_NUTS :
//cashews, peanuts or generic nuts
return item.contains("cashew") || item.contains("peanut") || item.contains("nuts");
case GLUTEN : case GLUTEN :
return item.contains("flour"); return item.contains("flour");
case PORK : case PORK :

View File

@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit; import com.thoughtworks.xstream.annotations.XStreamImplicit;
@@ -16,6 +17,32 @@ public class Survey {
@XStreamImplicit(itemFieldName="diner") @XStreamImplicit(itemFieldName="diner")
private List<Diner> diners = new ArrayList<Diner>(); private List<Diner> diners = new ArrayList<Diner>();
public double getAverageRating(int recipeIndex) {
double total = 0.0;
for (Diner diner : diners) {
total += diner.getRating(recipeIndex);
}
return total/diners.size();
}
public boolean isDiner(String category) {
for (int i = 0; i < diners.size(); i++) {
if (isCategory(i,category)) {
return true;
}
}
return false;
}
public boolean isCategory(int dinerIndex, String category) {
for (Entry<Integer,String> entry : categories.entrySet()) {
if (entry.getValue().equals(category)) {
return diners.get(dinerIndex).isCategory(entry.getKey());
}
}
return false;
}
public Diner getDiner(int dinerIndex) { public Diner getDiner(int dinerIndex) {
return diners.get(dinerIndex); return diners.get(dinerIndex);
} }

View File

@@ -18,10 +18,10 @@ import org.junit.Test;
public class RecipeBookReaderTest { public class RecipeBookReaderTest {
@Test @Test
public void testReadSurveyDataset() { public void testReadLongRecipeBook() {
RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/survey_recipes.xml")); RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/long_recipebook.xml"));
assertNotNull(recipeBook); assertNotNull(recipeBook);
assertThat(recipeBook.getSize(), is(equalTo(22))); assertThat(recipeBook.getSize(), is(equalTo(25)));
Recipe recipe = recipeBook.getRecipe(0); Recipe recipe = recipeBook.getRecipe(0);
System.out.println(recipe.getHead().getTitle()); System.out.println(recipe.getHead().getTitle());
@@ -39,7 +39,28 @@ public class RecipeBookReaderTest {
} }
@Test @Test
public void testReadShortSurveyDataset() { public void testReadMediumRecipeBook() {
RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/medium_recipebook.xml"));
assertNotNull(recipeBook);
assertThat(recipeBook.getSize(), is(equalTo(4)));
Recipe recipe = recipeBook.getRecipe(0);
System.out.println(recipe.getHead().getTitle());
assertThat(recipe.getHead().getTitle(), is(equalTo("Catalan Rice")));
assertFalse(recipe.getIngredients().contains(TYPE.EGGS));
assertFalse(recipe.getIngredients().contains(TYPE.GLUTEN));
assertTrue(recipe.getIngredients().contains(TYPE.SPICE));
assertFalse(recipe.getIngredients().contains(TYPE.BEEF));
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());
}
}
@Test
public void testReadShortRecipeBook() {
RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/short_recipebook.xml")); RecipeBook recipeBook = RecipeBookReader.readRecipeBook(new File("data/short_recipebook.xml"));
assertNotNull(recipeBook); assertNotNull(recipeBook);
assertThat(recipeBook.getSize(), is(equalTo(4))); assertThat(recipeBook.getSize(), is(equalTo(4)));

View File

@@ -12,13 +12,37 @@ import org.junit.Test;
public class SurveyReaderTest { public class SurveyReaderTest {
@Test @Test
public void testReadSurveyDataset() { public void testReadLongSurveyDataset() {
Survey survey = SurveyReader.readSurvey(new File("data/survey.xml")); Survey survey = SurveyReader.readSurvey(new File("data/long_survey.xml"));
assertNotNull(survey); assertNotNull(survey);
assertThat(survey.getDinerCount(), equalTo(5)); assertThat(survey.getDishCount(), equalTo(10));
assertThat(survey.getDinerCount(), equalTo(4));
assertThat(survey.isCategory(0,"vegetarian"), is(false));
assertThat(survey.isCategory(0,"allergic-nuts"), is(false));
assertThat(survey.isCategory(1,"vegetarian"), is(true));
assertThat(survey.isCategory(1,"allergic-nuts"), is(false));
assertThat(survey.isCategory(2,"vegan"), is(false));
assertThat(survey.isCategory(2,"allergic-nuts"), is(true));
assertThat(survey.isDiner("vegetarian"), is(true));
assertThat(survey.isDiner("allergic-nuts"), is(true));
assertThat(survey.isDiner("rastafarian"), is(false));
}
@Test
public void testReadMediumSurveyDataset() {
Survey survey = SurveyReader.readSurvey(new File("data/medium_survey.xml"));
assertNotNull(survey);
assertThat(survey.getDinerCount(), equalTo(2));
Diner diner = survey.getDiner(0); Diner diner = survey.getDiner(0);
assertThat(diner.isAllergic(0), is(false)); assertThat(diner.isCategory(0), is(false));
diner = survey.getDiner(1);
assertThat(diner.isCategory(0), is(true));
} }
} }