Index: bidspace/src/test/java/geniusweb/bidspace/BidsWithUtilityTest.java
===================================================================
--- bidspace/src/test/java/geniusweb/bidspace/BidsWithUtilityTest.java	(revision 2)
+++ bidspace/src/test/java/geniusweb/bidspace/BidsWithUtilityTest.java	(revision 4)
@@ -1,99 +1,112 @@
 package geniusweb.bidspace;
 
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.math.RoundingMode;
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Map;
+import java.util.Random;
 
-import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import geniusweb.issuevalue.Bid;
-import geniusweb.issuevalue.DiscreteValue;
-import geniusweb.issuevalue.DiscreteValueSet;
-import geniusweb.issuevalue.Domain;
-import geniusweb.issuevalue.NumberValue;
-import geniusweb.issuevalue.NumberValueSet;
-import geniusweb.issuevalue.ValueSet;
 import geniusweb.profile.Profile;
 import geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace;
+import tudelft.utilities.immutablelist.ImmutableList;
 
+@RunWith(Parameterized.class)
 public class BidsWithUtilityTest {
-	private static final DiscreteValue I1V2 = new DiscreteValue("i1v2");
-	private static final DiscreteValue I1V1 = new DiscreteValue("i1v1");
-	private static final NumberValue I2V1 = new NumberValue("2.00");
-	private static final NumberValue I2V2 = new NumberValue("2.45");
-	private static final NumberValue I2V3 = new NumberValue("2.90");
-	private static final String DOMAINNAME = "testdomain";
-	private static final String ISSUE1 = "issue1";
-	private static final String ISSUE2 = "issue2";
-	private static final Map<String, ValueSet> issues = new HashMap<>();
+	private final static ObjectMapper jackson = new ObjectMapper();
+	private final Interval utilityGoal = new Interval(new BigDecimal("0.50"),
+			new BigDecimal("0.51"));
+	private LinearAdditiveUtilitySpace profile;
+	private long expectedSize;
+	private int accuracy = 5;
 
-	private static ValueSet values1;
-	private static ValueSet values2;
-	private static final BigDecimal TWO = new BigDecimal("2");
-	private static final BigDecimal THREE = new BigDecimal("3");
-	private final static BigDecimal ZERO_1 = new BigDecimal("0.1"), ZERO_2 = new BigDecimal("0.2"),
-			ZERO_3 = new BigDecimal("0.3");
+	@Parameters
+	public static Collection<Object[]> data() {
+		return Arrays.asList(new Object[][] {
+				{ "src/test/resources/jobs/jobs1.json", 11 },
+				{ "src/test/resources/7issues/7issues1.json", 260000 },
+				{ "src/test/resources/9issues/9issues1.json", 25000000 } });
+	}
 
-	private static Domain domain;
-	private final static ObjectMapper jackson = new ObjectMapper();
+	public BidsWithUtilityTest(String filename, long expectedsize)
+			throws IOException {
+		String file = new String(Files.readAllBytes(Paths.get(filename)));
+		profile = (LinearAdditiveUtilitySpace) jackson.readValue(file,
+				Profile.class);
+		this.expectedSize = expectedsize;
+	}
 
-	@Before
-	public void before() {
-		Collection<DiscreteValue> discretevalues1 = new LinkedList<>();
-		discretevalues1.add(I1V1);
-		discretevalues1.add(I1V2);
-		values1 = new DiscreteValueSet(discretevalues1);
-		issues.put(ISSUE1, values1);
-
-		values2 = new NumberValueSet(TWO, THREE, new BigDecimal("0.45"));
-		issues.put(ISSUE2, values2);
-
-		domain = new Domain(DOMAINNAME, issues);
+	/**
+	 * Test if the values are within acceptable range from the goal.
+	 */
+	@Test
+	public void test() {
+		ImmutableList<Bid> list = new BidsWithUtility(profile, accuracy)
+				.getBids(utilityGoal);
+		Random rand = new Random();
+		// check not all but only 10000 random bids as list may be way too large
+		// to test them all. Testing 1 billion bids may take 15 minutes or so on
+		// quad core i7 @2.4GHz.....
+		// also notice that we may be checking only part of the list if
+		// the size of the list would become bigger than maxint.
+		for (int n = 0; n < 10000; n++) {
+			Bid bid = list.get(rand.nextInt(list.size().intValue()));
+			assertTrue(utilityGoal.contains(profile.getUtility(bid)
+					.setScale(accuracy - 1, RoundingMode.HALF_UP)));
+		}
+		assertTrue(
+				list.size().compareTo(BigInteger.valueOf(expectedSize)) >= 0);
 
 	}
 
 	@Test
-	public void smokeTest() {
-		LinearAdditiveUtilitySpace space = mock(LinearAdditiveUtilitySpace.class);
-		when(space.getDomain()).thenReturn(domain);
-		when(space.getUtility(any(Bid.class))).thenReturn(ZERO_2);
-		new BidsWithUtility(space, new BigDecimal("0.1"), new BigDecimal("0.3"));
+	public void testMaxUtil() {
+		BidsWithUtility bidswithutil = new BidsWithUtility(profile);
+		// notice, this is the *rounded* max util
+		BigDecimal maxutil = bidswithutil.getRange().getMax();
+		Interval goal = new Interval(
+				maxutil.subtract(new BigDecimal("0.00001")), maxutil);
+
+		ImmutableList<Bid> bidsnearmax = bidswithutil.getBids(goal);
+		assertTrue(bidsnearmax.size() != BigInteger.ZERO);
+
+		BigDecimal foundmax = BigDecimal.ZERO;
+		for (Bid bid : bidsnearmax) {
+			BigDecimal util = profile.getUtility(bid);
+			if (util.compareTo(foundmax) > 0) {
+				foundmax = util;
+			}
+		}
+		// found maximum may be slightly lower or higher because we rounded
+		// all weighted utilities.
+		assertTrue(Math
+				.abs(foundmax.doubleValue() - maxutil.doubleValue()) < 0.0001);
 	}
 
 	@Test
-	public void testSelection() {
-		LinearAdditiveUtilitySpace space = mock(LinearAdditiveUtilitySpace.class);
+	public void benchmark() {
+		System.out.println("\nBenchmarking " + profile.getName());
+		BigInteger domainsize = new AllBidsList(profile.getDomain()).size();
 
-		when(space.getDomain()).thenReturn(domain);
-		when(space.getUtility(any(Bid.class))).thenReturn(ZERO_2);
-		BidsWithUtility selected = new BidsWithUtility(space, new BigDecimal("0.1"), new BigDecimal("0.3"));
-		assertEquals(new BigInteger("6"), selected.size());
-	}
-
-	@Test
-	public void testRealSpace() throws IOException {
-		String file1 = new String(Files.readAllBytes(Paths.get("src/test/resources/jobs/jobs1.json")));
-		LinearAdditiveUtilitySpace profile = (LinearAdditiveUtilitySpace) jackson.readValue(file1, Profile.class);
-		BidsWithUtility selected = new BidsWithUtility(profile, ZERO_1, ZERO_3);
-
-		assertEquals(new BigInteger("56"), selected.size());
-		for (Bid bid : selected) {
-			assertEquals(1, profile.getUtility(bid).compareTo(ZERO_1));
-			assertEquals(-1, profile.getUtility(bid).compareTo(ZERO_3));
-		}
+		long start = System.currentTimeMillis();
+		BidsWithUtility body = new BidsWithUtility(profile, accuracy);
+		ImmutableList<Bid> list = body.getBids(utilityGoal);
+		long end = System.currentTimeMillis();
+		System.out.println("run time: " + (end - start) / 1000. + "s");
+		System.out.println("Total size of bidspace:" + domainsize);
+		System.out.println("Result size: " + list.size());
 	}
 
Index: bidspace/src/test/java/geniusweb/bidspace/IntervalTest.java
===================================================================
--- bidspace/src/test/java/geniusweb/bidspace/IntervalTest.java	(revision 4)
+++ bidspace/src/test/java/geniusweb/bidspace/IntervalTest.java	(revision 4)
@@ -0,0 +1,118 @@
+package geniusweb.bidspace;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import tudelft.utilities.junit.GeneralTests;
+
+public class IntervalTest extends GeneralTests<Interval> {
+
+	private static final BigDecimal ZERO = BigDecimal.ZERO;
+	private static final BigDecimal ONE = BigDecimal.ONE;
+	private static final BigDecimal TWO = BigDecimal.valueOf(2);
+	private static final BigDecimal THREE = BigDecimal.valueOf(3);
+	private static final BigDecimal TEN = BigDecimal.TEN;
+	private static final Interval int1 = new Interval(ZERO, ONE);
+	private static final Interval int1a = new Interval(ZERO, ONE);
+	private static final Interval int2 = new Interval(ONE, TEN);
+	private static final Interval int3 = new Interval(TWO, TEN);
+
+	@Override
+	public List<List<Interval>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(int1, int1a), Arrays.asList(int2),
+				Arrays.asList(int3));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("Interval\\[0,1\\]", "Interval\\[1,10\\]",
+				"Interval\\[2,10\\]");
+	}
+
+	@Test
+	public void smokeTest() {
+		new Interval(BigDecimal.ZERO, BigDecimal.ONE);
+	}
+
+	@Test
+	public void smokeTestBad() {
+		Interval i = new Interval(BigDecimal.TEN, BigDecimal.ONE);
+		assertTrue(i.isEmpty());
+	}
+
+	@Test(expected = NullPointerException.class)
+	public void smokeNull1() {
+		new Interval(null, BigDecimal.ZERO);
+	}
+
+	@Test(expected = NullPointerException.class)
+	public void smokeNull2() {
+		new Interval(BigDecimal.ZERO, null);
+	}
+
+	@Test
+	public void testMin() {
+		assertEquals(BigDecimal.ZERO, int1.getMin());
+		assertEquals(BigDecimal.ONE, int2.getMin());
+	}
+
+	@Test
+	public void testMax() {
+		assertEquals(BigDecimal.ONE, int1.getMax());
+		assertEquals(BigDecimal.TEN, int2.getMax());
+	}
+
+	@Test
+	public void containsTest() {
+		assertTrue(int1.contains(BigDecimal.valueOf(0.3)));
+		assertFalse(int1.contains(BigDecimal.valueOf(-0.3)));
+		assertFalse(int1.contains(BigDecimal.valueOf(1.3)));
+
+		assertFalse(int3.contains(ZERO));
+		assertFalse(int3.contains(ONE));
+		assertTrue(int3.contains(TWO));
+		assertTrue(int3.contains(THREE));
+		assertTrue(int3.contains(TEN));
+		assertFalse(int3.contains(BigDecimal.valueOf(10.3)));
+
+	}
+
+	@Test
+	public void testIntersect() {
+		assertEquals(int1, int1.intersect(int1));
+		assertEquals(new Interval(ONE, ONE), int1.intersect(int2));
+		assertTrue(int1.intersect(int3).isEmpty());
+		assertEquals(new Interval(ONE, TWO),
+				new Interval(ZERO, TEN).intersect(new Interval(ONE, TWO)));
+		assertEquals(new Interval(ONE, TWO),
+				new Interval(ONE, TWO).intersect(new Interval(ZERO, TEN)));
+		assertEquals(new Interval(ONE, TWO),
+				new Interval(ZERO, TWO).intersect(new Interval(ONE, TEN)));
+		assertEquals(new Interval(ONE, TWO),
+				new Interval(ONE, TEN).intersect(new Interval(ZERO, TWO)));
+	}
+
+	@Test
+	public void subtractTest() {
+		assertEquals(new Interval(BigDecimal.valueOf(-1), ZERO),
+				int1.subtract(ONE));
+	}
+
+	@Test
+	public void invertTest() {
+		assertEquals(new Interval(BigDecimal.valueOf(-10), ZERO),
+				int1.invert(int2));
+		assertEquals(new Interval(ZERO, TEN), int2.invert(int1));
+		assertEquals(
+				new Interval(BigDecimal.valueOf(-9), BigDecimal.valueOf(8)),
+				int2.invert(int3));
+	}
+
+}
Index: bidspace/src/test/resources/9issues/9issues1.json
===================================================================
--- bidspace/src/test/resources/9issues/9issues1.json	(revision 4)
+++ bidspace/src/test/resources/9issues/9issues1.json	(revision 4)
@@ -0,0 +1,134 @@
+{
+	"LinearAdditiveUtilitySpace": {
+		"name": "9issues1",
+		"issueUtilities": {
+			"i1": {
+				"numberutils": {
+					"lowValue": 0,
+					"lowUtility": 0.11,
+					"highValue": 9,
+					"highUtility": 0.99
+
+				}
+			},
+			"i2": {
+				"numberutils": {
+					"lowValue": 0,
+					"lowUtility": 0.12,
+					"highValue": 9,
+					"highUtility": 0.97
+
+				}
+			},
+			"i3": {
+				"numberutils": {
+					"lowValue": 0,
+					"lowUtility": 0.13,
+					"highValue": 9,
+					"highUtility": 0.96
+
+				}
+			},
+			"i4": {
+				"numberutils": {
+					"lowValue": 0,
+					"lowUtility": 0.14,
+					"highValue": 9,
+					"highUtility": 0.94
+
+				}
+			},
+			"i5": {
+				"numberutils": {
+					"lowValue": 0,
+					"lowUtility": 0.15,
+					"highValue": 9,
+					"highUtility": 0.93
+
+				}
+			},
+			"i6": {
+				"numberutils": {
+					"lowValue": 0,
+					"lowUtility": 0.16,
+					"highValue": 9,
+					"highUtility": 0.92
+
+				}
+			},
+			"i7": {
+				"numberutils": {
+					"lowValue": 0,
+					"lowUtility": 0.16,
+					"highValue": 9,
+					"highUtility": 0.91
+
+				}
+			},
+			"i8": {
+				"numberutils": {
+					"lowValue": 0,
+					"lowUtility": 0.7664,
+					"highValue": 9,
+					"highUtility": 0.183
+
+				}
+			},
+
+			"i9": {
+				"numberutils": {
+					"lowValue": 0,
+					"lowUtility": 0.191,
+					"highValue": 9,
+					"highUtility": 0.891
+
+				}
+			}
+
+		},
+		"issueWeights": {
+			"i1": 0.07531677352656704,
+			"i2": 0.18148468268008364,
+			"i3": 0.12035193969082373,
+			"i4": 0.21649985443378972,
+			"i5": 0.15621694966873587,
+			"i6": 0.111253,
+			"i7": 0.0656768,
+			"i8": 0.0201,
+			"i9": 0.0531
+		},
+		"domain": {
+			"name": "9issues",
+			"issuesValues": {
+				"i1": {
+					"range": ["0", "9", "1"]
+				},
+				"i2": {
+					"range": ["0", "9", "1"]
+				},
+				"i3": {
+					"range": ["0", "9", "1"]
+				},
+				"i4": {
+					"range": ["0", "9", "1"]
+				},
+				"i5": {
+					"range": ["0", "9", "1"]
+				},
+				"i6": {
+					"range": ["0", "9", "1"]
+				},
+				"i7": {
+					"range": ["0", "9", "1"]
+				},
+				"i8": {
+					"range": ["0", "9", "1"]
+				},
+				"i9": {
+					"range": ["0", "9", "1"]
+				}
+
+			}
+		}
+	}
+}
