public void filter(Set<Item> usedItems, boolean filterTransitions) {
		
		if (filterTransitions) {
			Set<Transition> removeTrans = new ShareableHashSet<Transition>();
			Set<Transition> usedTrans = new ShareableHashSet<Transition>();
			for (Transition t : transitions) {
				if (t.reverse.size() > 0) { // only derives and reduces
					if (!t.used) {
						removeTrans.add(t);
					} else {
						boolean noReverseUsed = true;
						for (Transition r : t.reverse) {
							if (r.used) {
								noReverseUsed = false;
								break;
							}
						}
						if (noReverseUsed) {
							removeTrans.add(t);
							//System.out.println(t.toStringExt());
						} else {
							usedTrans.add(t);
						}
					}
				}
			}
			removeTrans.removeAll(usedTrans);
			removeTransitions(removeTrans);
		}
				
		if (clusters == null) {
			Set<Item> remove = allItems();
			remove.removeAll(usedItems);
			removeItems(remove);
			optimize(true); // now removes items of incomplete clusters
		} else {
			/*
			// XXX some items can appear in multiple clusters (for instance with LALR)
			// therefore we need to remove only the items not used in any cluster

			Set<Item> remove = new ShareableHashSet<Item>();
			Set<Item> used = new ShareableHashSet<Item>();
			for (Set<Item> c : clusters) {
				if (usedItems.containsAll(c)) {
					used.addAll(c);
				} else {
					remove.addAll(c);
					//System.out.println("rc: " + c);				
				}
			}
			
			// after a call to optimize, certain clusters might be removed partially
			// again, remove incompletely used clusters
			// taking into account items used in multiple clusters
			
			int oldSize = 0;
			while (items.size() != oldSize) {
				oldSize = items.size();
				remove.removeAll(used);
				removeItems(remove);
				
				optimize(true);
				
				remove = new ShareableHashSet<Item>();
				used = new ShareableHashSet<Item>();
				for (Set<Item> c : clusters) {
					int contained = 0;
					for (Item i : c) {
						if (items.contains(i)) {
							++contained;
						}
					}
					if (contained > 0) { // avoid removing the same clusters over and over again
						if (contained == c.size()) {
							used.addAll(c);
						} else {
							remove.addAll(c);
							//System.out.println("rc: " + c);
						}
					}
				}
			}		
			
			computeClusters();
			verify(); */
		}
	}