Index: bidspace/src/test/java/geniusweb/bidspace/SumOfGroupsLinAdditiveAdapterTest.java
===================================================================
--- bidspace/src/test/java/geniusweb/bidspace/SumOfGroupsLinAdditiveAdapterTest.java	(revision 53)
+++ bidspace/src/test/java/geniusweb/bidspace/SumOfGroupsLinAdditiveAdapterTest.java	(revision 53)
@@ -0,0 +1,93 @@
+package geniusweb.bidspace;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Random;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.Value;
+import geniusweb.profile.utilityspace.ProductOfValue;
+import geniusweb.profile.utilityspace.SumOfGroupsUtilitySpace;
+
+public class SumOfGroupsLinAdditiveAdapterTest {
+	private final ObjectMapper jackson = new ObjectMapper();
+	private final Random random = new Random();
+	private final SumOfGroupsLinAdditiveAdapter adapter;
+	private final SumOfGroupsUtilitySpace groupspace;
+
+	public SumOfGroupsLinAdditiveAdapterTest()
+			throws JsonParseException, JsonMappingException, IOException {
+		groupspace = jackson.readValue(
+				getClass().getResourceAsStream("/computer/computerbuy.json"),
+				SumOfGroupsUtilitySpace.class);
+		adapter = SumOfGroupsLinAdditiveAdapter.create(groupspace);
+
+	}
+
+	@Test
+	public void smokeTest() {
+		System.out.println("" + adapter);
+	}
+
+	@Test
+	public void checkUtility() throws IOException {
+		AllBidsList bidspace = new AllBidsList(groupspace.getDomain());
+		int NISS = adapter.getDomain().getIssues().size() - 1;
+
+		// compare utility of many random bids
+		for (int n = 0; n < 100; n += 1) {
+			// space is small, do this simple
+
+			int i = random.nextInt(bidspace.size().intValue());
+			// this is bid in the group space.
+			Bid groupbid = bidspace.get(BigInteger.valueOf(i));
+
+			Bid linbid = adapter.toLinearBid(groupbid, groupspace);
+
+			assertEquals(groupspace.getUtility(groupbid).floatValue(),
+					NISS * adapter.getUtility(linbid).floatValue(), 0.000001);
+
+			assertEquals(groupbid, adapter.toGroupBid(linbid));
+		}
+	}
+
+	@Test
+	public void checkReservationBid() {
+		assertEquals(groupspace.getReservationBid(),
+				adapter.toGroupBid(adapter.getReservationBid()));
+	}
+
+	@Test
+	public void testGroupValueSet() {
+		final Value val1 = new DiscreteValue("val1");
+		final ProductOfValue pov = new ProductOfValue(Arrays.asList(val1));
+		final Collection<ProductOfValue> issuevalues = Arrays.asList(pov);
+		final GroupValueSet gvs = new GroupValueSet(issuevalues);
+		final GroupValueSet gvs1 = new GroupValueSet(issuevalues);
+
+		assertEquals(issuevalues, gvs.getValues());
+		assertEquals(BigInteger.ONE, gvs.size());
+		assertEquals(pov, gvs.get(BigInteger.ZERO));
+		assertEquals(pov, gvs.get(0));
+		assertEquals(pov, gvs.iterator().next());
+		assertEquals("[" + pov + "]", gvs.toString());
+
+		// poor man's GenericTests, we can't do GenericTests because that's on a
+		// class level
+		// and we can't make a class level test here.
+		assertEquals(gvs, gvs);
+		assertEquals(gvs1, gvs);
+		assertEquals(gvs.hashCode(), gvs1.hashCode());
+	}
+}
Index: bidspace/src/test/java/geniusweb/bidspace/pareto/ParetoRandomTest.java
===================================================================
--- bidspace/src/test/java/geniusweb/bidspace/pareto/ParetoRandomTest.java	(revision 53)
+++ bidspace/src/test/java/geniusweb/bidspace/pareto/ParetoRandomTest.java	(revision 53)
@@ -0,0 +1,136 @@
+package geniusweb.bidspace.pareto;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
+import org.junit.Test;
+
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.DiscreteValueSet;
+import geniusweb.issuevalue.Domain;
+import geniusweb.issuevalue.ValueSet;
+import geniusweb.profile.utilityspace.DiscreteValueSetUtilities;
+import geniusweb.profile.utilityspace.LinearAdditive;
+import geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace;
+import geniusweb.profile.utilityspace.ValueSetUtilities;
+
+/**
+ * Test pareto on random space.
+ */
+public class ParetoRandomTest {
+
+	private final int DIMENSION = 2; // #participants. 2 is normal bilateral
+										// space
+	private final int NISSUES = 3; // number of issues
+	private final int NVALS = 10; // number values per issue
+	private final int NRUNS = 50; // number of runs (to average result)
+
+	@Test
+	public void checkGenerciPareto() throws IOException {
+
+		DescriptiveStatistics time = new DescriptiveStatistics();
+		DescriptiveStatistics paretopoints = new DescriptiveStatistics();
+
+		for (int run = 0; run < NRUNS; run++) {
+			System.gc(); // free memory before each test run
+			System.out.print(".");
+			long startTime = System.nanoTime();
+			ParetoLinearAdditive pareto = runOneTest();
+			paretopoints.addValue(pareto.getPoints().size());
+
+			double dt = (System.nanoTime() - startTime) / 1000000000d;
+
+			time.addValue(dt);
+		}
+		System.out.println();
+		System.out.println("Results averaged over " + NRUNS + " runs");
+		System.out.println("DIMENSION=" + DIMENSION);
+		System.out.println("NISSUES=" + NISSUES);
+		System.out.println("NVALS=" + NVALS);
+		System.out.println("bidspace=" + Math.pow(NVALS, NISSUES));
+		System.out.println("runtime: " + time.getMean() + "s, stdev="
+				+ time.getStandardDeviation());
+		System.out.println("points on pareto: " + paretopoints.getMean()
+				+ ", stdev=" + paretopoints.getStandardDeviation());
+		System.out.println("{" + DIMENSION + "," + NISSUES + "," + NVALS + ","
+				+ time.getMean() + "," + time.getStandardDeviation() + ","
+				+ paretopoints.getMean() + ","
+				+ paretopoints.getStandardDeviation() + "}");
+	}
+
+	private ParetoLinearAdditive runOneTest() {
+		Domain domain = getRandomDomain();
+
+		List<LinearAdditive> profiles = new LinkedList<>();
+		for (int n = 0; n < DIMENSION; n++) {
+			LinearAdditiveUtilitySpace rspace = getRandomSpace(domain);
+			profiles.add(rspace);
+		}
+		return new ParetoLinearAdditive(profiles);
+
+	}
+
+	private Domain getRandomDomain() {
+		Map<String, ValueSet> issues = new HashMap<>();
+		List<BigDecimal> w = getRandomWeights();
+		for (int iss = 0; iss < NISSUES; iss++) {
+			Collection<DiscreteValue> values = new LinkedList<>();
+			for (int val = 0; val < NVALS; val++) {
+				DiscreteValue v = new DiscreteValue("iss" + iss + "val" + val);
+				values.add(v);
+			}
+			String issuename = "issue" + iss;
+			issues.put(issuename, new DiscreteValueSet(values));
+
+		}
+		return new Domain("dom", issues);
+	}
+
+	/**
+	 * 
+	 * @param domain some domain with discrete issue values
+	 * @return random LA utilspace for this domain
+	 */
+	private LinearAdditiveUtilitySpace getRandomSpace(Domain domain) {
+		List<String> issuelist = new LinkedList(domain.getIssues());
+		Map<String, ValueSetUtilities> utils = new HashMap<>();
+		Map<String, BigDecimal> weights = new HashMap<>();
+		List<BigDecimal> w = getRandomWeights();
+		for (int iss = 0; iss < NISSUES; iss++) {
+			String issuename = issuelist.get(iss);
+			Map<DiscreteValue, BigDecimal> utilsmap = new HashMap<>();
+			for (int val = 0; val < NVALS; val++) {
+				DiscreteValue v = (DiscreteValue) domain.getValues(issuename)
+						.get(val);
+				utilsmap.put(v, BigDecimal.valueOf(Math.random()));
+			}
+			weights.put(issuename, w.get(iss));
+			utils.put(issuename, new DiscreteValueSetUtilities(utilsmap));
+		}
+		return new LinearAdditiveUtilitySpace(domain, "name", utils, weights,
+				null);
+	}
+
+	/**
+	 * 
+	 * @return list of NISSUES BigDecimals, summing to 1
+	 */
+	private List<BigDecimal> getRandomWeights() {
+		List<BigDecimal> doubles = new LinkedList<>();
+		BigDecimal remainder = BigDecimal.ONE;
+		for (int n = 0; n < NISSUES - 1; n++) {
+			BigDecimal next = BigDecimal.valueOf(Math.random() / NISSUES);
+			doubles.add(next);
+			remainder = remainder.subtract(next);
+		}
+		doubles.add(remainder);
+		return doubles;
+	}
+
+}
Index: bidspace/src/test/resources/computer/computerbuy.json
===================================================================
--- bidspace/src/test/resources/computer/computerbuy.json	(revision 53)
+++ bidspace/src/test/resources/computer/computerbuy.json	(revision 53)
@@ -0,0 +1,618 @@
+{
+	"SumOfGroupsUtilitySpace": {
+		"domain": {
+			"name": "computer",
+			"issuesValues": {
+				"box": {
+					"values": [
+						"all-in-one",
+						"small box",
+						"tower"
+					]
+				},
+				"graphics": {
+					"values": [
+						"built-in",
+						"low 8G",
+						"medium 16G",
+						"high 32G"
+					]
+				},
+				"main mem": {
+					"values": [
+						"8GB",
+						"16GB",
+						"32GB",
+						"64GB"
+					]
+				},
+				"SSD": {
+					"values": [
+						"64GB",
+						"1TB",
+						"2TB",
+						"4TB",
+						"8TB"
+					]
+				},
+				"display": {
+					"values": [
+						"24-1K",
+						"27-4K",
+						"32-4K",
+						"27-4K gaming",
+						"34-4K gaming"
+					]
+				},
+				"input": {
+					"values": [
+						"standard keybd,mouse",
+						"wireless keybd,mouse",
+						"gaming keybd,mouse"
+					]
+				},
+				"price": {
+					"values": [
+						"614",
+						"663",
+						"716",
+						"773",
+						"835",
+						"902",
+						"974",
+						"1052",
+						"1136",
+						"1227",
+						"1326",
+						"1432",
+						"1546",
+						"1670",
+						"1803",
+						"1948",
+						"2104",
+						"2272",
+						"2454",
+						"2650",
+						"2862",
+						"3091",
+						"3338",
+						"3605",
+						"3893",
+						"4205",
+						"4541",
+						"4905",
+						"5297"
+					]
+				},
+				"rounding": {
+					"values": [
+						"1"
+					]
+				}
+			}
+		},
+		"name": "computerbuy",
+		"partUtilities": {
+			"boxandgraphics": {
+				"PartsUtilities": {
+					"issues": [
+						"box",
+						"graphics"
+					],
+					"utilslist": [
+						{
+							"values": [
+								"all-in-one",
+								"built-in"
+							],
+							"util": 0.09
+						},
+						{
+							"values": [
+								"all-in-one",
+								"low 8G"
+							],
+							"util": 0
+						},
+						{
+							"values": [
+								"all-in-one",
+								"medium 16G"
+							],
+							"util": 0
+						},
+						{
+							"values": [
+								"all-in-one",
+								"high 32G"
+							],
+							"util": 0
+						},
+						{
+							"values": [
+								"small box",
+								"built-in"
+							],
+							"util": 0.12
+						},
+						{
+							"values": [
+								"small box",
+								"low 8G"
+							],
+							"util": 0.15
+						},
+						{
+							"values": [
+								"small box",
+								"medium 16G"
+							],
+							"util": 0.003
+						},
+						{
+							"values": [
+								"small box",
+								"high 32G"
+							],
+							"util": 0.003
+						},
+						{
+							"values": [
+								"tower",
+								"built-in"
+							],
+							"util": 0.09
+						},
+						{
+							"values": [
+								"tower",
+								"low 8G"
+							],
+							"util": 0.18
+						},
+						{
+							"values": [
+								"tower",
+								"medium 16G"
+							],
+							"util": 0.24
+						},
+						{
+							"values": [
+								"tower",
+								"high 32G"
+							],
+							"util": 0.003
+						}
+					]
+				}
+			},
+			"display": {
+				"PartsUtilities": {
+					"issues": [
+						"display"
+					],
+					"utilslist": [
+						{
+							"values": [
+								"24-1K"
+							],
+							"util": 0.08
+						},
+						{
+							"values": [
+								"27-4K"
+							],
+							"util": 0.12
+						},
+						{
+							"values": [
+								"32-4K"
+							],
+							"util": 0.18
+						},
+						{
+							"values": [
+								"27-4K gaming"
+							],
+							"util": 0.18
+						},
+						{
+							"values": [
+								"34-4K gaming"
+							],
+							"util": 0.2
+						}
+					]
+				}
+			},
+			"input": {
+				"PartsUtilities": {
+					"issues": [
+						"input"
+					],
+					"utilslist": [
+						{
+							"values": [
+								"standard keybd,mouse"
+							],
+							"util": 0.04
+						},
+						{
+							"values": [
+								"wireless keybd,mouse"
+							],
+							"util": 0.06
+						},
+						{
+							"values": [
+								"gaming keybd,mouse"
+							],
+							"util": 0.09
+						}
+					]
+				}
+			},
+			"rounding": {
+				"PartsUtilities": {
+					"issues": [
+						"rounding"
+					],
+					"utilslist": [
+						{
+							"values": [
+								"1"
+							],
+							"util": 0.0
+						}
+					]
+				}
+			},
+			"memory": {
+				"PartsUtilities": {
+					"issues": [
+						"main mem",
+						"SSD"
+					],
+					"utilslist": [
+						{
+							"values": [
+								"8GB",
+								"64GB"
+							],
+							"util": 0.005
+						},
+						{
+							"values": [
+								"16GB",
+								"64GB"
+							],
+							"util": 0.01
+						},
+						{
+							"values": [
+								"32GB",
+								"64GB"
+							],
+							"util": 0.01
+						},
+						{
+							"values": [
+								"64GB",
+								"64GB"
+							],
+							"util": 0.01
+						},
+						{
+							"values": [
+								"8GB",
+								"1TB"
+							],
+							"util": 0.015
+						},
+						{
+							"values": [
+								"16GB",
+								"1TB"
+							],
+							"util": 0.02
+						},
+						{
+							"values": [
+								"32GB",
+								"1TB"
+							],
+							"util": 0.02
+						},
+						{
+							"values": [
+								"64GB",
+								"1TB"
+							],
+							"util": 0.02
+						},
+						{
+							"values": [
+								"8GB",
+								"2TB"
+							],
+							"util": 0.03
+						},
+						{
+							"values": [
+								"16GB",
+								"2TB"
+							],
+							"util": 0.04
+						},
+						{
+							"values": [
+								"32GB",
+								"2TB"
+							],
+							"util": 0.04
+						},
+						{
+							"values": [
+								"64GB",
+								"2TB"
+							],
+							"util": 0.04
+						},
+						{
+							"values": [
+								"8GB",
+								"4TB"
+							],
+							"util": 0.04
+						},
+						{
+							"values": [
+								"16GB",
+								"4TB"
+							],
+							"util": 0.05
+						},
+						{
+							"values": [
+								"32GB",
+								"4TB"
+							],
+							"util": 0.07
+						},
+						{
+							"values": [
+								"64GB",
+								"4TB"
+							],
+							"util": 0.09
+						},
+						{
+							"values": [
+								"8GB",
+								"8TB"
+							],
+							"util": 0.06
+						},
+						{
+							"values": [
+								"16GB",
+								"8TB"
+							],
+							"util": 0.07
+						},
+						{
+							"values": [
+								"32GB",
+								"8TB"
+							],
+							"util": 0.08
+						},
+						{
+							"values": [
+								"64GB",
+								"8TB"
+							],
+							"util": 0.10
+						}
+					]
+				}
+			},
+			"price": {
+				"PartsUtilities": {
+					"issues": [
+						"price"
+					],
+					"utilslist": [
+						{
+							"values": [
+								"614"
+							],
+							"util": 0.3
+						},
+						{
+							"values": [
+								"663"
+							],
+							"util": 0.29
+						},
+						{
+							"values": [
+								"716"
+							],
+							"util": 0.28
+						},
+						{
+							"values": [
+								"773"
+							],
+							"util": 0.27
+						},
+						{
+							"values": [
+								"835"
+							],
+							"util": 0.26
+						},
+						{
+							"values": [
+								"902"
+							],
+							"util": 0.25
+						},
+						{
+							"values": [
+								"974"
+							],
+							"util": 0.24
+						},
+						{
+							"values": [
+								"1052"
+							],
+							"util": 0.23
+						},
+						{
+							"values": [
+								"1136"
+							],
+							"util": 0.22
+						},
+						{
+							"values": [
+								"1227"
+							],
+							"util": 0.21
+						},
+						{
+							"values": [
+								"1326"
+							],
+							"util": 0.2
+						},
+						{
+							"values": [
+								"1432"
+							],
+							"util": 0.19
+						},
+						{
+							"values": [
+								"1546"
+							],
+							"util": 0.18
+						},
+						{
+							"values": [
+								"1670"
+							],
+							"util": 0.17
+						},
+						{
+							"values": [
+								"1803"
+							],
+							"util": 0.16
+						},
+						{
+							"values": [
+								"1948"
+							],
+							"util": 0.15
+						},
+						{
+							"values": [
+								"2104"
+							],
+							"util": 0.14
+						},
+						{
+							"values": [
+								"2272"
+							],
+							"util": 0.13
+						},
+						{
+							"values": [
+								"2454"
+							],
+							"util": 0.12
+						},
+						{
+							"values": [
+								"2650"
+							],
+							"util": 0.11
+						},
+						{
+							"values": [
+								"2862"
+							],
+							"util": 0.1
+						},
+						{
+							"values": [
+								"3091"
+							],
+							"util": 0.09
+						},
+						{
+							"values": [
+								"3338"
+							],
+							"util": 0.08
+						},
+						{
+							"values": [
+								"3605"
+							],
+							"util": 0.07
+						},
+						{
+							"values": [
+								"3893"
+							],
+							"util": 0.06
+						},
+						{
+							"values": [
+								"4205"
+							],
+							"util": 0.05
+						},
+						{
+							"values": [
+								"4541"
+							],
+							"util": 0.04
+						},
+						{
+							"values": [
+								"4905"
+							],
+							"util": 0.03
+						},
+						{
+							"values": [
+								"5297"
+							],
+							"util": 0.02
+						}
+					]
+				}
+			}
+		},
+		"reservationBid": {
+			"issuevalues": {
+				"box": "small box",
+				"graphics": "low 8G",
+				"main mem": "8GB",
+				"SSD": "1TB",
+				"display": "32-4K",
+				"input": "gaming keybd,mouse",
+				"price": "1432",
+				"rounding":"1"
+			}
+		}
+	}
+}
