Implementing an ADT Example SumConstraint ADT Part II

  • Slides: 30
Download presentation
Implementing an ADT Example: Sum-Constraint ADT Part II Ohad Barzilay May 2004

Implementing an ADT Example: Sum-Constraint ADT Part II Ohad Barzilay May 2004

Cell implementation /** * A cell contains a value, and may be connected to

Cell implementation /** * A cell contains a value, and may be connected to * several constraint ports. * * @invariant connections != null, "Non-null connections" */ public class Cell { protected Object _value; protected List. Set connections; Ohad Barzilay, April 2004 2

Cell implementation /** * Creates a new Cell with no value. * * @post

Cell implementation /** * Creates a new Cell with no value. * * @post value() == null, "Null value" */ public Cell() { connections = new List. Set(); _value = null; } /** * Creates a new Cell with a given value. * * @post value() == new_val, "Value stored" */ public Cell(Object new_val) { this(); _value = new_val; } Ohad Barzilay, April 2004 3

value() /** * Returns the value stored in this Cell. */ public Object value()

value() /** * Returns the value stored in this Cell. */ public Object value() { return _value; } l l Don’t access fields directly No postcondition Ohad Barzilay, April 2004 4

add_connection /** * Adds a connection (a 'constraint - port' * pair) to the

add_connection /** * Adds a connection (a 'constraint - port' * pair) to the Cell. * * @pre c != null, "Non-null constraint" * @pre c. port_valid(port), "Valid port" */ public void add_connection(Constraint c, int port) { connections. extend(new Pair(c, new Integer(port))); } Ohad Barzilay, April 2004 5

set_value /** * Sets the value stored in the Cell to the given one.

set_value /** * Sets the value stored in the Cell to the given one. * Notifier is the user program. * * @pre new_val != null, "Non-null new value" * @post value() == new_val, "Value stored" */ public void set_value(Object new_val) { set_value(new_val, null, 0); } Ohad Barzilay, April 2004 6

set_value /** * Sets the value stored in the Cell to the given one.

set_value /** * Sets the value stored in the Cell to the given one. * If null, notifier is the user program. * * @pre new_val != null, "Non-null new value" * @pre notifier == null || notifier. port_valid(port), * "Valid port" * @pre notifier == null || value() == null, * "Constraint cannot override existing value" * * @post value() == new_val, "Value stored" */ public void set_value(Object new_val, Constraint notifier, int port) Ohad Barzilay, April 2004 7

set_value public void set_value(Object new_val, Constraint notifier, int port) { Set agenda = null;

set_value public void set_value(Object new_val, Constraint notifier, int port) { Set agenda = null; if (_value != null) { agenda = new List. Set(); forget(agenda); } _value = new_val; . . . Ohad Barzilay, April 2004 8

set_value. . . Linear iter = connections. iterator(); for (iter. start(); !iter. after(); iter.

set_value. . . Linear iter = connections. iterator(); for (iter. start(); !iter. after(); iter. forth()) { Pair connection = (Pair)iter. item(); Constraint c = (Constraint)connection. car(); int p = ((Integer)connection. cdr()). int. Value(); if (!(c == notifier && p == port)) c. new_port_value(p); } if (agenda != null) { iter = agenda. iterator(); for (iter. start(); !iter. after(); iter. forth()) ((Constraint)iter. item()). deduce(); } } Ohad Barzilay, April 2004 9

forget /** * Begins a value retraction chain from this Cell. * When finished,

forget /** * Begins a value retraction chain from this Cell. * When finished, the value of this Cell, and every value * in the network depending on it will be retracted. Then * it will be deduced if possible. */ public void forget() { Set agenda = new List. Set(); forget(agenda); Linear iter = agenda. iterator(); for (iter. start(); !iter. after(); iter. forth()) ((Constraint)iter. item()). deduce(); } Ohad Barzilay, April 2004 10

forget /** * A link within a retracting chain. * When finished, the value

forget /** * A link within a retracting chain. * When finished, the value of this Cell will be retracted. * * @pre agenda != null, "Non-null agenda" * @post value() == null */ protected void forget(Set agenda) { if (_value != null) { _value = null; Linear iter = connections. iterator(); for (iter. start(); !iter. after(); iter. forth()) { Pair connection = (Pair)iter. item(); Constraint c = (Constraint)connection. car(); int p = ((Integer)connection. cdr()). int. Value(); c. forget(p, agenda); } } } Ohad Barzilay, April 2004 11

to. String public String to. String() { String. Buffer result = new String. Buffer("<Cell:

to. String public String to. String() { String. Buffer result = new String. Buffer("<Cell: "); result. append(value() == null ? "---" : value(). to. String()); result. append(">"); return result. to. String(); } Ohad Barzilay, April 2004 12

The Solution Implementing Sum. Constraint

The Solution Implementing Sum. Constraint

Sum. Constraint public class Sum. Constraint extends Constraint { public static final int ADDEND

Sum. Constraint public class Sum. Constraint extends Constraint { public static final int ADDEND = 0; public static final int AUGEND = 1; public static final int SUM = 2; public static final int NUM_OF_PORTS = 3; protected Cell[] ports; protected boolean[] _deduced; Ohad Barzilay, April 2004 14

Sum. Constraint public Sum. Constraint(Cell addend, Cell augend, Cell sum) { ports = new

Sum. Constraint public Sum. Constraint(Cell addend, Cell augend, Cell sum) { ports = new Cell[NUM_OF_PORTS]; ports[ADDEND] = addend; ports[AUGEND] = augend; ports[SUM] = sum; addend. add_connection(this, ADDEND); augend. add_connection(this, AUGEND); sum. add_connection(this, SUM); _deduced = new boolean[NUM_OF_PORTS]; for (int i = 0; i < NUM_OF_PORTS; i++) _deduced[i] = false; deduce(); } Ohad Barzilay, April 2004 15

Sum. Constraint - contract /** * Creates a new Sum. Constraint which is connected

Sum. Constraint - contract /** * Creates a new Sum. Constraint which is connected to the * given Cells. * The Cells are fixed during the life of the constraint. * * @pre addend != null, "Non-null addend" * @pre augend != null, "Non-null augend" * @pre sum != null, "Non-null sum" * @post ($prev(addend. value()) == null) || defined(ADDEND), * "Addend defined if cell had value" * @post ($prev(augend. value()) == null) || defined(AUGEND), * "Augend defined if cell had value" * @post ($prev(sum. value()) == null) || defined(SUM), * "Sum defined if cell had value" */ public Sum. Constraint(Cell addend, Cell augend, Cell sum) Ohad Barzilay, April 2004 16

port_valid /** * Returns true if the given port is one of * ADDEND,

port_valid /** * Returns true if the given port is one of * ADDEND, AUGEND or SUM. */ public boolean port_valid(int port) { return 0 <= port && port < NUM_OF_PORTS; } Ohad Barzilay, April 2004 17

get_port /** * Returns the value stored in the given port. * * @pre

get_port /** * Returns the value stored in the given port. * * @pre port_valid(port), "Valid port" * // @pre known(port), "Port value is known" // * possible, but better: * @post !known(port) == ($ret == null), * "Unknown iff null" */ public Object get_port(int port) { return ports[port]. value(); } Ohad Barzilay, April 2004 18

defined /** * returns true iff the given port is defined. * * @pre

defined /** * returns true iff the given port is defined. * * @pre port_valid(port), "Valid port" * * @post $ret == (!deduced(port) && get_port(port) != null), * "Defined iff has value but not deduced" */ public boolean defined(int port) { return !_deduced[port] && ports[port]. value() != null; } Ohad Barzilay, April 2004 19

deduced /** * Is the port deduced? * * @pre port_valid(port), "Valid port" *

deduced /** * Is the port deduced? * * @pre port_valid(port), "Valid port" * * @post $ret == (!defined(port) && get_port(port) != null), * "Deduced iff has value but not defined" * @post !$ret || (((Integer)get_port(SUM)). int. Value() == * ((Integer)get_port(ADDEND)). int. Value() + * ((Integer)get_port(AUGEND)). int. Value()), * "Deduction obeys constraint" */ public boolean deduced(int port) { return _deduced[port]; } Ohad Barzilay, April 2004 20

known /** * Returns true if this port is either defined or deduced. *

known /** * Returns true if this port is either defined or deduced. * * @pre port_valid(port), "Valid port" * * @post $ret == (get_port(port) != null), * "Known iff port is non-null" */ public boolean known(int port) { return ports[port]. value() != null; } Ohad Barzilay, April 2004 21

contradiction /** * Returns true if all the ports are defined, and the sum

contradiction /** * Returns true if all the ports are defined, and the sum of the addend * and the augend port's values isn't equal to the value of the sum port. * * @post $ret == (defined(ADDEND) && defined(AUGEND) && defined(SUM) * && (((Integer)get_port(ADDEND)). int. Value() + * ((Integer)get_port(AUGEND)). int. Value() != * ((Integer)get_port(SUM)). int. Value())), * "Contradiction iff constraint not obeyed" */ public boolean contradiction() { return defined(ADDEND) && defined(AUGEND) && defined(SUM) && (((Integer)get_port(ADDEND)). int. Value() + ((Integer)get_port(AUGEND)). int. Value() != ((Integer)get_port(SUM)). int. Value()); } Ohad Barzilay, April 2004 22

new_port_value /** * Inform constraint of new value in port. To be called by

new_port_value /** * Inform constraint of new value in port. To be called by * connected cell after changing the cell's own value. * * @pre port_valid(port), "Valid port" * * @post defined(port), "Port defined" * @post !deduced(port), "Port not deduced" */ protected void new_port_value(int port) { deduced[port] = false; deduce(); } Ohad Barzilay, April 2004 23

forget /** * Retracts the value from the given port recursively. To be *

forget /** * Retracts the value from the given port recursively. To be * called by connected cell after it forgot its own value. If the * given port is not defined and/or is deduced nothing happens. * The constraint adds itself to the agenda in order to check * deductions after the process is finished. * * @pre port_valid(port), "Valid port" * @pre agenda != null, "Non-null agenda" * * @post !defined(port), "Port undefined" */ protected void forget(int port, Set agenda) { agenda. extend(this); retract(agenda); } Ohad Barzilay, April 2004 24

retract /** Retract previous deduction if no longer valid. */ protected void retract(Set agenda)

retract /** Retract previous deduction if no longer valid. */ protected void retract(Set agenda) { if (_deduced[ADDEND] && !(defined(AUGEND) && defined(SUM))) { _deduced[ADDEND] = false; ports[ADDEND]. forget(agenda); } else if (_deduced[AUGEND] && !(defined(ADDEND) && defined(SUM))) { _deduced[AUGEND] = false; ports[AUGEND]. forget(agenda); } else if (_deduced[SUM] && !(defined(ADDEND) && defined(AUGEND))) { _deduced[SUM] = false; ports[SUM]. forget(agenda); } } Ohad Barzilay, April 2004 25

deduce /** Attempt to deduce new information for ports in this constraint. */ protected

deduce /** Attempt to deduce new information for ports in this constraint. */ protected void deduce() { if (defined(ADDEND) && defined(AUGEND) && !known(SUM)) { _deduced[SUM] = true; ports[SUM]. set_value( new Integer(((Integer)get_port(ADDEND)). int. Value() + ((Integer)get_port(AUGEND)). int. Value()), this, SUM); }. . . Ohad Barzilay, April 2004 26

deduce. . . if (defined(ADDEND) && !known(AUGEND) && defined(SUM)) { _deduced[AUGEND] = true; ports[AUGEND].

deduce. . . if (defined(ADDEND) && !known(AUGEND) && defined(SUM)) { _deduced[AUGEND] = true; ports[AUGEND]. set_value (new Integer(((Integer)get_port(SUM)). int. Value() ((Integer)get_port(ADDEND)). int. Value()), this, AUGEND); } if (!known(ADDEND) && defined(AUGEND) && defined(SUM)) { _deduced[ADDEND] = true; ports[ADDEND]. set_value (new Integer(((Integer)get_port(SUM)). int. Value() ((Integer)get_port(AUGEND)). int. Value()), this, ADDEND); } } Ohad Barzilay, April 2004 27

port_string /** * @pre port_valid(port), "Valid port" */ protected String port_string(int port) { if

port_string /** * @pre port_valid(port), "Valid port" */ protected String port_string(int port) { if (defined(port)) return "defined(" + get_port(port). to. String() + ")"; else if (deduced(port)) return "deduced(" + get_port(port). to. String() + ")"; else return "---"; } Ohad Barzilay, April 2004 28

to. String public String to. String() { String. Buffer result = new String. Buffer("<Sum:

to. String public String to. String() { String. Buffer result = new String. Buffer("<Sum: "); result. append(port_string(ADDEND)); result. append(" + "); result. append(port_string(AUGEND)); result. append(" = "); result. append(port_string(SUM)); if (contradiction()) result. append(" ***"); result. append(">"); return result. to. String(); } Ohad Barzilay, April 2004 29

Questions?

Questions?