Index: /trunk/EventBenchConsole/src/de/ugoe/cs/eventbench/commands/CMDgenerateGreedy.java
===================================================================
--- /trunk/EventBenchConsole/src/de/ugoe/cs/eventbench/commands/CMDgenerateGreedy.java	(revision 394)
+++ /trunk/EventBenchConsole/src/de/ugoe/cs/eventbench/commands/CMDgenerateGreedy.java	(revision 395)
@@ -2,5 +2,6 @@
 
 import java.security.InvalidParameterException;
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -10,5 +11,4 @@
 
 import de.ugoe.cs.eventbench.CommandHelpers;
-import de.ugoe.cs.eventbench.coverage.CoverageCalculatorProcess;
 import de.ugoe.cs.eventbench.coverage.SequenceTools;
 import de.ugoe.cs.eventbench.data.Event;
@@ -50,4 +50,5 @@
 		int coverageDepth;
 		float desiredCoverage;
+		boolean validEnd = true;
 		try {
 			modelname = (String) parameters.get(0);
@@ -57,4 +58,7 @@
 			coverageDepth = Integer.parseInt((String) parameters.get(4));
 			desiredCoverage = Float.parseFloat((String) parameters.get(5));
+			if (parameters.size() >= 7) {
+				validEnd = Boolean.parseBoolean((String) parameters.get(6));
+			}
 		} catch (Exception e) {
 			throw new InvalidParameterException();
@@ -74,18 +78,21 @@
 
 		// set up everything
-		List<List<? extends Event<?>>> allSequences = new ArrayList<List<? extends Event<?>>>();
+		List<List<? extends Event<?>>> allSequences = new LinkedList<List<? extends Event<?>>>();
 		for (int length = minLength; length <= maxLength; length++) {
-			allSequences.addAll(model.generateValidSequences(length + 2));
+			if (validEnd) {
+				allSequences.addAll(model.generateValidSequences(length + 2));
+			} else {
+				allSequences.addAll(model.generateSequences(length + 1, true));
+			}
 		}
 		Console.traceln("" + allSequences.size() + " possible");
 
-		Set<List<? extends Event<?>>> allSubSeqs = SequenceTools
-				.containedSubSequences(allSequences, coverageDepth);
+		Collection<List<? extends Event<?>>> allSubSeqs = model
+				.generateSequences(coverageDepth);
 		Map<List<? extends Event<?>>, Double> weightMap = SequenceTools
 				.generateWeights(model, allSubSeqs);
 		Set<List<? extends Event<?>>> coveredSubSeqs = new LinkedHashSet<List<? extends Event<?>>>();
 
-		List<Set<List<? extends Event<?>>>> containedSubSeqs = new ArrayList<Set<List<? extends Event<?>>>>(
-				allSequences.size());
+		List<Set<List<? extends Event<?>>>> containedSubSeqs = new LinkedList<Set<List<? extends Event<?>>>>();
 		for (List<? extends Event<?>> sequence : allSequences) {
 			List<List<? extends Event<?>>> wrapper = new LinkedList<List<? extends Event<?>>>();
@@ -96,30 +103,59 @@
 		}
 
-		Double[] sequenceGain = new Double[allSequences.size()];
 		List<List<? extends Event<?>>> testSuite = new LinkedList<List<? extends Event<?>>>();
-		CoverageCalculatorProcess coverageCalculator = new CoverageCalculatorProcess(
-				model, testSuite, coverageDepth);
 		double currentCoverage = 0.0d;
 
 		// Build test suite
+		double prevGain = 1.0d;
+		boolean gainEqual = false;
 		while (currentCoverage < desiredCoverage) {
-			for (int i = 0; i < allSequences.size(); i++) {
+			Double[] sequenceGain = new Double[allSequences.size()];
+			int i = 0;
+			for (Set<List<? extends Event<?>>> containedSubSeq : containedSubSeqs) {
 				double gain = 0.0d;
-				for (List<? extends Event<?>> subSeq : containedSubSeqs.get(i)) {
+				Iterator<List<? extends Event<?>>> subSeqIter = containedSubSeq
+						.iterator();
+				while (subSeqIter.hasNext()) {
+					List<? extends Event<?>> subSeq = subSeqIter.next();
 					if (!coveredSubSeqs.contains(subSeq)) {
 						gain += weightMap.get(subSeq);
+					} else {
+						subSeqIter.remove();
 					}
 				}
 				sequenceGain[i] = gain;
+				// optimization using that the gain is monotonically decreasing
+				if (Math.abs(gain - prevGain) <= eps) {
+					gainEqual = true;
+					break;
+				}
+				i++;
 			}
-			int maxIndex = ArrayTools.findMax(sequenceGain);
-			if (sequenceGain[maxIndex] <= 0.0 + eps) {
+			int maxIndex;
+			if (gainEqual) {
+				maxIndex = i;
+			} else {
+				maxIndex = ArrayTools.findMax(sequenceGain);
+			}
+			if (maxIndex < 0 || sequenceGain[maxIndex] <= 0.0 + eps) {
 				Console.traceln("No gain anymore! Desired coverage cannot be satisfied!");
 				break;
 			}
+			prevGain = sequenceGain[maxIndex];
 			testSuite.add(allSequences.get(maxIndex));
 			coveredSubSeqs.addAll(containedSubSeqs.get(maxIndex));
-			coverageCalculator.setSequences(testSuite);
-			currentCoverage = coverageCalculator.getCoveragePossibleWeight();
+			currentCoverage += sequenceGain[maxIndex];
+			if (gainEqual) {
+				allSequences.remove(maxIndex);
+				containedSubSeqs.remove(maxIndex);
+				gainEqual = false;
+			} else {
+				for (int j = sequenceGain.length - 1; j >= 0; j--) {
+					if (j == maxIndex || sequenceGain[j] <= 0.0 + eps) {
+						allSequences.remove(j);
+						containedSubSeqs.remove(j);
+					}
+				}
+			}
 		}
 
@@ -138,5 +174,5 @@
 	@Override
 	public void help() {
-		Console.println("generateGreedy <modelname> <sequencesName> <minLength> <maxLength> <coverageDepth> <desiredCoverage>");
+		Console.println("generateGreedy <modelname> <sequencesName> <minLength> <maxLength> <coverageDepth> <desiredCoverage> {<validEnd>}");
 	}
 
