Added sum criterion, based on the upcoming 2.3.1 release of Sat4j.
diff --git a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Main.java b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Main.java
index fd2c856..ffdab99 100644
--- a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Main.java
+++ b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Main.java
@@ -88,7 +88,7 @@
 	private static final void usage() {
 		System.out.println("Usage: p2cudf [flags] inputFile [outputFile]");
 		System.out.println("-obj paranoid|trendy|<user defined>   The objective function to be used to resolve the problem.");
-		System.out.println("                                      Users can define their own: +new,-changed,-notuptodate,-unsat_recommends,-removed");
+		System.out.println("                                      Users can define their own: +new,-changed,-notuptodate,-unsat_recommends,-removed,-sum(installedsize)");
 		System.out.println("-timeout <number>(c|s)                The time out after which the solver will stop. e.g. 10s stops after 10 seconds, 10c stops after 10 conflicts. Default is set to 200c for p2 and 2000c for other objective functions.");
 		System.out.println("-sort                                 Sort the output.");
 		System.out.println("-explain                              Provides one reason of the unability to fullfil the request");
@@ -129,9 +129,9 @@
 				//				}
 				result.objective = args[++i];
 				if ("paranoid".equalsIgnoreCase(result.objective)) {
-					result.objective = "-removed,-changed";
+					result.objective = Options.PARANOID;
 				} else if ("trendy".equalsIgnoreCase(result.objective)) {
-					result.objective = "-removed,-notuptodate,-unsat_recommends,-new";
+					result.objective = Options.TRENDY;
 				}
 				continue;
 			}
@@ -243,12 +243,23 @@
 	private static ProfileChangeRequest parseCUDF(File file) {
 		Log.println("Parsing ...");
 		long myBegin = System.currentTimeMillis();
-		ProfileChangeRequest result = new Parser().parse(file, options.objective.contains("recommend"));
+		String sumpProperty = extractSumProperty(options.objective);
+		ProfileChangeRequest result = new Parser().parse(file, options.objective.contains("recommend"), sumpProperty);
 		long myEnd = System.currentTimeMillis();
 		Log.println(("Parsing done (" + (myEnd - myBegin) / 1000.0 + "s)."));
 		return result;
 	}
 
+	private static String extractSumProperty(String objectiveFunction) {
+		String[] criteria = objectiveFunction.split(",");
+		for (String criterion : criteria) {
+			if (criterion.contains("sum")) {
+				return Options.extractSumProperty(criterion);
+			}
+		}
+		return null;
+	}
+
 	static void printSolution(Collection state, Options theOptions) {
 		if (theOptions.sort) {
 			ArrayList tmp = new ArrayList(state);
diff --git a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Options.java b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Options.java
index 51777d7..66ad31a 100644
--- a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Options.java
+++ b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Options.java
@@ -4,7 +4,11 @@
 
 public class Options {
 	public static final String PARANOID = "-removed,-changed";
-	public static final String TRENDY = "-removed,-notuptodate,-unmet_recommends,-new";
+	public static final String TRENDY = "-removed,-notuptodate,-unsat_recommends,-new";
+
+	public static String extractSumProperty(String sumCriterion) {
+		return sumCriterion.substring(5, sumCriterion.length() - 1);
+	}
 
 	boolean verbose = false;
 	String objective = PARANOID;
diff --git a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Parser.java b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Parser.java
index 9b5ca0c..f8e81c5 100644
--- a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Parser.java
+++ b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/Parser.java
@@ -46,12 +46,12 @@
 	}
 
 	public ProfileChangeRequest parse(File file) {
-		return parse(file, false);
+		return parse(file, false, null);
 	}
 
-	public ProfileChangeRequest parse(File file, boolean includeRecommends) {
+	public ProfileChangeRequest parse(File file, boolean includeRecommends, String sumProperty) {
 		try {
-			return parse(new FileInputStream(file), includeRecommends);
+			return parse(new FileInputStream(file), includeRecommends, sumProperty);
 		} catch (FileNotFoundException e) {
 			e.printStackTrace();
 			return null;
@@ -59,10 +59,14 @@
 	}
 
 	public ProfileChangeRequest parse(InputStream stream) {
-		return parse(stream, false);
+		return parse(stream, false, null);
 	}
 
-	public ProfileChangeRequest parse(InputStream stream, boolean includeRecommends) {
+	public ProfileChangeRequest parse(InputStream stream, String sumProperty) {
+		return parse(stream, false, sumProperty);
+	}
+
+	public ProfileChangeRequest parse(InputStream stream, boolean includeRecommends, String sumProperty) {
 		long start;
 		if (TIMING)
 			start = System.currentTimeMillis();
@@ -125,8 +129,8 @@
 					handleRecommends(line);
 				} else if (line.startsWith("keep: ")) {
 					handleKeep(line);
-					// } else {
-					//	Log.println("Ignoring line:" + line);
+				} else if (sumProperty != null && line.startsWith(sumProperty)) {
+					handleSumProperty(line, sumProperty);
 				}
 			}
 		} catch (FileNotFoundException e) {
@@ -156,6 +160,11 @@
 		return currentRequest;
 	}
 
+	private void handleSumProperty(String line, String sumProperty) {
+		currentIU.setSumProperty(line.substring(sumProperty.length() + 1).trim());
+		System.out.printf("**** handling property %s with value %s for IU %s\n", sumProperty, currentIU.getSumProperty(), currentIU.getId());
+	}
+
 	private void handleKeep(String line) {
 		line = line.substring("keep: ".length());
 		if (line.contains("version")) {
diff --git a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/metadata/InstallableUnit.java b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/metadata/InstallableUnit.java
index f990594..e762311 100644
--- a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/metadata/InstallableUnit.java
+++ b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/metadata/InstallableUnit.java
@@ -26,6 +26,8 @@
 	private boolean singleton;
 	private boolean installed;
 
+	private String sumProperty;
+
 	public InstallableUnit() {
 		super();
 	}
@@ -133,4 +135,12 @@
 	public boolean isInstalled() {
 		return installed;
 	}
+
+	public String getSumProperty() {
+		return sumProperty;
+	}
+
+	public void setSumProperty(String sumProperty) {
+		this.sumProperty = sumProperty;
+	}
 }
diff --git a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/solver/OptimizationFunction.java b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/solver/OptimizationFunction.java
index 6456ebe..4201e46 100644
--- a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/solver/OptimizationFunction.java
+++ b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/solver/OptimizationFunction.java
@@ -195,6 +195,23 @@
 		}
 	}
 
+	protected void sum(List weightedObjects, boolean minimize, InstallableUnit metaIu, String sumProperty) {
+		Set s = slice.entrySet();
+		for (Iterator iterator = s.iterator(); iterator.hasNext();) {
+			Map.Entry entry = (Map.Entry) iterator.next();
+			if (entry.getKey() == metaIu.getId())
+				continue;
+			Collection versions = ((HashMap) entry.getValue()).values();
+			for (Iterator iterator2 = versions.iterator(); iterator2.hasNext();) {
+				InstallableUnit iuv = (InstallableUnit) iterator2.next();
+				if (iuv.getSumProperty() != null) {
+					BigInteger weight = new BigInteger(iuv.getSumProperty());
+					weightedObjects.add(WeightedObject.newWO(iuv, minimize ? weight : weight.negate()));
+				}
+			}
+		}
+	}
+
 	public abstract String getName();
 
 }
diff --git a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/solver/UserDefinedOptimizationFunction.java b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/solver/UserDefinedOptimizationFunction.java
index a63d550..84ca7cc 100644
--- a/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/solver/UserDefinedOptimizationFunction.java
+++ b/org.eclipse.equinox.p2.cudf/src/main/java/org/eclipse/equinox/p2/cudf/solver/UserDefinedOptimizationFunction.java
@@ -2,8 +2,10 @@
 
 import java.math.BigInteger;
 import java.util.*;
+import org.eclipse.equinox.p2.cudf.Options;
 import org.eclipse.equinox.p2.cudf.metadata.InstallableUnit;
 import org.sat4j.pb.tools.WeightedObject;
+import org.sat4j.specs.IVec;
 
 public class UserDefinedOptimizationFunction extends OptimizationFunction {
 
@@ -44,6 +46,12 @@
 				weightedObjects.clear();
 				changed(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
 				currentWeight = currentWeight.divide(weight);
+			} else if (criteria[i].contains("sum")) {
+				weightedObjects.clear();
+				sum(weightedObjects, criteria[i].charAt(0) == '-', metaIu, Options.extractSumProperty(criteria[i]));
+				dependencyHelper.addWeightedCriterion(weightedObjects);
+				System.out.println("# criteria " + criteria[i].substring(1) + " size is " + weightedObjects.size());
+				continue;
 			} else {
 				System.out.println("Skipping unknown criteria:" + criteria[i]);
 			}
@@ -58,7 +66,7 @@
 			}
 			dependencyHelper.addCriterion(objects);
 			newmaxvarid = dependencyHelper.getSolver().nextFreeVarId(false);
-			System.out.println("# criteria " + criteria[i].substring(1) + " size is " + objects.size() + " using vars " + formermaxvarid + " to " + newmaxvarid);
+			System.out.println("# criteria " + criteria[i].substring(1) + " size is " + objects.size() + " using new vars " + formermaxvarid + " to " + newmaxvarid);
 			formermaxvarid = newmaxvarid;
 		}
 		weightedObjects.clear();
@@ -144,6 +152,22 @@
 				System.out.println("# Changed packages: " + proof);
 				continue;
 			}
+			if (criteria[i].contains("sum")) {
+				String sumpProperty = Options.extractSumProperty(criteria[i]);
+				long sum = 0;
+				IVec sol = dependencyHelper.getSolution();
+				for (Iterator it = sol.iterator(); it.hasNext();) {
+					Object element = it.next();
+					if (element instanceof InstallableUnit) {
+						InstallableUnit iu = (InstallableUnit) element;
+						if (iu.getSumProperty() != null) {
+							sum += Long.parseLong(iu.getSumProperty());
+						}
+					}
+				}
+				System.out.println("# " + criteria[i] + " criteria value: " + sum);
+				continue;
+			}
 		}
 	}
 }