http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/collections/MediumProductCollection.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/collections/MediumProductCollection.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/collections/MediumProductCollection.java
new file mode 100644
index 0000000..c9683bc
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/collections/MediumProductCollection.java
@@ -0,0 +1,275 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.collections;
+
+import java.util.List;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.PetSpecies;
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ProductCategory;
+import 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.ProductCategoryBuilder;
+import 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.ProductFieldValue;
+import 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules.AndRule;
+import 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules.FieldPredicate;
+import 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules.NotRule;
+import 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules.OrRule;
+
+import com.google.common.collect.Lists;
+
+public class MediumProductCollection
+{
+       private ProductCategory createDogFood()
+       {
+               ProductCategoryBuilder builder = new ProductCategoryBuilder();
+
+               builder.addApplicableSpecies(PetSpecies.DOG);
+               builder.setCategory("dry dog food");
+               builder.setTriggerTransaction(true);
+               builder.setDailyUsageRate(2.0);
+               builder.setAmountUsedPetPetAverage(0.25);
+               builder.setAmountUsedPetPetVariance(0.1);
+               builder.setTriggerTransactionRate(2.0);
+               builder.setTriggerPurchaseRate(7.0);
+               builder.setBasePrice(2.0);
+
+               builder.addPropertyValues("brand",
+                               new ProductFieldValue("Wellfed", 0.67, 1.0),
+                               new ProductFieldValue("Happy Pup", 0.67, 1.0),
+                               new ProductFieldValue("Dog Days", 1.0, 1.0),
+                               new ProductFieldValue("Chef Corgi", 0.0, 1.0));
+
+               builder.addPropertyValues("meat",
+                               new ProductFieldValue("Chicken", 0.0, 1.0),
+                               new ProductFieldValue("Pork", 0.0, 1.0),
+                               new ProductFieldValue("Lamb", 0.1, 1.0),
+                               new ProductFieldValue("Salmon", 0.25, 1.0),
+                               new ProductFieldValue("Venison", 0.5, 1.0),
+                               new ProductFieldValue("Rabbit", 0.5, 1.0),
+                               new ProductFieldValue("Vegetarian", 0.0, 1.0));
+
+               builder.addPropertyValues("grain",
+                               new ProductFieldValue("Corn", 0.0, 1.0),
+                               new ProductFieldValue("Potatoes", 0.1, 1.0),
+                               new ProductFieldValue("Barley", 0.1, 1.0),
+                               new ProductFieldValue("Rice", 0.0, 1.0),
+                               new ProductFieldValue("Soy", 0.1, 1.0));
+
+               builder.addPropertyValues("lifestage",
+                               new ProductFieldValue("Senior", 0.0, 1.0),
+                               new ProductFieldValue("Puppy", 0.0, 1.0),
+                               new ProductFieldValue("Adult", 0.0, 1.0));
+
+               builder.addPropertyValues("organic",
+                               new ProductFieldValue("false", 0.0, 1.0),
+                               new ProductFieldValue("true", 0.0, 1.1));
+
+               builder.addPropertyValues("quantity",
+                               new ProductFieldValue(4.5, 0.0, 4.5),
+                               new ProductFieldValue(15.0, 0.0, 15.0),
+                               new ProductFieldValue(30.0, 0.0, 30.0));
+
+               builder.addExclusionRule(new AndRule(
+                               new FieldPredicate("brand", "Chef Corgi"),
+                               new FieldPredicate("organic", "true")));
+
+               builder.addExclusionRule(new AndRule(
+                               new FieldPredicate("brand", "Chef Corgi"),
+                               new FieldPredicate("meat", "Vegetarian")));
+
+               builder.addExclusionRule(new AndRule(
+                               new FieldPredicate("brand", "Dog Days"),
+                               new FieldPredicate("organic", "false")));
+
+               builder.addExclusionRule(new AndRule(
+                               new FieldPredicate("grain", "Corn"),
+                               new OrRule(
+                                               new FieldPredicate("organic", 
"true"),
+                                               new FieldPredicate("meat", 
"Venison"),
+                                               new FieldPredicate("meat", 
"Rabbit"),
+                                               new FieldPredicate("meat", 
"Lamb"),
+                                               new FieldPredicate("meat", 
"Salmon"))));
+
+               builder.addExclusionRule(new AndRule(
+                               new FieldPredicate("organic", "true"),
+                               new FieldPredicate("meat", "Pork")));
+
+               builder.addExclusionRule(new AndRule(
+                               new NotRule(new FieldPredicate("grain", 
"Corn")),
+                               new FieldPredicate("meat", "Pork")));
+
+               builder.addExclusionRule(new AndRule(
+                               new OrRule(
+                                               new FieldPredicate("brand", 
"Chef Corgi"),
+                                               new FieldPredicate("brand", 
"Happy Pup")),
+                               new OrRule(
+                                               new FieldPredicate("meat", 
"Rabbit"),
+                                               new FieldPredicate("meat", 
"Venison"))
+                                               ));
+
+               return builder.build();
+       }
+
+       private ProductCategory createCatFood()
+       {
+               ProductCategoryBuilder builder = new ProductCategoryBuilder();
+
+               builder.addApplicableSpecies(PetSpecies.CAT);
+               builder.setCategory("dry cat food");
+               builder.setTriggerTransaction(true);
+               builder.setDailyUsageRate(2.0);
+               builder.setAmountUsedPetPetAverage(0.1);
+               builder.setAmountUsedPetPetVariance(0.05);
+               builder.setTriggerTransactionRate(2.0);
+               builder.setTriggerPurchaseRate(7.0);
+               builder.setBasePrice(2.14);
+
+               builder.addPropertyValues("brand",
+                               new ProductFieldValue("Wellfed", 0.67, 1.0),
+                               new ProductFieldValue("Feisty Feline", 0.72, 
1.0),
+                               new ProductFieldValue("Pretty Cat", 0.0, 1.0));
+
+               builder.addPropertyValues("meat",
+                               new ProductFieldValue("Tuna", 0.0, 1.0),
+                               new ProductFieldValue("Chicken", 0.0, 1.0),
+                               new ProductFieldValue("Turkey", 0.0, 1.0),
+                               new ProductFieldValue("Salmon", 0.1, 1.0));
+
+               builder.addPropertyValues("lifestyle",
+                               new ProductFieldValue("Indoor", 0.0, 1.0),
+                               new ProductFieldValue("Outdoor", 0.0, 1.0),
+                               new ProductFieldValue("Weight Management", 0.1, 
1.0));
+
+               builder.addPropertyValues("lifestage",
+                               new ProductFieldValue("Senior", 0.0, 1.0),
+                               new ProductFieldValue("Kitten", 0.0, 1.0),
+                               new ProductFieldValue("Adult", 0.0, 1.0));
+
+               builder.addPropertyValues("organic",
+                               new ProductFieldValue("true", 0.0, 1.1),
+                               new ProductFieldValue("false", 0.0, 1.0));
+
+               builder.addPropertyValues("quantity",
+                               new ProductFieldValue(7.0, 0.0, 7.0),
+                               new ProductFieldValue(15.0, 0.0, 15.0));
+
+               builder.addPropertyValues("hairball management",
+                               new ProductFieldValue("true", 0.1, 1.0),
+                               new ProductFieldValue("false", 0.0, 1.0));
+
+               builder.addExclusionRule(new AndRule(
+                                       new FieldPredicate("brand", "Pretty 
Cat"),
+                                       new FieldPredicate("organic", "true")));
+
+               builder.addExclusionRule(new AndRule(
+                               new FieldPredicate("brand", "Feisty Feline"),
+                               new FieldPredicate("organic", "false")));
+
+               return builder.build();
+       }
+
+       private ProductCategory createKittyLitter()
+       {
+               ProductCategoryBuilder builder = new ProductCategoryBuilder();
+
+               builder.addApplicableSpecies(PetSpecies.CAT);
+               builder.setCategory("kitty litter");
+               builder.setTriggerTransaction(true);
+               builder.setDailyUsageRate(1.0);
+               builder.setAmountUsedPetPetAverage(0.1);
+               builder.setAmountUsedPetPetVariance(0.05);
+               builder.setTriggerTransactionRate(2.0);
+               builder.setTriggerPurchaseRate(7.0);
+               builder.setBasePrice(1.43);
+
+               builder.addPropertyValues("brand",
+                               new ProductFieldValue("Pretty Cat", 0.0, 1.0),
+                               new ProductFieldValue("Feisty Feline", 0.1, 
1.0));
+
+               builder.addPropertyValues("material",
+                               new ProductFieldValue("clay", 0.0, 1.0),
+                               new ProductFieldValue("pellets", 0.1, 1.0));
+
+               builder.addPropertyValues("clumping",
+                               new ProductFieldValue("true", 0.0, 1.0),
+                               new ProductFieldValue("false", 0.0, 1.0));
+
+               builder.addPropertyValues("odor control",
+                               new ProductFieldValue("true", 0.1, 1.0),
+                               new ProductFieldValue("false", 0.0, 1.0));
+
+               builder.addPropertyValues("quantity",
+                               new ProductFieldValue(7.0, 0.0, 7.0),
+                               new ProductFieldValue(14.0, 0.0, 14.0),
+                               new ProductFieldValue(28.0, 0.0, 28.0));
+
+               return builder.build();
+       }
+
+       private ProductCategory createPoopBags()
+       {
+               ProductCategoryBuilder builder = new ProductCategoryBuilder();
+
+               builder.addApplicableSpecies(PetSpecies.DOG);
+               builder.setCategory("poop bags");
+               builder.setTriggerTransaction(true);
+               builder.setDailyUsageRate(2.0);
+               builder.setAmountUsedPetPetAverage(1.0);
+               builder.setAmountUsedPetPetVariance(0.5);
+               builder.setTriggerTransactionRate(2.0);
+               builder.setTriggerPurchaseRate(7.0);
+               builder.setBasePrice(0.17);
+
+               builder.addPropertyValues("brand",
+                               new ProductFieldValue("Chef Corgi", 0.0, 1.0),
+                               new ProductFieldValue("Happy Pup", 0.67, 1.0),
+                               new ProductFieldValue("Dog Days", 1.0, 1.0));
+
+               builder.addPropertyValues("color",
+                               new ProductFieldValue("blue", 0.0, 1.0),
+                               new ProductFieldValue("multicolor (pastels)", 
0.0, 1.0),
+                               new ProductFieldValue("multicolor (solids)", 
0.0, 1.0),
+                               new ProductFieldValue("designs", 0.0, 1.0));
+
+               builder.addPropertyValues("recycled material",
+                               new ProductFieldValue("false", 0.0, 60.0),
+                               new ProductFieldValue("true", 0.1, 120.0));
+
+               builder.addPropertyValues("quantity",
+                               new ProductFieldValue(60.0, 0.0, 60.0),
+                               new ProductFieldValue(120.0, 0.0, 120.0));
+
+               builder.addExclusionRule(new AndRule(
+                               new FieldPredicate("brand", "Chef Corgi"),
+                               new FieldPredicate("recycled material", 
"true")));
+
+               builder.addExclusionRule(new AndRule(
+                               new FieldPredicate("brand", "Dog Days"),
+                               new FieldPredicate("recycled material", 
"false")));
+
+               return builder.build();
+       }
+
+       public List<ProductCategory> generateProductCategory()
+       {
+               List<ProductCategory> productCategories = Lists.newArrayList();
+
+               productCategories.add(this.createDogFood());
+               productCategories.add(this.createCatFood());
+               productCategories.add(this.createKittyLitter());
+               productCategories.add(this.createPoopBags());
+
+               return productCategories;
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/collections/SmallProductCollection.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/collections/SmallProductCollection.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/collections/SmallProductCollection.java
new file mode 100644
index 0000000..40edf78
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/collections/SmallProductCollection.java
@@ -0,0 +1,162 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.collections;
+
+import java.util.List;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.PetSpecies;
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ProductCategory;
+import 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.ProductCategoryBuilder;
+import 
org.apache.bigtop.datagenerators.bigpetstore.generators.products.ProductFieldValue;
+
+import com.google.common.collect.Lists;
+
+public class SmallProductCollection
+{
+       private ProductCategory createDogFood()
+       {
+               ProductCategoryBuilder builder = new ProductCategoryBuilder();
+
+               builder.addApplicableSpecies(PetSpecies.DOG);
+               builder.setCategory("dry dog food");
+               builder.setTriggerTransaction(true);
+               builder.setDailyUsageRate(2.0);
+               builder.setAmountUsedPetPetAverage(0.25);
+               builder.setAmountUsedPetPetVariance(0.1);
+               builder.setTriggerTransactionRate(2.0);
+               builder.setTriggerPurchaseRate(7.0);
+               builder.setBasePrice(2.0);
+
+               builder.addPropertyValues("brand",
+                               new ProductFieldValue("Wellfed", 0.0, 1.0),
+                               new ProductFieldValue("Happy Pup", 0.67, 1.0),
+                               new ProductFieldValue("Dog Days", 1.0, 1.0));
+
+               builder.addPropertyValues("flavor",
+                               new ProductFieldValue("Chicken", 0.0, 1.0),
+                               new ProductFieldValue("Pork", 0.0, 1.0),
+                               new ProductFieldValue("Lamb & Rice", 0.0, 1.0),
+                               new ProductFieldValue("Fish & Potato", 0.0, 
1.0));
+
+               builder.addPropertyValues("quantity",
+                               new ProductFieldValue(4.5, 0.0, 4.5),
+                               new ProductFieldValue(15.0, 0.0, 15.0),
+                               new ProductFieldValue(30.0, 0.0, 30.0));
+
+               return builder.build();
+       }
+
+       private ProductCategory createCatFood()
+       {
+               ProductCategoryBuilder builder = new ProductCategoryBuilder();
+
+               builder.addApplicableSpecies(PetSpecies.CAT);
+               builder.setCategory("dry cat food");
+               builder.setTriggerTransaction(true);
+               builder.setDailyUsageRate(2.0);
+               builder.setAmountUsedPetPetAverage(0.1);
+               builder.setAmountUsedPetPetVariance(0.05);
+               builder.setTriggerTransactionRate(2.0);
+               builder.setTriggerPurchaseRate(7.0);
+               builder.setBasePrice(2.14);
+
+               builder.addPropertyValues("brand",
+                               new ProductFieldValue("Wellfed", 0.0, 1.0),
+                               new ProductFieldValue("Pretty Cat", 0.72, 1.0),
+                               new ProductFieldValue("Feisty Feline", 0.0, 
1.0));
+
+               builder.addPropertyValues("flavor",
+                               new ProductFieldValue("Tuna", 0.0, 1.0),
+                               new ProductFieldValue("Chicken & Rice", 0.0, 
1.0));
+
+               builder.addPropertyValues("quantity",
+                               new ProductFieldValue(7.0, 0.0, 7.0),
+                               new ProductFieldValue(15.0, 0.0, 15.0));
+
+               builder.addPropertyValues("hairball management",
+                               new ProductFieldValue("true", 0.0, 1.0),
+                               new ProductFieldValue("false", 0.0, 1.0));
+
+               return builder.build();
+       }
+
+       private ProductCategory createKittyLitter()
+       {
+               ProductCategoryBuilder builder = new ProductCategoryBuilder();
+
+               builder.addApplicableSpecies(PetSpecies.CAT);
+               builder.setCategory("kitty litter");
+               builder.setTriggerTransaction(true);
+               builder.setDailyUsageRate(1.0);
+               builder.setAmountUsedPetPetAverage(0.1);
+               builder.setAmountUsedPetPetVariance(0.05);
+               builder.setTriggerTransactionRate(2.0);
+               builder.setTriggerPurchaseRate(7.0);
+               builder.setBasePrice(1.43);
+
+               builder.addPropertyValues("brand",
+                               new ProductFieldValue("Pretty Cat", 0.0, 1.0),
+                               new ProductFieldValue("Feisty Feline", 0.07, 
1.0));
+
+               builder.addPropertyValues("quantity",
+                               new ProductFieldValue(7.0, 0.0, 7.0),
+                               new ProductFieldValue(14.0, 0.0, 14.0),
+                               new ProductFieldValue(28.0, 0.0, 28.0));
+
+               return builder.build();
+       }
+
+       private ProductCategory createPoopBags()
+       {
+               ProductCategoryBuilder builder = new ProductCategoryBuilder();
+
+               builder.addApplicableSpecies(PetSpecies.DOG);
+               builder.setCategory("poop bags");
+               builder.setTriggerTransaction(true);
+               builder.setDailyUsageRate(2.0);
+               builder.setAmountUsedPetPetAverage(1.0);
+               builder.setAmountUsedPetPetVariance(0.5);
+               builder.setTriggerTransactionRate(2.0);
+               builder.setTriggerPurchaseRate(7.0);
+               builder.setBasePrice(0.17);
+
+               builder.addPropertyValues("brand",
+                               new ProductFieldValue("Happy Pup", 0.0, 1.0),
+                               new ProductFieldValue("Dog Days", 0.04, 1.0));
+
+               builder.addPropertyValues("color",
+                               new ProductFieldValue("blue", 0.0, 1.0),
+                               new ProductFieldValue("multicolor", 0.0, 1.0));
+
+               builder.addPropertyValues("quantity",
+                               new ProductFieldValue(60.0, 0.0, 60.0),
+                               new ProductFieldValue(120.0, 0.0, 120.0));
+
+               return builder.build();
+       }
+
+       public List<ProductCategory> generateProductCategory()
+       {
+               List<ProductCategory> productCategories = Lists.newArrayList();
+
+               productCategories.add(this.createDogFood());
+               productCategories.add(this.createCatFood());
+               productCategories.add(this.createKittyLitter());
+               productCategories.add(this.createPoopBags());
+
+               return productCategories;
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/AlwaysTrueRule.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/AlwaysTrueRule.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/AlwaysTrueRule.java
new file mode 100644
index 0000000..a89022e
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/AlwaysTrueRule.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+
+public class AlwaysTrueRule implements Rule
+{
+
+       @Override
+       public boolean ruleMatches(Product product) throws 
IllegalArgumentException
+       {
+               return true;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/AndRule.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/AndRule.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/AndRule.java
new file mode 100644
index 0000000..5186423
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/AndRule.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+
+public class AndRule implements Rule
+{
+       List<Rule> rules;
+
+       public AndRule(Rule rule1, Rule rule2, Rule ... rules)
+       {
+               this.rules = new LinkedList<Rule>(Arrays.asList(rules));
+               this.rules.add(rule1);
+               this.rules.add(rule2);
+       }
+
+       @Override
+       public boolean ruleMatches(Product product) throws 
IllegalArgumentException
+       {
+               boolean matches = true;
+               for(Rule rule : rules)
+               {
+                       if(! rule.ruleMatches(product))
+                       {
+                               matches = false;
+                       }
+               }
+
+               return matches;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/FieldPredicate.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/FieldPredicate.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/FieldPredicate.java
new file mode 100644
index 0000000..bd96ccd
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/FieldPredicate.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+
+public class FieldPredicate implements Rule
+{
+       String fieldName;
+       Collection<String> allowedValues;
+
+       public FieldPredicate(String fieldName, String ... allowedValues)
+       {
+               this.fieldName = fieldName;
+               this.allowedValues = Arrays.asList(allowedValues);
+       }
+
+       @Override
+       public boolean ruleMatches(Product product)
+       {
+               if(! product.getFieldNames().contains(fieldName))
+               {
+                       throw new IllegalArgumentException("Product (" + 
product.toString() +
+                                       ") does not contain field name (" + 
fieldName + ")");
+               }
+
+               Object seenValue = product.getFieldValue(fieldName);
+
+               return allowedValues.contains(seenValue);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/NotRule.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/NotRule.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/NotRule.java
new file mode 100644
index 0000000..bed11fa
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/NotRule.java
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+
+public class NotRule implements Rule
+{
+       Rule rule;
+
+       public NotRule(Rule rule)
+       {
+               this.rule = rule;
+       }
+
+
+       @Override
+       public boolean ruleMatches(Product product) throws 
IllegalArgumentException
+       {
+               return ! rule.ruleMatches(product);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/OrRule.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/OrRule.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/OrRule.java
new file mode 100644
index 0000000..c979e02
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/OrRule.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+
+public class OrRule implements Rule
+{
+       Rule[] rules;
+
+       public OrRule(Rule ... rules)
+       {
+               this.rules = rules;
+       }
+
+       @Override
+       public boolean ruleMatches(Product product) throws 
IllegalArgumentException
+       {
+               for(Rule rule : rules)
+               {
+                       if(rule.ruleMatches(product))
+                       {
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/Rule.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/Rule.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/Rule.java
new file mode 100644
index 0000000..c3ad6f3
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/products/rules/Rule.java
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.products.rules;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+
+public interface Rule
+{
+       public boolean ruleMatches(Product product) throws 
IllegalArgumentException;
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovModelProductCategorySampler.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovModelProductCategorySampler.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovModelProductCategorySampler.java
new file mode 100644
index 0000000..e2549f7
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovModelProductCategorySampler.java
@@ -0,0 +1,119 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.purchase;
+
+import java.util.Map;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ProductCategory;
+import org.apache.bigtop.datagenerators.samplers.markovmodels.MarkovModel;
+import 
org.apache.bigtop.datagenerators.samplers.markovmodels.MarkovModelBuilder;
+import org.apache.bigtop.datagenerators.samplers.samplers.Sampler;
+
+import com.google.common.collect.Maps;
+
+public class MarkovModelProductCategorySampler implements 
Sampler<MarkovModel<Product>>
+{
+       final ProductCategory productCategory;
+       final Sampler<Double> fieldSimilarityWeightSampler;
+       final Sampler<Double> loopbackWeightSampler;
+
+       final Map<String, Double> fieldWeights;
+       Map<String, Double> fieldSimilarityWeights;
+       double loopbackWeight;
+
+       public MarkovModelProductCategorySampler(ProductCategory 
productCategory,
+                       Map<String, Double> fieldWeights, Sampler<Double> 
fieldSimilarityWeightSampler,
+                       Sampler<Double> loopbackWeightSampler)
+       {
+               this.productCategory = productCategory;
+
+               this.fieldSimilarityWeightSampler = 
fieldSimilarityWeightSampler;
+               this.fieldWeights = fieldWeights;
+               this.loopbackWeightSampler = loopbackWeightSampler;
+       }
+
+       protected void generateWeights() throws Exception
+       {
+               fieldSimilarityWeights = Maps.newHashMap();
+
+               for(String fieldName : productCategory.getFieldNames())
+               {
+                       
fieldSimilarityWeights.put(fieldName,fieldSimilarityWeightSampler.sample());
+               }
+
+               loopbackWeight = loopbackWeightSampler.sample();
+       }
+
+       protected double productPairWeight(Product product1, Product product2)
+       {
+               double weightSum = 0.0;
+               for(String fieldName : productCategory.getFieldNames())
+               {
+                       double fieldWeight = this.fieldWeights.get(fieldName);
+
+                       
if(product1.getFieldValue(fieldName).equals(product2.getFieldValue(fieldName)))
+                       {
+                               fieldWeight *= 
this.fieldSimilarityWeights.get(fieldName);
+                       }
+                       else
+                       {
+                               fieldWeight *= (1.0 - 
this.fieldSimilarityWeights.get(fieldName));
+                       }
+
+                       weightSum += fieldWeight;
+               }
+               return weightSum;
+       }
+
+       public MarkovModel<Product> sample() throws Exception
+       {
+               generateWeights();
+
+               MarkovModelBuilder<Product> builder = new 
MarkovModelBuilder<Product>();
+
+               for(Product product1 : productCategory.getProducts())
+               {
+                       builder.addStartState(product1, 1.0);
+
+                       double weightSum = 0.0;
+                       for(Product product2 : productCategory.getProducts())
+                       {
+                               if(!product1.equals(product2))
+                               {
+                                       weightSum += 
productPairWeight(product1, product2);
+                               }
+                       }
+
+                       for(Product product2 : productCategory.getProducts())
+                       {
+                               double weight = 0.0;
+                               if(!product1.equals(product2))
+                               {
+                                       weight = (1.0 - loopbackWeight) * 
productPairWeight(product1, product2) / weightSum;
+                               }
+                               else
+                               {       weight = loopbackWeight;
+
+                               }
+
+                               builder.addTransition(product1, product2, 
weight);
+                       }
+               }
+
+               return builder.build();
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovPurchasingModel.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovPurchasingModel.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovPurchasingModel.java
new file mode 100644
index 0000000..6855aa8
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovPurchasingModel.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.purchase;
+
+import java.util.Map;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+import org.apache.bigtop.datagenerators.samplers.SeedFactory;
+import org.apache.bigtop.datagenerators.samplers.markovmodels.MarkovModel;
+import org.apache.bigtop.datagenerators.samplers.markovmodels.MarkovProcess;
+import org.apache.bigtop.datagenerators.samplers.samplers.Sampler;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+
+public class MarkovPurchasingModel implements 
PurchasingModel<MarkovModel<Product>>
+{
+
+       private static final long serialVersionUID = 3098355461347511619L;
+       ImmutableMap<String, MarkovModel<Product>> productCategoryProfiles;
+
+       public MarkovPurchasingModel(Map<String, MarkovModel<Product>> 
productCategoryProfiles)
+       {
+               this.productCategoryProfiles = 
ImmutableMap.copyOf(productCategoryProfiles);
+       }
+
+       @Override
+       public ImmutableSet<String> getProductCategories()
+       {
+               return productCategoryProfiles.keySet();
+       }
+
+       @Override
+       public MarkovModel<Product> getProfile(String productCategory)
+       {
+               return productCategoryProfiles.get(productCategory);
+       }
+
+       @Override
+       public PurchasingProcesses buildProcesses(SeedFactory seedFactory)
+       {
+               Map<String, Sampler<Product>> processes = Maps.newHashMap();
+               for(String category : getProductCategories())
+               {
+                       MarkovModel<Product> model = getProfile(category);
+                       processes.put(category, new 
MarkovProcess<Product>(model, seedFactory));
+               }
+
+               return new PurchasingProcesses(processes);
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovPurchasingModelSampler.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovPurchasingModelSampler.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovPurchasingModelSampler.java
new file mode 100644
index 0000000..7beb634
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MarkovPurchasingModelSampler.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.purchase;
+
+import java.util.Map;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ProductCategory;
+import org.apache.bigtop.datagenerators.samplers.markovmodels.MarkovModel;
+import org.apache.bigtop.datagenerators.samplers.samplers.Sampler;
+
+import com.google.common.collect.Maps;
+
+public class MarkovPurchasingModelSampler implements 
Sampler<MarkovPurchasingModel>
+{
+       final Map<ProductCategory, Sampler<MarkovModel<Product>>> 
categorySamplers;
+
+       public MarkovPurchasingModelSampler(Map<ProductCategory, 
Sampler<MarkovModel<Product>>> categorySamplers)
+       {
+               this.categorySamplers = categorySamplers;
+       }
+
+       public MarkovPurchasingModel sample() throws Exception
+       {
+               Map<String, MarkovModel<Product>> markovModels = 
Maps.newHashMap();
+               for(ProductCategory productCategory : categorySamplers.keySet())
+               {
+                       Sampler<MarkovModel<Product>> sampler = 
categorySamplers.get(productCategory);
+                       markovModels.put(productCategory.getCategoryLabel(), 
sampler.sample());
+               }
+
+               return new MarkovPurchasingModel(markovModels);
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MultinomialPurchasingModel.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MultinomialPurchasingModel.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MultinomialPurchasingModel.java
new file mode 100644
index 0000000..f0c90fe
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MultinomialPurchasingModel.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.purchase;
+
+import java.util.Map;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+import org.apache.bigtop.datagenerators.samplers.SeedFactory;
+import org.apache.bigtop.datagenerators.samplers.pdfs.MultinomialPDF;
+import org.apache.bigtop.datagenerators.samplers.samplers.RouletteWheelSampler;
+import org.apache.bigtop.datagenerators.samplers.samplers.Sampler;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+
+public class MultinomialPurchasingModel implements 
PurchasingModel<MultinomialPDF<Product>>
+{
+
+       private static final long serialVersionUID = 5863830733003282570L;
+
+       private final ImmutableMap<String, MultinomialPDF<Product>> productPDFs;
+
+       public MultinomialPurchasingModel(Map<String, MultinomialPDF<Product>> 
productPDFs)
+       {
+               this.productPDFs = ImmutableMap.copyOf(productPDFs);
+       }
+
+       @Override
+       public ImmutableSet<String> getProductCategories()
+       {
+               return productPDFs.keySet();
+       }
+
+       @Override
+       public MultinomialPDF<Product> getProfile(String category)
+       {
+               return productPDFs.get(category);
+       }
+
+       @Override
+       public PurchasingProcesses buildProcesses(SeedFactory seedFactory)
+       {
+               Map<String, Sampler<Product>> processes = Maps.newHashMap();
+               for(String category : getProductCategories())
+               {
+                       MultinomialPDF<Product> pdf = productPDFs.get(category);
+                       processes.put(category, 
RouletteWheelSampler.create(pdf, seedFactory));
+               }
+
+               return new PurchasingProcesses(processes);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MultinomialPurchasingModelSampler.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MultinomialPurchasingModelSampler.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MultinomialPurchasingModelSampler.java
new file mode 100644
index 0000000..b190cb1
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/MultinomialPurchasingModelSampler.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.purchase;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.bigtop.datagenerators.bigpetstore.Constants;
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ProductCategory;
+import org.apache.bigtop.datagenerators.samplers.SeedFactory;
+import org.apache.bigtop.datagenerators.samplers.pdfs.MultinomialPDF;
+import org.apache.bigtop.datagenerators.samplers.samplers.Sampler;
+import org.apache.bigtop.datagenerators.samplers.samplers.UniformIntSampler;
+import org.apache.bigtop.datagenerators.samplers.samplers.UniformSampler;
+import org.apache.commons.lang3.tuple.Pair;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+
+public class MultinomialPurchasingModelSampler implements 
Sampler<MultinomialPurchasingModel>
+{
+       private final SeedFactory seedFactory;
+       private final Collection<ProductCategory> productCategories;
+
+       public MultinomialPurchasingModelSampler(Collection<ProductCategory> 
productCategories, SeedFactory seedFactory)
+       {
+               this.seedFactory = seedFactory;
+               this.productCategories = productCategories;
+       }
+
+       protected <T> List<T> shuffle(Collection<T> input) throws Exception
+       {
+               Vector<T> shuffled = new Vector<>(input);
+               for(int i = 0; i < input.size() - 1; i++)
+               {
+                       int swapIdx = new UniformIntSampler(i, input.size() - 
1, seedFactory).sample();
+                       T tmp = shuffled.get(i);
+                       shuffled.set(i, shuffled.get(swapIdx));
+                       shuffled.set(swapIdx, tmp);
+               }
+
+               return shuffled;
+       }
+
+       protected Map<Pair<String, Object>, Double> 
generateFieldValueWeights(ProductCategory productCategory) throws Exception
+       {
+               // Get all values for each field by iterating over all products
+               Multimap<String, Object> allFieldValues = HashMultimap.create();
+               for(String fieldName : productCategory.getFieldNames())
+               {
+                       
if(!Constants.PRODUCT_MODEL_EXCLUDED_FIELDS.contains(fieldName))
+                       {
+                               for(Product p : productCategory.getProducts())
+                               {
+                                       Object fieldValue = 
p.getFieldValue(fieldName);
+                                       allFieldValues.put(fieldName, 
fieldValue);
+                               }
+                       }
+               }
+
+               Sampler<Double> sampler = new UniformSampler(seedFactory);
+
+               // shuffle field values
+               Map<Pair<String, Object>, Double> fieldValueWeights = 
Maps.newHashMap();
+               for(Map.Entry<String, Collection<Object>> entry : 
allFieldValues.asMap().entrySet())
+               {
+                       String fieldName = entry.getKey();
+                       List<Object> shuffled = shuffle(entry.getValue());
+
+                       for(int i = 0; i < shuffled.size(); i++)
+                       {
+                               double weight = 
Constants.PRODUCT_MULTINOMIAL_POSITIVE_WEIGHT;
+                               if ((i + 1) > 
Constants.PRODUCT_MULTINOMIAL_POSITIVE_COUNT_MIN)
+                               {
+                                       double r = sampler.sample();
+                                       if (r >= 
Constants.PRODUCT_MULTINOMIAL_POSITIVE_FREQUENCY)
+                                       {
+                                               weight = 
Constants.PRODUCT_MULTINOMIAL_NEGATIVE_WEIGHT;
+                                       }
+                               }
+
+                               Object fieldValue = shuffled.get(i);
+                               fieldValueWeights.put(Pair.of(fieldName, 
fieldValue), weight);
+                       }
+               }
+
+
+               return ImmutableMap.copyOf(fieldValueWeights);
+       }
+
+       protected Map<Product, Double> generateProductWeights(Map<Pair<String, 
Object>, Double> fieldValueWeights,
+                       ProductCategory productCategory) throws Exception
+       {
+               Map<Product, Double> productWeights = Maps.newHashMap();
+               for(Product p : productCategory.getProducts())
+               {
+                       double weight = 1.0;
+                       for(String fieldName : productCategory.getFieldNames())
+                       {
+                               
if(!Constants.PRODUCT_MODEL_EXCLUDED_FIELDS.contains(fieldName))
+                               {
+                                       Object fieldValue = 
p.getFieldValue(fieldName);
+                                       Pair<String, Object> key = 
Pair.of(fieldName, fieldValue);
+                                       weight *= fieldValueWeights.get(key);
+                               }
+                       }
+                       productWeights.put(p, weight);
+               }
+
+               return productWeights;
+       }
+
+       public MultinomialPurchasingModel sample() throws Exception
+       {
+               Map<String, MultinomialPDF<Product>> pdfs = Maps.newHashMap();
+               for(ProductCategory productCategory : productCategories)
+               {
+                       Map<Pair<String, Object>, Double> fieldWeights = 
this.generateFieldValueWeights(productCategory);
+                       Map<Product, Double> productWeights = 
this.generateProductWeights(fieldWeights, productCategory);
+                       pdfs.put(productCategory.getCategoryLabel(), new 
MultinomialPDF<Product>(productWeights));
+               }
+
+               return new MultinomialPurchasingModel(pdfs);
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingModel.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingModel.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingModel.java
new file mode 100644
index 0000000..eddc0a0
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingModel.java
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.purchase;
+
+import java.io.Serializable;
+
+import org.apache.bigtop.datagenerators.samplers.SeedFactory;
+
+import com.google.common.collect.ImmutableSet;
+
+public interface PurchasingModel<T> extends Serializable
+{
+       public ImmutableSet<String> getProductCategories();
+
+       public T getProfile(String category);
+
+       public PurchasingProcesses buildProcesses(SeedFactory seedFactory);
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingModelSamplerBuilder.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingModelSamplerBuilder.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingModelSamplerBuilder.java
new file mode 100644
index 0000000..2a22487
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingModelSamplerBuilder.java
@@ -0,0 +1,108 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.purchase;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.bigtop.datagenerators.bigpetstore.Constants;
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ProductCategory;
+import org.apache.bigtop.datagenerators.samplers.SeedFactory;
+import org.apache.bigtop.datagenerators.samplers.markovmodels.MarkovModel;
+import 
org.apache.bigtop.datagenerators.samplers.samplers.BoundedMultiModalGaussianSampler;
+import org.apache.bigtop.datagenerators.samplers.samplers.Sampler;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+
+public class PurchasingModelSamplerBuilder
+{
+       final ImmutableList<ProductCategory> productCategories;
+       final SeedFactory seedFactory;
+
+       public PurchasingModelSamplerBuilder(Collection<ProductCategory> 
productCategories, SeedFactory seedFactory)
+       {
+               this.productCategories = 
ImmutableList.copyOf(productCategories);
+               this.seedFactory = seedFactory;
+       }
+
+       protected Map<String, Double> generateFieldWeights(Sampler<Double> 
fieldWeightSampler) throws Exception
+       {
+               Set<String> fieldNames = new HashSet<String>();
+               for(ProductCategory pc : productCategories)
+               {
+                       for(String fieldName : pc.getFieldNames())
+                       {
+                               fieldNames.add(fieldName);
+                       }
+               }
+
+               Map<String, Double> fieldWeights = Maps.newHashMap();
+               for(String fieldName : fieldNames)
+               {
+                       double weight = fieldWeightSampler.sample();
+                       fieldWeights.put(fieldName, weight);
+               }
+
+               return fieldWeights;
+       }
+
+       public Sampler<MarkovPurchasingModel> buildMarkovPurchasingModel() 
throws Exception
+       {
+
+               Sampler<Double> fieldWeightSampler = new 
BoundedMultiModalGaussianSampler(Constants.PRODUCT_MSM_FIELD_WEIGHT_GAUSSIANS,
+                               Constants.PRODUCT_MSM_FIELD_WEIGHT_LOWERBOUND,
+                               Constants.PRODUCT_MSM_FIELD_WEIGHT_UPPERBOUND,
+                               seedFactory);
+
+               Sampler<Double> fieldSimilarityWeightSampler = new 
BoundedMultiModalGaussianSampler(Constants.PRODUCT_MSM_FIELD_SIMILARITY_WEIGHT_GAUSSIANS,
+                               
Constants.PRODUCT_MSM_FIELD_SIMILARITY_WEIGHT_LOWERBOUND,
+                               
Constants.PRODUCT_MSM_FIELD_SIMILARITY_WEIGHT_UPPERBOUND,
+                               seedFactory);
+
+               Sampler<Double> loopbackWeightSampler = new 
BoundedMultiModalGaussianSampler(Constants.PRODUCT_MSM_LOOPBACK_WEIGHT_GAUSSIANS,
+                               
Constants.PRODUCT_MSM_LOOPBACK_WEIGHT_LOWERBOUND,
+                               
Constants.PRODUCT_MSM_LOOPBACK_WEIGHT_UPPERBOUND,
+                               seedFactory);
+
+               Map<String, Double> fieldWeights = 
generateFieldWeights(fieldWeightSampler);
+
+               Map<ProductCategory, Sampler<MarkovModel<Product>>> 
categorySamplers = Maps.newHashMap();
+               for(ProductCategory productCategory : productCategories)
+               {
+                       MarkovModelProductCategorySampler sampler = new 
MarkovModelProductCategorySampler(productCategory,
+                                       fieldWeights, 
fieldSimilarityWeightSampler, loopbackWeightSampler);
+                       categorySamplers.put(productCategory, sampler);
+               }
+
+               return new MarkovPurchasingModelSampler(categorySamplers);
+       }
+
+       public Sampler<? extends PurchasingModel> build() throws Exception
+       {
+               
if(Constants.PURCHASING_MODEL_TYPE.equals(Constants.PurchasingModelType.MARKOV))
+               {
+                       return buildMarkovPurchasingModel();
+               }
+               else
+               {
+                       return new 
MultinomialPurchasingModelSampler(productCategories, seedFactory);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingProcesses.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingProcesses.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingProcesses.java
new file mode 100644
index 0000000..99516d7
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/purchase/PurchasingProcesses.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.purchase;
+
+import java.util.Map;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+import org.apache.bigtop.datagenerators.samplers.samplers.ConditionalSampler;
+import org.apache.bigtop.datagenerators.samplers.samplers.Sampler;
+
+import com.google.common.collect.ImmutableMap;
+
+public class PurchasingProcesses implements ConditionalSampler<Product, String>
+{
+       ImmutableMap<String, Sampler<Product>> processes;
+
+       public PurchasingProcesses(Map<String, Sampler<Product>> processes)
+       {
+               this.processes = ImmutableMap.copyOf(processes);
+       }
+
+       public Product sample(String productCategory) throws Exception
+       {
+               return this.processes.get(productCategory).sample();
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreLocationIncomePDF.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreLocationIncomePDF.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreLocationIncomePDF.java
new file mode 100644
index 0000000..7e56462
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreLocationIncomePDF.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.store;
+
+import java.util.List;
+
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ZipcodeRecord;
+import 
org.apache.bigtop.datagenerators.samplers.pdfs.ProbabilityDensityFunction;
+
+public class StoreLocationIncomePDF implements 
ProbabilityDensityFunction<ZipcodeRecord>
+{
+       double incomeNormalizationFactor;
+       double minIncome;
+       double k;
+
+       public StoreLocationIncomePDF(List<ZipcodeRecord> zipcodeTable, double 
incomeScalingFactor)
+       {
+
+               double maxIncome = 0.0;
+               minIncome = Double.MAX_VALUE;
+
+               for(ZipcodeRecord record : zipcodeTable)
+               {
+                       maxIncome = Math.max(maxIncome, 
record.getMedianHouseholdIncome());
+                       minIncome = Math.min(minIncome, 
record.getMedianHouseholdIncome());
+               }
+
+               k = Math.log(incomeScalingFactor) / (maxIncome - minIncome);
+
+               incomeNormalizationFactor = 0.0d;
+               for(ZipcodeRecord record : zipcodeTable)
+               {
+                       double weight = incomeWeight(record);
+                       incomeNormalizationFactor += weight;
+               }
+       }
+
+       private double incomeWeight(ZipcodeRecord record)
+       {
+               return Math.exp(k * (record.getMedianHouseholdIncome() - 
minIncome));
+       }
+
+
+       @Override
+       public double probability(ZipcodeRecord datum)
+       {
+               double weight = incomeWeight(datum);
+
+               return weight / this.incomeNormalizationFactor;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreLocationPopulationPDF.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreLocationPopulationPDF.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreLocationPopulationPDF.java
new file mode 100644
index 0000000..2623bb5
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreLocationPopulationPDF.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.store;
+
+import java.util.List;
+
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ZipcodeRecord;
+import 
org.apache.bigtop.datagenerators.samplers.pdfs.ProbabilityDensityFunction;
+
+public class StoreLocationPopulationPDF implements 
ProbabilityDensityFunction<ZipcodeRecord>
+{
+       double populationSum = 0.0;
+
+       public StoreLocationPopulationPDF(List<ZipcodeRecord> zipcodeTable)
+       {
+               long populationSum = 0L;
+               for(ZipcodeRecord record : zipcodeTable)
+               {
+                       populationSum += record.getPopulation();
+               }
+
+               this.populationSum = ((double) populationSum);
+       }
+
+       public double probability(ZipcodeRecord record)
+       {
+               return ((double) record.getPopulation()) / populationSum;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreSampler.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreSampler.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreSampler.java
new file mode 100644
index 0000000..7b981c4
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreSampler.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.store;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Store;
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ZipcodeRecord;
+import org.apache.bigtop.datagenerators.samplers.samplers.Sampler;
+
+public class StoreSampler implements Sampler<Store>
+{
+
+       private final Sampler<ZipcodeRecord> locationSampler;
+       private final Sampler<Integer> idSampler;
+
+       public StoreSampler(Sampler<Integer> idSampler, Sampler<ZipcodeRecord> 
locationSampler)
+       {
+               this.locationSampler = locationSampler;
+               this.idSampler = idSampler;
+       }
+
+       public Store sample() throws Exception
+       {
+               Integer id = idSampler.sample();
+               String name = "Store_" + id;
+               ZipcodeRecord location = locationSampler.sample();
+
+               Store store = new Store(id, name, location);
+
+               return store;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreSamplerBuilder.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreSamplerBuilder.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreSamplerBuilder.java
new file mode 100644
index 0000000..74f6698
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/store/StoreSamplerBuilder.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.store;
+
+import java.util.List;
+
+import org.apache.bigtop.datagenerators.bigpetstore.Constants;
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Store;
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ZipcodeRecord;
+import org.apache.bigtop.datagenerators.samplers.SeedFactory;
+import org.apache.bigtop.datagenerators.samplers.pdfs.JointPDF;
+import 
org.apache.bigtop.datagenerators.samplers.pdfs.ProbabilityDensityFunction;
+import org.apache.bigtop.datagenerators.samplers.samplers.RouletteWheelSampler;
+import org.apache.bigtop.datagenerators.samplers.samplers.Sampler;
+import org.apache.bigtop.datagenerators.samplers.samplers.SequenceSampler;
+
+public class StoreSamplerBuilder
+{
+       private final List<ZipcodeRecord> zipcodeTable;
+       private final SeedFactory seedFactory;
+
+       public StoreSamplerBuilder(List<ZipcodeRecord> zipcodeTable, 
SeedFactory seedFactory)
+       {
+               this.zipcodeTable = zipcodeTable;
+               this.seedFactory = seedFactory;
+       }
+
+       public Sampler<Store> build()
+       {
+               Sampler<Integer> idSampler = new SequenceSampler();
+
+               ProbabilityDensityFunction<ZipcodeRecord> locationPopulationPDF 
=
+                               new StoreLocationPopulationPDF(zipcodeTable);
+               ProbabilityDensityFunction<ZipcodeRecord> locationIncomePDF =
+                               new StoreLocationIncomePDF(zipcodeTable, 
Constants.INCOME_SCALING_FACTOR);
+               ProbabilityDensityFunction<ZipcodeRecord> locationJointPDF =
+                               new JointPDF<ZipcodeRecord>(zipcodeTable, 
locationPopulationPDF, locationIncomePDF);
+
+               Sampler<ZipcodeRecord> locationSampler = 
RouletteWheelSampler.create(zipcodeTable, locationJointPDF, seedFactory);
+
+               return new StoreSampler(idSampler, locationSampler);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CategoryWeightFunction.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CategoryWeightFunction.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CategoryWeightFunction.java
new file mode 100644
index 0000000..c576812
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CategoryWeightFunction.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.transaction;
+
+import org.apache.bigtop.datagenerators.samplers.pdfs.ExponentialPDF;
+import 
org.apache.bigtop.datagenerators.samplers.pdfs.ProbabilityDensityFunction;
+import org.apache.bigtop.datagenerators.samplers.wfs.ConditionalWeightFunction;
+import org.apache.bigtop.datagenerators.samplers.wfs.WeightFunction;
+
+public class CategoryWeightFunction implements 
ConditionalWeightFunction<Double, Double>
+{
+       private final ProbabilityDensityFunction<Double> pdf;
+
+       public CategoryWeightFunction(double averagePurchaseTriggerTime)
+       {
+               double lambda = 1.0 / averagePurchaseTriggerTime;
+               pdf = new ExponentialPDF(lambda);
+       }
+
+       @Override
+       public double weight(Double exhaustionTime, Double transactionTime)
+       {
+               double remainingTime = Math.max(0.0, exhaustionTime - 
transactionTime);
+               return pdf.probability(remainingTime);
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerInventory.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerInventory.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerInventory.java
new file mode 100644
index 0000000..3798532
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerInventory.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.transaction;
+
+import java.util.Map;
+
+import org.apache.bigtop.datagenerators.bigpetstore.Constants;
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.Product;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+public class CustomerInventory
+{
+       final private ImmutableMap<String, ProductCategoryInventory> 
productCategoryInventories;
+
+       public CustomerInventory(Map<String, ProductCategoryInventory> 
productCategoryInventories)
+       {
+               this.productCategoryInventories = 
ImmutableMap.copyOf(productCategoryInventories);
+       }
+
+       public void simulatePurchase(double time, Product product) throws 
Exception
+       {
+               String category = 
product.getFieldValueAsString(Constants.PRODUCT_CATEGORY);
+               ProductCategoryInventory inventory = 
productCategoryInventories.get(category);
+               inventory.simulatePurchase(time, product);
+       }
+
+       public ImmutableMap<String, Double> getInventoryAmounts(double time)
+       {
+               Map<String, Double> amounts = Maps.newHashMap();
+               for(String category : productCategoryInventories.keySet())
+               {
+                       double amount = 
productCategoryInventories.get(category).findRemainingAmount(time);
+                       amounts.put(category, amount);
+               }
+
+               return ImmutableMap.copyOf(amounts);
+       }
+
+       public ImmutableMap<String, Double> getExhaustionTimes()
+       {
+               Map<String, Double> times = Maps.newHashMap();
+               for(String category : productCategoryInventories.keySet())
+               {
+                       double time = 
productCategoryInventories.get(category).findExhaustionTime();
+                       times.put(category, time);
+               }
+
+               return ImmutableMap.copyOf(times);
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerInventoryBuilder.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerInventoryBuilder.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerInventoryBuilder.java
new file mode 100644
index 0000000..f1793a4
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerInventoryBuilder.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.transaction;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import 
org.apache.bigtop.datagenerators.bigpetstore.datamodels.inputs.ProductCategory;
+import org.apache.bigtop.datagenerators.samplers.SeedFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class CustomerInventoryBuilder
+{
+       final private List<ProductCategory> productCategories;
+       final private SeedFactory seedFactory;
+       final private CustomerTransactionParameters parameters;
+
+       public CustomerInventoryBuilder(CustomerTransactionParameters 
parameters,
+                       SeedFactory seedFactory)
+       {
+               productCategories = Lists.newArrayList();
+               this.seedFactory = seedFactory;
+               this.parameters = parameters;
+       }
+
+       public void addProductCategory(ProductCategory productCategory)
+       {
+               this.productCategories.add(productCategory);
+       }
+
+       public void addAllProductCategories(Collection<ProductCategory> 
productCategories)
+       {
+               this.productCategories.addAll(productCategories);
+       }
+
+       public CustomerInventory build()
+       {
+               Map<String, ProductCategoryInventory> inventories = 
Maps.newHashMap();
+               for(ProductCategory productCategory : productCategories)
+               {
+                       
if(parameters.countPetsBySpecies(productCategory.getApplicableSpecies()) > 0)
+                       {
+                               ProductCategoryInventory inventory = new 
ProductCategoryInventory(productCategory,
+                                       parameters, seedFactory);
+                               
inventories.put(productCategory.getCategoryLabel(), inventory);
+                       }
+               }
+
+               return new CustomerInventory(inventories);
+       }
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerTransactionParameters.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerTransactionParameters.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerTransactionParameters.java
new file mode 100644
index 0000000..dbceb04
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerTransactionParameters.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.transaction;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.PetSpecies;
+
+import com.google.common.collect.ImmutableMultiset;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.Sets;
+
+public class CustomerTransactionParameters
+{
+       final ImmutableMultiset<PetSpecies> petCounts;
+       final double averageTransactionTriggerTime;
+       final double averagePurchaseTriggerTime;
+
+       public CustomerTransactionParameters(Multiset<PetSpecies> petCounts,
+                       double averageTransactionTriggerTime, double 
averagePurchaseTriggerTime)
+       {
+               this.petCounts = ImmutableMultiset.copyOf(petCounts);
+               this.averageTransactionTriggerTime = 
averageTransactionTriggerTime;
+               this.averagePurchaseTriggerTime = averagePurchaseTriggerTime;
+       }
+
+       public double getAverageTransactionTriggerTime()
+       {
+               return averageTransactionTriggerTime;
+       }
+
+       public double getAveragePurchaseTriggerTime()
+       {
+               return averagePurchaseTriggerTime;
+       }
+
+       public int countPetsBySpecies(PetSpecies species)
+       {
+               return petCounts.count(species);
+       }
+
+       public int countPetsBySpecies(Collection<PetSpecies> allSpecies)
+       {
+               int count = 0;
+               Set<PetSpecies> speciesSet = Sets.newHashSet(allSpecies);
+               for(PetSpecies species : speciesSet)
+               {
+                       count += countPetsBySpecies(species);
+               }
+
+               return count;
+       }
+
+       public int countPets()
+       {
+               return petCounts.size();
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/bigtop/blob/15af83eb/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerTransactionParametersBuilder.java
----------------------------------------------------------------------
diff --git 
a/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerTransactionParametersBuilder.java
 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerTransactionParametersBuilder.java
new file mode 100644
index 0000000..97a73e7
--- /dev/null
+++ 
b/bigtop-data-generators/bigpetstore-data-generator/src/main/java/org/apache/bigtop/datagenerators/bigpetstore/generators/transaction/CustomerTransactionParametersBuilder.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bigtop.datagenerators.bigpetstore.generators.transaction;
+
+import org.apache.bigtop.datagenerators.bigpetstore.datamodels.PetSpecies;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+
+public class CustomerTransactionParametersBuilder
+{
+       private Multiset<PetSpecies> petCounts;
+       private double averageTransactionTriggerTime;
+       private double averagePurchaseTriggerTime;
+
+       public CustomerTransactionParametersBuilder()
+       {
+               this.petCounts = HashMultiset.create();
+               this.averagePurchaseTriggerTime = 0.0;
+               this.averageTransactionTriggerTime = 0.0;
+       }
+
+       public void addPet(PetSpecies species)
+       {
+               this.petCounts.add(species);
+       }
+
+       public void setAverageTransactionTriggerTime(
+                       double averageTransactionTriggerTime)
+       {
+               this.averageTransactionTriggerTime = 
averageTransactionTriggerTime;
+       }
+
+       public void setAveragePurchaseTriggerTime(double 
averagePurchaseTriggerTime)
+       {
+               this.averagePurchaseTriggerTime = averagePurchaseTriggerTime;
+       }
+
+       public CustomerTransactionParameters build()
+       {
+               return new CustomerTransactionParameters(this.petCounts,
+                               this.averageTransactionTriggerTime,
+                               this.averagePurchaseTriggerTime);
+       }
+}

Reply via email to