Index: bidspace/src/main/java/geniusweb/bidspace/BidsWithUtility.java
===================================================================
--- bidspace/src/main/java/geniusweb/bidspace/BidsWithUtility.java	(revision 52)
+++ bidspace/src/main/java/geniusweb/bidspace/BidsWithUtility.java	(revision 53)
@@ -3,4 +3,5 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -39,5 +40,6 @@
 	 */
 	private final Map<Tuple<Integer, Interval>, ImmutableList<Bid>> cache = new HashMap<>();
-	private ImmutableList<Bid> emptylist = new FixedList<>();
+	private ImmutableList<Bid> emptylist = new FixedList<>(
+			Collections.emptyList());
 
 	/**
@@ -176,5 +178,5 @@
 		goal = goal.intersect(getRange(n));
 		if (goal.isEmpty()) {
-			return new FixedList<>();
+			return new FixedList<>(Collections.emptyList());
 		}
 
@@ -220,5 +222,6 @@
 					pbid -> pbid.merge(new Bid(issue, val)), partialbids);
 			if (!fullbids.size().equals(BigInteger.ZERO))
-				fulllist = new JoinedList<Bid>(fullbids, fulllist);
+				fulllist = new JoinedList<Bid>(
+						Arrays.asList(fullbids, fulllist));
 		}
 		return fulllist;
Index: bidspace/src/main/java/geniusweb/bidspace/PartialSpaceFromUtility.java
===================================================================
--- bidspace/src/main/java/geniusweb/bidspace/PartialSpaceFromUtility.java	(revision 52)
+++ bidspace/src/main/java/geniusweb/bidspace/PartialSpaceFromUtility.java	(revision 53)
@@ -3,4 +3,5 @@
 import java.math.BigInteger;
 import java.security.SecureRandom;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -24,21 +25,25 @@
 public class PartialSpaceFromUtility extends DefaultPartialOrdering {
 	public PartialSpaceFromUtility(UtilitySpace space, int nRankings) {
-		super(space.getName() + "_" + nRankings, space.getDomain(), space.getReservationBid(),
-				pickBetter(space, nRankings));
+		super(space.getName() + "_" + nRankings, space.getDomain(),
+				space.getReservationBid(), pickBetter(space, nRankings));
 	}
 
 	/**
-	 * Pick subset of static isbetter rankings. Notice, ShuffledList currently can't
-	 * handle really large lists which also limits this. This has to be fixed.
+	 * Pick subset of static isbetter rankings. Notice, ShuffledList currently
+	 * can't handle really large lists which also limits this. This has to be
+	 * fixed.
 	 * 
 	 * @param space     the space to sample from
-	 * @param nRankings the number of rankings to be placed in the PartialOrdering.
+	 * @param nRankings the number of rankings to be placed in the
+	 *                  PartialOrdering.
 	 * @return a subset creating a partial profile of the geiven UtilitySpace
 	 */
-	private static Map<Bid, Set<Bid>> pickBetter(UtilitySpace space, int nRankings) {
+	private static Map<Bid, Set<Bid>> pickBetter(UtilitySpace space,
+			int nRankings) {
 		Map<Bid, Set<Bid>> eqOrBetter = new HashMap<>();
 
 		AllBidsList allbids = new AllBidsList(space.getDomain());
-		ListWithRemove<Tuple<Bid, Bid>> available = new ListWithRemove<>(new Tuples<Bid, Bid>(allbids, allbids));
+		ListWithRemove<Tuple<Bid, Bid>> available = new ListWithRemove<>(
+				new Tuples<Bid, Bid>(allbids, allbids), Collections.emptySet());
 		for (int n = 0; n < nRankings; n++) {
 			BigInteger sel = rnd(available.size());
@@ -79,6 +84,6 @@
 
 	/**
-	 * Bit simplistic way to generate random in [0,n>. Simplistic because the mod()
-	 * operator that we use causes bias in the random numbers.
+	 * Bit simplistic way to generate random in [0,n>. Simplistic because the
+	 * mod() operator that we use causes bias in the random numbers.
 	 * 
 	 * @param n the maximum value for the random number
Index: bidspace/src/main/java/geniusweb/bidspace/SumOfGroupsLinAdditiveAdapter.java
===================================================================
--- bidspace/src/main/java/geniusweb/bidspace/SumOfGroupsLinAdditiveAdapter.java	(revision 53)
+++ bidspace/src/main/java/geniusweb/bidspace/SumOfGroupsLinAdditiveAdapter.java	(revision 53)
@@ -0,0 +1,337 @@
+package geniusweb.bidspace;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import geniusweb.bidspace.pareto.ParetoLinearAdditive;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.Domain;
+import geniusweb.issuevalue.Value;
+import geniusweb.issuevalue.ValueSet;
+import geniusweb.profile.utilityspace.DiscreteValueSetUtilities;
+import geniusweb.profile.utilityspace.LinearAdditive;
+import geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace;
+import geniusweb.profile.utilityspace.PartsUtilities;
+import geniusweb.profile.utilityspace.ProductOfValue;
+import geniusweb.profile.utilityspace.SumOfGroupsUtilitySpace;
+import geniusweb.profile.utilityspace.ValueSetUtilities;
+import tudelft.utilities.immutablelist.ArrayListSet;
+
+/**
+ * ValueSet with ProductOfValue objects as elements. Otherwise just a
+ * DiscreteValueSet. Storing the ProductOfValues here directly (instead of
+ * strings) makes it easier to map back and forth
+ *
+ */
+class GroupValueSet implements ValueSet {
+
+	/*
+	 * final, must be immutable so do not provide external access to this list.
+	 * ArrayList (instead of List) to help Jackson serializer which avoids
+	 * per-field type annotations.
+	 */
+	private final ArrayListSet<ProductOfValue> values = new ArrayListSet<>();
+
+	public GroupValueSet(Collection<ProductOfValue> issuevalues) {
+		this.values.addAll(issuevalues);
+	}
+
+	public List<ProductOfValue> getValues() {
+		return Collections.unmodifiableList(values);
+	}
+
+	@Override
+	public Boolean contains(Value value) {
+		return values.contains(value);
+	}
+
+	@Override
+	public ProductOfValue get(BigInteger index) {
+		return values.get(index.intValue());
+	}
+
+	@Override
+	public BigInteger size() {
+		return BigInteger.valueOf(values.size());
+	}
+
+	@Override
+	public ProductOfValue get(long index) {
+		return values.get((int) index);
+	}
+
+	@Override
+	public Iterator iterator() {
+		return values.iterator();
+	}
+
+	@Override
+	public String toString() {
+		return values.toString();
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((values == null) ? 0 : values.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		GroupValueSet other = (GroupValueSet) obj;
+		if (values == null) {
+			if (other.values != null)
+				return false;
+		} else if (!values.equals(other.values))
+			return false;
+		return true;
+	}
+}
+
+/**
+ * As {@link DiscreteValueSetUtilities} but with ProductOfValue instead of Value
+ */
+class GroupValueSetUtilities implements ValueSetUtilities {
+	private final Map<ProductOfValue, BigDecimal> valueUtilities = new HashMap<>();
+
+	public GroupValueSetUtilities(Map<ProductOfValue, BigDecimal> utilities) {
+		valueUtilities.putAll(utilities);
+	}
+
+	@Override
+	public BigDecimal getUtility(Value value) {
+		if (!valueUtilities.containsKey(value)) {
+			return BigDecimal.ZERO;
+		}
+		return valueUtilities.get(value);
+	}
+
+	@Override
+	public String isFitting(ValueSet valueset) {
+		if (!(valueset instanceof GroupValueSet)) {
+			return "The utilities are for a GroupValueSet valueset but the given values are "
+					+ valueset;
+		}
+		GroupValueSet discvalueset = (GroupValueSet) valueset;
+		if (!valueUtilities.keySet()
+				.equals(new HashSet<>(discvalueset.getValues())))
+			return "The values in the set " + valueset
+					+ " do not match the values mapped to utilities "
+					+ valueUtilities.keySet();
+		return null;
+	}
+
+	@Override
+	public String toString() {
+		return valueUtilities.toString();
+	}
+}
+
+/**
+ * Creates a {@link LinearAdditive} profile matching a
+ * {@link SumOfGroupsUtilitySpace}. THe {@link LinearAdditive} can then be used
+ * with tools like {@link ParetoLinearAdditive} or linear parties. Note that
+ * TimeDependentParty and all derivatives use this already and thus seamlessly
+ * support {@link SumOfGroupsUtilitySpace}.
+ * 
+ * <p>
+ * 
+ * The domain, issues values and utilities are all different from the
+ * {@link SumOfGroupsUtilitySpace}. The methods {@link #toLinearBid(Bid)} and
+ * {@link #toGroupBid(Bid)} can be used to convert back and forth. The space is
+ * made such that there is a constant scaling between utilities in the
+ * {@link SumOfGroupsUtilitySpace} and those in the adapted
+ * {@link LinearAdditive} space.
+ * 
+ */
+public class SumOfGroupsLinAdditiveAdapter extends LinearAdditiveUtilitySpace {
+
+	/*
+	 * special character, used as separator char in constructed issue names.
+	 * Must not be used in any original issue names. can be a non-printable
+	 * char, as this class does not serialize but for debugging it's nice to get
+	 * something readable
+	 */
+	private final static String SEP = "~";
+	private final static MathContext mc = new MathContext(10,
+			RoundingMode.DOWN);
+	private static final DiscreteValue WCVALUE = new DiscreteValue("C");
+	private static final ProductOfValue WC = new ProductOfValue(
+			Arrays.asList(WCVALUE));
+	private static final ValueSet WEIGHTCORRECTION = new GroupValueSet(
+			Collections.singletonList(WC));
+	private static final Map<ProductOfValue, BigDecimal> WEIGHTCORRUTIL = Collections
+			.singletonMap(WC, BigDecimal.ZERO);
+
+	private final SumOfGroupsUtilitySpace groupspace;
+
+	/**
+	 * Basically LinearAdditive constructor plus the original group space. Use
+	 * {@link #create(SumOfGroupsUtilitySpace)} to create a
+	 * {@link SumOfGroupsLinAdditiveAdapter}
+	 */
+	private SumOfGroupsLinAdditiveAdapter(SumOfGroupsUtilitySpace groupspace,
+			LinearAdditiveUtilitySpace lin) {
+		super(lin.getDomain(), groupspace.getName(), lin.getUtilities(),
+				lin.getWeights(), lin.getReservationBid());
+		this.groupspace = groupspace;
+	}
+
+	public static SumOfGroupsLinAdditiveAdapter create(
+			SumOfGroupsUtilitySpace groupspace) {
+		checkSpecialCharacter(groupspace);
+
+		final HashMap<String, ValueSetUtilities> linIssueUtilities = new HashMap<>();
+		final HashMap<String, BigDecimal> weights = new HashMap<>();
+		final Map<String, ValueSet> issueValues = new HashMap<>();
+		final BigDecimal SIZE = BigDecimal
+				.valueOf(groupspace.getPartsUtilities().size());
+		final BigDecimal weight = BigDecimal.ONE.divide(SIZE, mc);
+
+		// compute the joned-issue-names, values and utility maps
+		for (final PartsUtilities part : groupspace.getPartsUtilities()
+				.values()) {
+
+			// part is a group, containing a set of issues and
+			// ProductOfValue for every possible combination.
+			final String joinedissue = String.join(SEP, part.getIssues());
+			weights.put(joinedissue, weight);
+
+			issueValues.put(joinedissue,
+					new GroupValueSet(part.getUtilities().keySet()));
+			linIssueUtilities.put(joinedissue,
+					new GroupValueSetUtilities(part.getUtilities()));
+
+		}
+
+		// weight correction. Add issue with name SEP filling the remainder
+		issueValues.put(SEP, WEIGHTCORRECTION);
+		linIssueUtilities.put(SEP, new GroupValueSetUtilities(WEIGHTCORRUTIL));
+		weights.put(SEP, BigDecimal.ONE.subtract(weight.multiply(SIZE)));
+
+		final Domain lindomain = new Domain(groupspace.getDomain().getName(),
+				issueValues);
+		final Bid resbid = toLinearBid(groupspace.getReservationBid(),
+				groupspace);
+		final LinearAdditiveUtilitySpace linspace = new LinearAdditiveUtilitySpace(
+				lindomain, groupspace.getName(), linIssueUtilities, weights,
+				resbid);
+		return new SumOfGroupsLinAdditiveAdapter(groupspace, linspace);
+
+	}
+
+	/**
+	 * Check for occurences of {@link #SEP} in this space.
+	 * 
+	 * @param space2 the space to check
+	 */
+	private static void checkSpecialCharacter(SumOfGroupsUtilitySpace space2) {
+		Domain dom = space2.getDomain();
+		for (String issue : dom.getIssues()) {
+			checkString(issue);
+			for (Value val : dom.getValues(issue)) {
+				if (val instanceof DiscreteValue) {
+					checkString(((DiscreteValue) val).getValue());
+				}
+			}
+		}
+	}
+
+	/**
+	 * check that name does not contain the {@link #SEP} characte to avoid
+	 * problems later. This ensures 1-1 mapping between original names and names
+	 * in converted space.
+	 * 
+	 * @param name the name to check
+	 */
+	private static void checkString(String name) {
+		if (name.contains(SEP))
+			throw new IllegalArgumentException("space should not use  " + name
+					+ " : character '" + SEP + "' is reserved");
+	}
+
+	@Override
+	public String toString() {
+		return "LinearAdditiveAdapter[" + super.toString() + "]";
+	}
+
+	/**
+	 * 
+	 * @param bid
+	 * @param groupspace
+	 * @return bid converted to {@link LinearAdditiveUtilitySpace.
+	 */
+	public static Bid toLinearBid(Bid bid, SumOfGroupsUtilitySpace groupspace) {
+		if (bid == null)
+			return null;
+
+		final Map<String, Value> map = new HashMap<>();
+
+		for (PartsUtilities part : groupspace.getPartsUtilities().values()) {
+			String linissue = String.join(SEP, part.getIssues());
+			List<Value> values = part.getIssues().stream()
+					.map(iss -> bid.getValue(iss)).collect(Collectors.toList());
+			map.put(linissue, new ProductOfValue(values));
+		}
+		return new Bid(map);
+	}
+
+	/**
+	 * 
+	 * @param bid possibly partial {@link Bid} from {@link LinearAdditive} space
+	 * @return a possibly partial Bid in the {@link SumOfGroupsUtilitySpace}.
+	 */
+	public Bid toGroupBid(Bid bid) {
+		if (bid == null)
+			return null;
+
+		final Map<String, Value> allvalues = new HashMap<>();
+
+		for (String linissue : bid.getIssues()) {
+			allvalues.putAll(toGroupValues(linissue,
+					(ProductOfValue) bid.getValue(linissue)));
+		}
+		return new Bid(allvalues);
+	}
+
+	/**
+	 * 
+	 * @param linissue an issue in the {@link LinearAdditive} space
+	 * @param value    a value in the {@link LinearAdditive} space
+	 * @return a map of issue-value pairs in the {@link SumOfGroupsUtilitySpace}
+	 */
+	private Map<String, Value> toGroupValues(String linissue,
+			ProductOfValue value) {
+		if (linissue.equals(SEP))
+			// ignore the weight-balancer issue
+			return Collections.emptyMap();
+
+		final Map<String, Value> values = new HashMap<>();
+		final String[] issues = linissue.split(SEP);
+		for (int n = 0; n < issues.length; n = n + 1) {
+			values.put(issues[n], value.getValues().get(n));
+		}
+
+		return values;
+	}
+}
