private ArrayList<Solution> dispatchAlgorithms(Solution solution, Set<Algebra> states){
		ArrayList<Solution> solutions = new ArrayList<Solution>();
		//iterate over algorithms
		//keep a list of all smarts, along with the respective algorithm and tree
		ArrayList<AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Algorithm, Tree>>> list = new ArrayList<AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Algorithm, Tree>>>();
		Tree tree = new Tree(solution.getLastAlgebraicExpression());
		
		//find the smarts and make a list of algorithms and the trees that represent the algebra to feed to them
		for(Algorithm algorithm : this.algorithms) {
			List<Tree> resources = tree.where(algorithm.ALGORITHM_LEVEL);
			//iterate over resources for the algorithm
			for(Tree node : resources) {
				int smarts = algorithm.smarts(node.algebra());
				if(smarts > 0) {
					list.add(new AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Algorithm, Tree>>(smarts, new AbstractMap.SimpleEntry<Algorithm, Tree>(algorithm, node)));
				}
			}
		}
		
		//sort the list by smarts
		Collections.sort(list, new Comparator<AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Algorithm, Tree>>>() {
			public int compare(AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Algorithm, Tree>> a, AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Algorithm, Tree>> b) {
				//sort DESC
				return b.getKey() - a.getKey();
			}
		});
		
		//now actually work with what we found
		for(AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Algorithm, Tree>> entry : list) {
			//pass the algebra to the algorithm
			Step step = entry.getValue().getKey().execute(entry.getValue().getValue().algebra());
			step.setAlgebraicExpression(entry.getValue().getValue().considerReplacement(step.getChange()));
			
			//skip this algorithm/algebra combination if it reaches a state already reached
			if(states.contains(step.getAlgebraicExpression())) continue;
			Solution newSolution = new Solution(solution);
			newSolution.addStep(step);
			solutions.add(newSolution);
		}
		return solutions;
	}