// Path: src/de/uni_koblenz/west/splendid/helpers/FilterConditionCollector.java
// public class FilterConditionCollector extends QueryModelVisitorBase<RuntimeException> {
// 
// 	public static List<ValueExpr> process(QueryModelNode node) {
// 		FilterConditionCollector collector = new FilterConditionCollector();
// 		node.visit(collector);
// 		return collector.conditions;
// 	}
// 
// 	private List<ValueExpr> conditions = new ArrayList<ValueExpr>();
// 
// 	@Override
// 	public void meet(Filter node)
// 	{
// 		node.getArg().visit(this);
// 		conditions.add(node.getCondition());
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/helpers/Format.java
// public class Format {
// 
// 	private static final StringBuffer b = new StringBuffer();
// 	private static final Formatter f = new Formatter(b, Locale.US);
// 
// 	public static synchronized String d(double value, int length) {
// 		String style = "%." + length + "f";
// 		b.setLength(0);
// 		return f.format(style, value).toString();
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/model/BindJoin.java
// public class BindJoin extends Join {
// 	
// 	public BindJoin(TupleExpr leftArg, TupleExpr rightArg) {
// 		super(leftArg, rightArg);
// 	}
// 	
// 	@Override
// 	public boolean equals(Object other) {
// 		return other instanceof BindJoin && super.equals(other);
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return super.hashCode() ^ "BindJoin".hashCode();
// 	}
// 
// 	@Override
// 	public BindJoin clone() {
// 		return (BindJoin)super.clone();
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/model/HashJoin.java
// public class HashJoin extends Join {
// 	
// 	public HashJoin(TupleExpr leftArg, TupleExpr rightArg) {
// 		super(leftArg, rightArg);
// 	}
// 	
// 	@Override
// 	public boolean equals(Object other) {
// 		return other instanceof HashJoin && super.equals(other);
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return super.hashCode() ^ "HashJoin".hashCode();
// 	}
// 
// 	@Override
// 	public HashJoin clone() {
// 		return (HashJoin)super.clone();
// 	}
// 
// }


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openrdf.query.algebra.Filter;
import org.openrdf.query.algebra.Join;
import org.openrdf.query.algebra.StatementPattern;
import org.openrdf.query.algebra.TupleExpr;
import org.openrdf.query.algebra.ValueExpr;
import org.openrdf.query.algebra.helpers.StatementPatternCollector;
import org.openrdf.query.algebra.helpers.VarNameCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.uni_koblenz.west.splendid.helpers.FilterConditionCollector;
import de.uni_koblenz.west.splendid.helpers.Format;
import de.uni_koblenz.west.splendid.model.BindJoin;
import de.uni_koblenz.west.splendid.model.HashJoin;
//			LOGGER.debug("pruning " + plans.size() + " " + arity + " plans in " + equivalentPlans.size() + " equivalence classes");
//			if (LOGGER.isTraceEnabled()) {
//				int eqs = 0;
//				for (Set<O> equalSet : equivalentPlans) {
//					eqs++;
//					for (O plan : equalSet) {
//						String pStr = plan.toString().replace("\n", " ");
//						LOGGER.trace("SET [" + eqs + "] " + pStr);
//					}
//				}
//			}
//		}
		
		// Compare all plan from same equivalence class to find best one
		for (Set<TupleExpr> equalSet : equivalentPlans) {
			
			int planCount = 0;
			eqClass++;

			TupleExpr bestPlan = null;
			double lowestCost = Double.MAX_VALUE;
			
			for (TupleExpr plan : equalSet) {
				
				planCount++;
				double cost = costEstimator.process(plan);
				
				if (bestPlan == null || cost < lowestCost) {
					
					if (LOGGER.isTraceEnabled() && bestPlan != null) {
// Path: src/de/uni_koblenz/west/splendid/helpers/FilterConditionCollector.java
// public class FilterConditionCollector extends QueryModelVisitorBase<RuntimeException> {
// 
// 	public static List<ValueExpr> process(QueryModelNode node) {
// 		FilterConditionCollector collector = new FilterConditionCollector();
// 		node.visit(collector);
// 		return collector.conditions;
// 	}
// 
// 	private List<ValueExpr> conditions = new ArrayList<ValueExpr>();
// 
// 	@Override
// 	public void meet(Filter node)
// 	{
// 		node.getArg().visit(this);
// 		conditions.add(node.getCondition());
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/helpers/Format.java
// public class Format {
// 
// 	private static final StringBuffer b = new StringBuffer();
// 	private static final Formatter f = new Formatter(b, Locale.US);
// 
// 	public static synchronized String d(double value, int length) {
// 		String style = "%." + length + "f";
// 		b.setLength(0);
// 		return f.format(style, value).toString();
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/model/BindJoin.java
// public class BindJoin extends Join {
// 	
// 	public BindJoin(TupleExpr leftArg, TupleExpr rightArg) {
// 		super(leftArg, rightArg);
// 	}
// 	
// 	@Override
// 	public boolean equals(Object other) {
// 		return other instanceof BindJoin && super.equals(other);
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return super.hashCode() ^ "BindJoin".hashCode();
// 	}
// 
// 	@Override
// 	public BindJoin clone() {
// 		return (BindJoin)super.clone();
// 	}
// 
// }
// 
// Path: src/de/uni_koblenz/west/splendid/model/HashJoin.java
// public class HashJoin extends Join {
// 	
// 	public HashJoin(TupleExpr leftArg, TupleExpr rightArg) {
// 		super(leftArg, rightArg);
// 	}
// 	
// 	@Override
// 	public boolean equals(Object other) {
// 		return other instanceof HashJoin && super.equals(other);
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return super.hashCode() ^ "HashJoin".hashCode();
// 	}
// 
// 	@Override
// 	public HashJoin clone() {
// 		return (HashJoin)super.clone();
// 	}
// 
// }


// Path: src/de/uni_koblenz/west/splendid/optimizer/DynamicProgrammingOptimizer.java
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openrdf.query.algebra.Filter;
import org.openrdf.query.algebra.Join;
import org.openrdf.query.algebra.StatementPattern;
import org.openrdf.query.algebra.TupleExpr;
import org.openrdf.query.algebra.ValueExpr;
import org.openrdf.query.algebra.helpers.StatementPatternCollector;
import org.openrdf.query.algebra.helpers.VarNameCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.uni_koblenz.west.splendid.helpers.FilterConditionCollector;
import de.uni_koblenz.west.splendid.helpers.Format;
import de.uni_koblenz.west.splendid.model.BindJoin;
import de.uni_koblenz.west.splendid.model.HashJoin;

//			LOGGER.debug("pruning " + plans.size() + " " + arity + " plans in " + equivalentPlans.size() + " equivalence classes");
//			if (LOGGER.isTraceEnabled()) {
//				int eqs = 0;
//				for (Set<O> equalSet : equivalentPlans) {
//					eqs++;
//					for (O plan : equalSet) {
//						String pStr = plan.toString().replace("\n", " ");
//						LOGGER.trace("SET [" + eqs + "] " + pStr);
//					}
//				}
//			}
//		}
		
		// Compare all plan from same equivalence class to find best one
		for (Set<TupleExpr> equalSet : equivalentPlans) {
			
			int planCount = 0;
			eqClass++;

			TupleExpr bestPlan = null;
			double lowestCost = Double.MAX_VALUE;
			
			for (TupleExpr plan : equalSet) {
				
				planCount++;
				double cost = costEstimator.process(plan);
				
				if (bestPlan == null || cost < lowestCost) {
					
					if (LOGGER.isTraceEnabled() && bestPlan != null) {
						LOGGER.trace("found better plan (" + Format.d(cost, 2) + " < " + Format.d(lowestCost, 2) + "): " + planCount + " of " + equalSet.size() + " in class " + eqClass);