KR-IST - Lecture 3a: Problem solving in Java

Chris Thornton


Introduction

This lecture will look at a java program for solving the water-jugs problem.

We have two jugs X and Y.

X can hold 4 pints.

Y can hold 3.

Permissable moves are to fill X from Y, to fill Y from X, and to empty or fill either jug completely.

The aim is to find a sequence of actions, starting from empty jugs, which achieves a state in which Y contains exactly two pints.

Preliminaries

Initial questions

Produce a sketch of the successor method

Represent jug contents by numbers.

State representation is a data structure containing two numbers.

Successor generation will involve looking at two numbers and finding out which actions are possible.

Is it possible to transfer from one jug to another?

Is it possible to empty a jug?

Is it possible to fill a jug?

How will these actions be applied within the chosen state representation?

Node class

  import java.util.*;

  class Node {
     int x = 0, y = 0; /* state variables */
     Node parent = null; /* parent link */

     Node (int x, int y, Node parent) {
        this.x = x;
        this.y = y;
        this.parent = parent;
     }

     public String toString() {
        return(x + " " + y);
     }

     public boolean equals(Object node) { /* argument has to be an Object */
        return(((Node)node).x == x && ((Node)node).y == y);
     }

Re. use of Vectors rather than ArrayLists

For purposes of representing collections of Nodes, we need to use a collection class, like ArrayList.

However, this program uses Vectors rather than ArrayLists.

Vectors are essentially the same as ArrayLists, but they have a couple of extra features which are of use here, e.g., they print out nicely and also implement a `contains' method.

Node class cont.

     Vector<Node> getPath(Vector<Node> v) {
        v.insertElementAt(this, 0);
        if (parent != null) v = parent.getPath(v);
        return(v);
     }

     Vector<Node> getPath() { return(getPath(new Vector<Node>())); }
  }

WaterJugsSearch class (successor function)

  public class WaterJugsSearch {

     boolean isGoal(Node node) {
        return(node.y == 2);
     }

WaterJugsSearch class cont.

  Vector<Node> getSuccessors(Node parent) {
     int x = parent.x, y = parent.y;
     Vector<Node> successors = new Vector<Node>();
     if (x < 4 && y > 0) { /* transfer amount z from y to x */
        int z = Math.min(y, 4-x);
        successors.add(new Node(x+z, y-z, parent)); }
     if (y < 3 && x > 0) { /* transfer amount z from x to y */
        int z = Math.min(x, 3-y);
        successors.add(new Node(x-z, y+z, parent)); }
     if (x > 0) { /* empty x */
        successors.add(new Node(0, y, parent)); }
     if (y > 0) { /* empty y */
        successors.add(new Node(x, 0, parent)); }
     if (x < 4) { /* fill x from tap */
        successors.add(new Node(4, y, parent)); }
     if (y < 3) { /* fill y from tap */
        successors.add(new Node(x, 3, parent)); }
     return(successors);
  }

Main loop

  void run() {
     Vector<Node> open = new Vector<Node>();
     open.add(new Node(0, 0, null));

     while (open.size() > 0) {
        Node node = open.remove(0);
        if (isGoal(node)) {
           System.out.println("Solution: " + node.getPath()); }
        else {
           Vector<Node> successors = getSuccessors(node);
           for (int i = 0; i < successors.size(); i++) {
              Node child = successors.get(i);
              if (!node.getPath().contains((Object)child)) {
                 open.add(child); }
           }
        }
     }
  }

main method

     public static void main(String args[]) { // do the search
        new WaterJugsSearch().run();
     }
  }

Output generated

There are 12 distinct solutions:

  Solution: [0 0, 0 3, 3 0, 3 3, 4 2]
  Solution: [0 0, 4 0, 1 3, 0 3, 3 0, 3 3, 4 2]
  Solution: [0 0, 4 0, 4 3, 0 3, 3 0, 3 3, 4 2]
  Solution: [0 0, 4 0, 1 3, 4 3, 0 3, 3 0, 3 3, 4 2]
  Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 2 0, 0 2]
  Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 0 3, 3 0, 3 3, 4 2]
  Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 0 3, 3 0, 3 3, 4 2]
  Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 4 1, 4 3, 0 3, 3 0, 3 3, 4 2]
  Solution: [0 0, 0 3, 3 0, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 2 0, 0 2]
  Solution: [0 0, 0 3, 4 3, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 2 0, 0 2]
  Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 4 3, 0 3, 3 0, 3 3, 4 2]
  Solution: [0 0, 0 3, 3 0, 3 3, 4 3, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 2 0, 0 2]
.

Summary

Questions

Exercises

Implement a version of the WaterJugsSearch program which searches for a debt-minimising sequence of card transfers (as detailed in the previous lecture).