All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ai.libs.jaicore.search.exampleproblems.cannibals.CannibalGraphGenerator Maven / Gradle / Ivy

package ai.libs.jaicore.search.exampleproblems.cannibals;

import java.util.ArrayList;
import java.util.List;

import org.api4.java.datastructure.graph.implicit.IGraphGenerator;
import org.api4.java.datastructure.graph.implicit.INewNodeDescription;
import org.api4.java.datastructure.graph.implicit.IRootGenerator;
import org.api4.java.datastructure.graph.implicit.ISingleRootGenerator;
import org.api4.java.datastructure.graph.implicit.ISuccessorGenerator;

import ai.libs.jaicore.problems.cannibals.CannibalProblem;
import ai.libs.jaicore.search.model.NodeExpansionDescription;

public class CannibalGraphGenerator implements IGraphGenerator {

	private final CannibalProblem initState;

	public CannibalGraphGenerator(final CannibalProblem initState) {
		super();
		this.initState = initState;
	}

	@Override
	public IRootGenerator getRootGenerator() {
		return new ISingleRootGenerator() {

			@Override
			public CannibalProblem getRoot() {
				return CannibalGraphGenerator.this.initState;
			}
		};
	}

	@Override
	public ISuccessorGenerator getSuccessorGenerator() {
		return new ISuccessorGenerator() {

			@Override
			public List> generateSuccessors(final CannibalProblem node) throws InterruptedException {
				List> successors = new ArrayList<>();
				int ml = node.getMissionariesOnLeft();
				int mr = node.getMissionariesOnRight();
				int cl = node.getCannibalsOnLeft();
				int cr = node.getCannibalsOnRight();

				/* first consider the case that the boat is on the left */
				if (node.isBoatOnLeft()) {
					if (ml >= 2) {
						CannibalProblem candidate = new CannibalProblem(false, ml - 2, cl, mr + 2, cr);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "2m->"));
						}
					}
					if (ml >= 1) {
						CannibalProblem candidate = new CannibalProblem(false, ml - 1, cl, mr + 1, cr);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "1m->"));
						}
					}
					if (cl >= 1) {
						CannibalProblem candidate = new CannibalProblem(false, ml, cl - 1, mr, cr + 1);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "1c->"));
						}
					}
					if (ml >= 1 && cl >= 1) {
						CannibalProblem candidate = new CannibalProblem(false, ml - 1, cl - 1, mr + 1, cr + 1);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "1m1c->"));
						}
					}
					if (cl >= 2) {
						CannibalProblem candidate = new CannibalProblem(false, ml, cl - 2, mr, cr + 2);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "2c->"));
						}
					}
				}

				/* now consider the cases that the boat is on the right */
				else {
					if (mr >= 2) {
						CannibalProblem candidate = new CannibalProblem(true, ml + 2, cl, mr - 2, cr);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "2m<-"));
						}
					}
					if (mr >= 1) {
						CannibalProblem candidate = new CannibalProblem(true, ml + 1, cl, mr - 1, cr);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "1m<-"));
						}
					}
					if (cr >= 1) {
						CannibalProblem candidate = new CannibalProblem(true, ml, cl + 1, mr, cr - 1);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "1c<-"));
						}
					}
					if (mr >= 1 && cr >= 1) {
						CannibalProblem candidate = new CannibalProblem(true, ml + 1, cl + 1, mr - 1, cr - 1);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "1m1c<-"));
						}
					}
					if (cr >= 2) {
						CannibalProblem candidate = new CannibalProblem(true, ml, cl + 2, mr, cr - 2);
						CannibalGraphGenerator.this.checkThatNumberOfPeopleHasNotChanged(node, candidate);
						if (!candidate.isLost()) {
							successors.add(new NodeExpansionDescription<>(candidate, "2c<-"));
						}
					}
				}
				return successors;
			}
		};
	}

	private void checkThatNumberOfPeopleHasNotChanged(final CannibalProblem a, final CannibalProblem b) {
		if (a.getTotalNumberOfPeople() != b.getTotalNumberOfPeople()) {
			throw new IllegalStateException("Number of people has changed from " + a.getTotalNumberOfPeople() + " to " + b.getTotalNumberOfPeople());
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy