61A-013-Constraints_..

61A Lecture 13
Wednesday, September 28
Tuesday, September 27, 2011
Dictionaries
{'Dem': 0}
2
Tuesday, September 27, 2011
Limitations on Dictionaries
3
Tuesday, September 27, 2011
Limitations on Dictionaries
Dictionaries are unordered collections of key-value pairs.
3
Tuesday, September 27, 2011
Limitations on Dictionaries
Dictionaries are unordered collections of key-value pairs.
Dictionaries do have two restrictions:
3
Tuesday, September 27, 2011
Limitations on Dictionaries
Dictionaries are unordered collections of key-value pairs.
Dictionaries do have two restrictions:
•
A key of a dictionary cannot be an object of a mutable
built-in type.
3
Tuesday, September 27, 2011
Limitations on Dictionaries
Dictionaries are unordered collections of key-value pairs.
Dictionaries do have two restrictions:
•
A key of a dictionary cannot be an object of a mutable
built-in type.
•
Two keys cannot be equal. There can be at most one value for
a given key.
3
Tuesday, September 27, 2011
Limitations on Dictionaries
Dictionaries are unordered collections of key-value pairs.
Dictionaries do have two restrictions:
•
A key of a dictionary cannot be an object of a mutable
built-in type.
•
Two keys cannot be equal. There can be at most one value for
a given key.
This first restriction is tied to Python's underlying
implementation of dictionaries.
3
Tuesday, September 27, 2011
Limitations on Dictionaries
Dictionaries are unordered collections of key-value pairs.
Dictionaries do have two restrictions:
•
A key of a dictionary cannot be an object of a mutable
built-in type.
•
Two keys cannot be equal. There can be at most one value for
a given key.
This first restriction is tied to Python's underlying
implementation of dictionaries.
The second restriction is an intentional consequence of the
dictionary abstraction.
3
Tuesday, September 27, 2011
Implementing Dictionaries
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
for item in records:
if item[0] == key:
item[1] = value
return
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
for item in records:
if item[0] == key:
item[1] = value
return
records.append([key, value])
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
for item in records:
if item[0] == key:
item[1] = value
return
records.append([key, value])
def dispatch(message, key=None, value=None):
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
for item in records:
if item[0] == key:
item[1] = value
return
records.append([key, value])
def dispatch(message, key=None, value=None):
if message == 'getitem':
return getitem(key)
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
for item in records:
if item[0] == key:
item[1] = value
return
records.append([key, value])
def dispatch(message, key=None, value=None):
if message == 'getitem':
return getitem(key)
elif message == 'setitem':
setitem(key, value)
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
for item in records:
if item[0] == key:
item[1] = value
return
records.append([key, value])
def dispatch(message, key=None, value=None):
if message == 'getitem':
return getitem(key)
elif message == 'setitem':
setitem(key, value)
elif message == 'keys':
return tuple(k for k, _ in records)
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
for item in records:
if item[0] == key:
item[1] = value
return
records.append([key, value])
def dispatch(message, key=None, value=None):
if message == 'getitem':
return getitem(key)
elif message == 'setitem':
setitem(key, value)
elif message == 'keys':
return tuple(k for k, _ in records)
elif message == 'values':
return tuple(v for _, v in records)
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
for item in records:
if item[0] == key:
item[1] = value
return
records.append([key, value])
def dispatch(message, key=None, value=None):
if message == 'getitem':
return getitem(key)
elif message == 'setitem':
setitem(key, value)
elif message == 'keys':
return tuple(k for k, _ in records)
elif message == 'values':
return tuple(v for _, v in records)
return dispatch
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
Question: Do we need a
nonlocal statement here?
for item in records:
if item[0] == key:
item[1] = value
return
records.append([key, value])
def dispatch(message, key=None, value=None):
if message == 'getitem':
return getitem(key)
elif message == 'setitem':
setitem(key, value)
elif message == 'keys':
return tuple(k for k, _ in records)
elif message == 'values':
return tuple(v for _, v in records)
return dispatch
4
Tuesday, September 27, 2011
Implementing Dictionaries
def make_dict():
"""Return a functional implementation of a dictionary."""
records = []
def getitem(key):
for k, v in records:
if k == key:
return v
def setitem(key, value):
Question: Do we need a
nonlocal statement here?
for item in records:
if item[0] == key:
item[1] = value
return
records.append([key, value])
def dispatch(message, key=None, value=None):
if message == 'getitem':
return getitem(key)
elif message == 'setitem':
setitem(key, value)
elif message == 'keys':
return tuple(k for k, _ in records)
elif message == 'values':
return tuple(v for _, v in records)
Demo
return dispatch
4
Tuesday, September 27, 2011
Message Passing
5
Tuesday, September 27, 2011
Message Passing
An approach to organizing the relationship among different
pieces of a program
5
Tuesday, September 27, 2011
Message Passing
An approach to organizing the relationship among different
pieces of a program
Different objects pass messages to each other
5
Tuesday, September 27, 2011
Message Passing
An approach to organizing the relationship among different
pieces of a program
Different objects pass messages to each other
• What is your fourth element?
5
Tuesday, September 27, 2011
Message Passing
An approach to organizing the relationship among different
pieces of a program
Different objects pass messages to each other
• What is your fourth element?
• Change your third element to this new value. (please)
5
Tuesday, September 27, 2011
Message Passing
An approach to organizing the relationship among different
pieces of a program
Different objects pass messages to each other
• What is your fourth element?
• Change your third element to this new value. (please)
Encapsulates the behavior of all
operations on a piece of data
within one function that responds
to different messages.
5
Tuesday, September 27, 2011
Message Passing
An approach to organizing the relationship among different
pieces of a program
Different objects pass messages to each other
• What is your fourth element?
• Change your third element to this new value. (please)
Encapsulates the behavior of all
operations on a piece of data
within one function that responds
to different messages.
Important historical interest: the
message passing approach strongly
influenced object-oriented
programming (next lecture).
5
Tuesday, September 27, 2011
Dispatch Dictionaries
6
Tuesday, September 27, 2011
Dispatch Dictionaries
Enumerating different messages in a conditional statement
isn't very convenient:
6
Tuesday, September 27, 2011
Dispatch Dictionaries
Enumerating different messages in a conditional statement
isn't very convenient:
 Equality tests are repetitive
6
Tuesday, September 27, 2011
Dispatch Dictionaries
Enumerating different messages in a conditional statement
isn't very convenient:
 Equality tests are repetitive
 We can't add new messages without writing new code
6
Tuesday, September 27, 2011
Dispatch Dictionaries
Enumerating different messages in a conditional statement
isn't very convenient:
 Equality tests are repetitive
 We can't add new messages without writing new code
A dispatch dictionary has messages as keys and functions (or
data objects) as values.
6
Tuesday, September 27, 2011
Dispatch Dictionaries
Enumerating different messages in a conditional statement
isn't very convenient:
 Equality tests are repetitive
 We can't add new messages without writing new code
A dispatch dictionary has messages as keys and functions (or
data objects) as values.
Dictionaries handle the message look-up logic; we concentrate
on implementing useful behavior.
6
Tuesday, September 27, 2011
Dispatch Dictionaries
Enumerating different messages in a conditional statement
isn't very convenient:
 Equality tests are repetitive
 We can't add new messages without writing new code
A dispatch dictionary has messages as keys and functions (or
data objects) as values.
Dictionaries handle the message look-up logic; we concentrate
on implementing useful behavior.
In Javascript, all objects are just dictionaries
6
Tuesday, September 27, 2011
Dispatch Dictionaries
Enumerating different messages in a conditional statement
isn't very convenient:
 Equality tests are repetitive
 We can't add new messages without writing new code
A dispatch dictionary has messages as keys and functions (or
data objects) as values.
Dictionaries handle the message look-up logic; we concentrate
on implementing useful behavior.
Demo
In Javascript, all objects are just dictionaries
6
Tuesday, September 27, 2011
Example: Constraint Programming
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
a = c - b
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
a = c - b
b = c - a
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
a = c - b
b = c - a
Algebraic equations are declarative. They describe how
different quantities relate to one another.
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
a = c - b
b = c - a
Algebraic equations are declarative. They describe how
different quantities relate to one another.
Python functions are procedural. They describe how to compute
a particular result from a particular set of inputs.
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
a = c - b
b = c - a
Algebraic equations are declarative. They describe how
different quantities relate to one another.
Python functions are procedural. They describe how to compute
a particular result from a particular set of inputs.
Constraint programming:
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
a = c - b
b = c - a
Algebraic equations are declarative. They describe how
different quantities relate to one another.
Python functions are procedural. They describe how to compute
a particular result from a particular set of inputs.
Constraint programming:
 We define the relationship between quantities
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
a = c - b
b = c - a
Algebraic equations are declarative. They describe how
different quantities relate to one another.
Python functions are procedural. They describe how to compute
a particular result from a particular set of inputs.
Constraint programming:
 We define the relationship between quantities
 We provide values for the "known" quantities
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
a = c - b
b = c - a
Algebraic equations are declarative. They describe how
different quantities relate to one another.
Python functions are procedural. They describe how to compute
a particular result from a particular set of inputs.
Constraint programming:
 We define the relationship between quantities
 We provide values for the "known" quantities
 The system computes values for the "unknown" quantities
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
a = c - b
b = c - a
Algebraic equations are declarative. They describe how
different quantities relate to one another.
Python functions are procedural. They describe how to compute
a particular result from a particular set of inputs.
Constraint programming:
 We define the relationship between quantities
 We provide values for the "known" quantities
 The system computes values for the "unknown" quantities
Challenge: We want a general means of combination.
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
p * v = n * k * t
a = c - b
b = c - a
Algebraic equations are declarative. They describe how
different quantities relate to one another.
Python functions are procedural. They describe how to compute
a particular result from a particular set of inputs.
Constraint programming:
 We define the relationship between quantities
 We provide values for the "known" quantities
 The system computes values for the "unknown" quantities
Challenge: We want a general means of combination.
7
Tuesday, September 27, 2011
Example: Constraint Programming
a + b = c
p * v = n * k * t
a = c - b
b = c - a
9 * c = 5 * (f - 32)
Algebraic equations are declarative. They describe how
different quantities relate to one another.
Python functions are procedural. They describe how to compute
a particular result from a particular set of inputs.
Constraint programming:
 We define the relationship between quantities
 We provide values for the "known" quantities
 The system computes values for the "unknown" quantities
Challenge: We want a general means of combination.
7
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
9 * celsius = 5 * (fahrenheit - 32)
8
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
Combination idea: All intermediate quantities have values too.
9 * celsius = 5 * (fahrenheit - 32)
8
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
Combination idea: All intermediate quantities have values too.
9 * celsius = 5 * (fahrenheit - 32)
This quantity
relates directly
to celsius
8
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
Combination idea: All intermediate quantities have values too.
u
9 * celsius = 5 * (fahrenheit - 32)
This quantity
relates directly
to celsius
8
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
Combination idea: All intermediate quantities have values too.
u
9 * celsius = 5 * (fahrenheit - 32)
This quantity
relates directly
to celsius
This quantity
relates directly
to fahrenheit
8
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
Combination idea: All intermediate quantities have values too.
u
v
9 * celsius = 5 * (fahrenheit - 32)
This quantity
relates directly
to celsius
This quantity
relates directly
to fahrenheit
8
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
Combination idea: All intermediate quantities have values too.
u
v
9 * celsius = 5 * (fahrenheit - 32)
This quantity
relates directly
to celsius
This quantity
relates directly
to fahrenheit
8
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
Combination idea: All intermediate quantities have values too.
u
v
9 * celsius = 5 * (fahrenheit - 32)
This quantity
relates directly
to celsius
This quantity
relates directly
to fahrenheit
Both sides equal:
they must be
the same quantity
8
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
Combination idea: All intermediate quantities have values too.
u
u
v
9 * celsius = 5 * (fahrenheit - 32)
This quantity
relates directly
to celsius
This quantity
relates directly
to fahrenheit
Both sides equal:
they must be
the same quantity
8
Tuesday, September 27, 2011
A Constraint Network for Temperature Conversion
Combination idea: All intermediate quantities have values too.
u
u
v
Both sides equal:
they must be
the same quantity
9 * celsius = 5 * (fahrenheit - 32)
This quantity
relates directly
to celsius
celsius
a
w
b
9
*
This quantity
relates directly
to fahrenheit
c
u
c
*
v
a
b
x
5
a
b
y
+
c
fahrenheit
32
8
Tuesday, September 27, 2011
Anatomy of a Constraint
celsius
a
w
b
*
c
u
9
Tuesday, September 27, 2011
Anatomy of a Constraint
celsius
a
w
b
Blue names are
"connectors"
*
c
u
9
Tuesday, September 27, 2011
Anatomy of a Constraint
celsius
a
w
b
Blue names are
"connectors"
*
c
u
Boxes are
"constraints"
9
Tuesday, September 27, 2011
Anatomy of a Constraint
celsius
a
w
b
Blue names are
"connectors"
*
c
u
Constraints compute
values for "unknown"
connectors
Boxes are
"constraints"
9
Tuesday, September 27, 2011
Anatomy of a Constraint
celsius
a
w
b
Blue names are
"connectors"
*
c
u
Constraints compute
values for "unknown"
connectors
Boxes are
"constraints"
• Connectors represent quantities that have values.
9
Tuesday, September 27, 2011
Anatomy of a Constraint
celsius
a
w
b
Blue names are
"connectors"
*
c
u
Constraints compute
values for "unknown"
connectors
Boxes are
"constraints"
• Connectors represent quantities that have values.
• Constraints spread information among connectors.
9
Tuesday, September 27, 2011
Anatomy of a Constraint
celsius
a
w
b
Blue names are
"connectors"
*
c
u
Constraints compute
values for "unknown"
connectors
Boxes are
"constraints"
• Connectors represent quantities that have values.
• Constraints spread information among connectors.
• A constraint can receive two messages from its connectors:
9
Tuesday, September 27, 2011
Anatomy of a Constraint
celsius
a
w
b
Blue names are
"connectors"
*
c
u
Constraints compute
values for "unknown"
connectors
Boxes are
"constraints"
• Connectors represent quantities that have values.
• Constraints spread information among connectors.
• A constraint can receive two messages from its connectors:
 'new_val' indicates that some connector that is connected
to the constraint has a new value.
9
Tuesday, September 27, 2011
Anatomy of a Constraint
celsius
a
w
b
Blue names are
"connectors"
*
c
u
Constraints compute
values for "unknown"
connectors
Boxes are
"constraints"
• Connectors represent quantities that have values.
• Constraints spread information among connectors.
• A constraint can receive two messages from its connectors:
 'new_val' indicates that some connector that is connected
to the constraint has a new value.
 'forget' indicates that some connector that is connected
to the constraint has forgotten its value.
9
Tuesday, September 27, 2011
Constructing a Constraint Network
10
Tuesday, September 27, 2011
Constructing a Constraint Network
celsius = make_connector('Celsius')
10
Tuesday, September 27, 2011
Constructing a Constraint Network
celsius
celsius = make_connector('Celsius')
10
Tuesday, September 27, 2011
Constructing a Constraint Network
celsius
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
10
Tuesday, September 27, 2011
Constructing a Constraint Network
celsius
fahrenheit
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
10
Tuesday, September 27, 2011
Constructing a Constraint Network
celsius
fahrenheit
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
celsius
fahrenheit
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
celsius
fahrenheit
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
celsius
w
v
u
fahrenheit
x
y
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
celsius
w
v
u
fahrenheit
x
y
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
celsius
a
w
b
v
*
c
u
fahrenheit
x
y
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
multiplier(v, x, u)
celsius
a
w
b
v
*
c
u
fahrenheit
x
y
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
multiplier(v, x, u)
celsius
a
w
b
*
c
u
c
*
v
a
b
fahrenheit
x
y
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
multiplier(v, x, u)
adder(v, y, fahrenheit)
celsius
a
w
b
*
c
u
c
*
v
a
b
fahrenheit
x
y
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
multiplier(v, x, u)
adder(v, y, fahrenheit)
celsius
a
w
b
*
c
u
c
*
v
a
b
x
a
y
b
+
c
fahrenheit
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
multiplier(v, x, u)
adder(v, y, fahrenheit)
constant(w, 9)
celsius
a
w
b
*
c
u
c
*
v
a
b
x
a
y
b
+
c
fahrenheit
9
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
multiplier(v, x, u)
adder(v, y, fahrenheit)
constant(w, 9)
constant(x, 5)
celsius
a
w
b
9
*
c
u
c
*
v
a
b
x
a
y
b
+
c
fahrenheit
5
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
multiplier(v, x, u)
adder(v, y, fahrenheit)
constant(w, 9)
constant(x, 5)
constant(y, 32)
celsius
a
w
b
9
*
c
u
c
*
v
a
b
x
5
a
b
y
+
c
fahrenheit
32
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
10
Tuesday, September 27, 2011
Constructing a Constraint Network
def make_converter(celsius, fahrenheit):
"""Make a temperature conversion network."""
u, v, w, x, y = [make_connector() for _ in range(5)]
multiplier(celsius, w, u)
multiplier(v, x, u)
adder(v, y, fahrenheit)
constant(w, 9)
constant(x, 5)
constant(y, 32)
celsius
a
w
b
9
*
c
u
c
*
v
a
b
x
5
a
b
y
+
c
fahrenheit
32
celsius = make_connector('Celsius')
fahrenheit = make_connector('Fahrenheit')
make_converter(celsius, fahrenheit)
Demo
10
Tuesday, September 27, 2011
The Messages of a Connector
11
Tuesday, September 27, 2011
The Messages of a Connector
connector = make_connector('Celsius')
11
Tuesday, September 27, 2011
The Messages of a Connector
connector = make_connector('Celsius')
connector['set_val'](source, value) indicates that the
source is requesting the connector to set its current
value to value.
11
Tuesday, September 27, 2011
The Messages of a Connector
connector = make_connector('Celsius')
connector['set_val'](source, value) indicates that the
source is requesting the connector to set its current
value to value.
connector['has_val']() returns whether the connector
already has a value.
11
Tuesday, September 27, 2011
The Messages of a Connector
connector = make_connector('Celsius')
connector['set_val'](source, value) indicates that the
source is requesting the connector to set its current
value to value.
connector['has_val']() returns whether the connector
already has a value.
connector['val'] is the current value of the connector.
11
Tuesday, September 27, 2011
The Messages of a Connector
connector = make_connector('Celsius')
connector['set_val'](source, value) indicates that the
source is requesting the connector to set its current
value to value.
connector['has_val']() returns whether the connector
already has a value.
connector['val'] is the current value of the connector.
connector['forget'](source) tells the connector that the
source is requesting it to forget its value.
11
Tuesday, September 27, 2011
The Messages of a Connector
connector = make_connector('Celsius')
connector['set_val'](source, value) indicates that the
source is requesting the connector to set its current
value to value.
connector['has_val']() returns whether the connector
already has a value.
connector['val'] is the current value of the connector.
connector['forget'](source) tells the connector that the
source is requesting it to forget its value.
connector['connect'](source) tells the connector to
participate in a new constraint, the source.
11
Tuesday, September 27, 2011
Implementing an Adder Constraint
12
Tuesday, September 27, 2011
multiplier(v, x, u)
adder(v, y, f)
constant(w, 9)
constant(x, 5)
Implementing
constant(y, an
32)Adder
Constraint
def adder_constraint(a, b, c):
"""The constraint that a + b = c.
>>>
>>>
>>>
a =
>>>
b =
c =
"""
def
a, b, c = [make_connector(name) for name in ('a', 'b', 'c')]
constraint = adder_constraint(a, b, c)
a['set_val']('user', 2)
2
b['set_val']('user', 3)
3
5
new_value():
av, bv, cv = [connector['has_val']() for connector in (a, b, c)]
if av and bv:
c['set_val'](constraint, a['val'] + b['val'])
elif av and cv:
b['set_val'](constraint, c['val'] é a['val'])
elif bv and cv:
a['set_val'](constraint, c['val'] é b['val'])
def forget_value():
for connector in (a, b, c):
connector['forget'](constraint)
constraint = {'new_val': new_value, 'forget': forget_value}
for connector in (a, b, c):
connector['connect'](constraint)
return constraint
Tuesday, September 27, 2011
12
multiplier(c,
multiplier(v, w,
x, u)
u)
multiplier(v,
adder(v, y, f)x, u)
adder(v,
y, f)
constant(w,
9)
constant(w,
constant(x, 9)
5)
Implementing
an
constant(x,
constant(y, 5)
32)Adder Constraint
constant(y, 32)
def adder_constraint(a, b, c):
def adder_constraint(a,
b, a
c):
"""The constraint that
+ b = c.
"""The constraint that a + b = c.
>>> a, b, c = [make_connector(name) for name in ('a', 'b', 'c')]
>>>
b, c = [make_connector(name)
name in ('a', 'b', 'c')]
>>> a,
constraint
= adder_constraint(a,for
b, c)
>>>
= adder_constraint(a,
b, c)
>>> constraint
a['set_val']('user',
2)
>>>
2)
a = a['set_val']('user',
2
a
= 2
>>>
b['set_val']('user', 3)
>>>
3)
b = b['set_val']('user',
3
b
c =
= 3
5
c
=
""" 5
"""
def new_value():
def av,
new_value():
bv, cv = [connector['has_val']() for connector in (a, b, c)]
av, bv, cv = [connector['has_val']() for connector in (a, b, c)]
if
if av
av and
and bv:
bv:
c['set_val'](constraint,
c['set_val'](constraint, a['val']
a['val'] +
+ b['val'])
b['val'])
elif
av
and
cv:
elif av and cv:
b['set_val'](constraint,
b['set_val'](constraint, c['val']
c['val'] é
é a['val'])
a['val'])
elif
bv
and
cv:
elif bv and cv:
a['set_val'](constraint,
a['set_val'](constraint, c['val']
c['val'] é
é b['val'])
b['val'])
def
def forget_value():
forget_value():
for
for connector
connector in
in (a,
(a, b,
b, c):
c):
connector['forget'](constraint)
connector['forget'](constraint)
constraint
constraint =
= {'new_val':
{'new_val': new_value,
new_value, 'forget':
'forget': forget_value}
forget_value}
for
for connector
connector in
in (a,
(a, b,
b, c):
c):
connector['connect'](constraint)
connector['connect'](constraint)
return constraint
Tuesday, September 27, 2011
12
multiplier(c,
multiplier(v, w,
x, u)
u)
multiplier(v,
adder(v, y, f)x, u)
adder(v,
y, f)
constant(w,
9)
constant(w,
constant(x, 9)
5)
Implementing
an
constant(x,
constant(y, 5)
32)Adder Constraint
constant(y, 32)
def adder_constraint(a, b, c):
def adder_constraint(a,
b, a
c):
"""The constraint that
+ b = c.
"""The constraint that a + b = c.
>>> a, b, c = [make_connector(name) for name in ('a', 'b', 'c')]
>>>
b, c = [make_connector(name)
name in ('a', 'b', 'c')]
>>> a,
constraint
= adder_constraint(a,for
b, c)
>>>
= adder_constraint(a,
b, c)
>>> constraint
a['set_val']('user',
2)
>>>
2)
a = a['set_val']('user',
2
a
= 2
>>>
b['set_val']('user', 3)
>>>
3)
b = b['set_val']('user',
3
b
c =
= 3
5
c
=
""" 5
"""
def new_value():
def av,
new_value():
bv, cv = [connector['has_val']() for connector in (a, b, c)]
av, bv, cv = [connector['has_val']() for connector in (a, b, c)]
if
av
# We
willbv:
implement this function momentarily!
if
av and
and
bv:
c['set_val'](constraint,
c['set_val'](constraint, a['val']
a['val'] +
+ b['val'])
b['val'])
elif
av
and
cv:
elif av and cv:
b['set_val'](constraint,
b['set_val'](constraint, c['val']
c['val'] é
é a['val'])
a['val'])
elif
bv
and
cv:
elif bv and cv:
a['set_val'](constraint,
a['set_val'](constraint, c['val']
c['val'] é
é b['val'])
b['val'])
def
def forget_value():
forget_value():
for
for connector
connector in
in (a,
(a, b,
b, c):
c):
connector['forget'](constraint)
connector['forget'](constraint)
constraint
constraint =
= {'new_val':
{'new_val': new_value,
new_value, 'forget':
'forget': forget_value}
forget_value}
for
for connector
connector in
in (a,
(a, b,
b, c):
c):
connector['connect'](constraint)
connector['connect'](constraint)
return constraint
Tuesday, September 27, 2011
12
multiplier(c,
multiplier(v, w,
x, u)
u)
multiplier(v,
adder(v, y, f)x, u)
def adder_constraint(a,
b, c):
adder(v,
y, f)
constant(w,
9)
"""The
constraint
that a + b = c.
constant(w,
9)
constant(x,
5)
Implementing
constant(x,
5)
constant(y, an
32)Adder Constraint
>>>
a, b, c =32)
[make_connector(name) for name in ('a', 'b', 'c')]
constant(y,
constraint = adder_constraint(a,
b, c)
def >>>
adder_constraint(a,
b, c):
def >>>
adder_constraint(a,
b, a
c):
a['set_val']('user',
2)
"""The
constraint that
+ b = c.
a"""The
= 2 constraint that a + b = c.
>>>
3)
>>> b['set_val']('user',
a, b, c = [make_connector(name)
for name in ('a', 'b', 'c')]
b, c = [make_connector(name)
name in ('a', 'b', 'c')]
b>>>
= 3a,
>>>
constraint
= adder_constraint(a,for
b, c)
= adder_constraint(a,
b, c)
c>>>
= 5constraint
>>>
a['set_val']('user',
2)
>>>
2)
"""
a = a['set_val']('user',
2
a
= new_value():
2
def
>>>
b['set_val']('user', 3)
>>>
b['set_val']('user',
3)
bv, cv = [connector['has_val']()
for connector in (a, b, c)]
b = av,
3
b
3
c =
= if
5 av and bv:
c
= 5
c['set_val'](constraint, a['val'] + b['val'])
"""
"""
av and cv:
def elif
new_value():
def av,
new_value():
b['set_val'](constraint,
c['val'] for
é a['val'])
bv, cv = [connector['has_val']()
connector in (a, b, c)]
av,
bv,
cv
=
[connector['has_val']()
for
connector in (a, b, c)]
elif
bvand
andbv:
cv:
if
av
# We
willbv:
implement this function
momentarily!
if
av
and
a['set_val'](constraint,
c['val']
é+ b['val'])
c['set_val'](constraint,
a['val']
c['set_val'](constraint, a['val'] + b['val'])
b['val'])
elif
av
and
cv:
elif av and cv:
def forget_value():
b['set_val'](constraint,
c['val']
b['set_val'](constraint,
c['val'] é
é a['val'])
a['val'])
for
connector
in
(a,
b,
c):
elif
bv
and
cv:
elifconnector['forget'](constraint)
bv and cv:
a['set_val'](constraint,
a['set_val'](constraint, c['val']
c['val'] é
é b['val'])
b['val'])
constraint
= {'new_val': new_value, 'forget': forget_value}
def
forget_value():
def forget_value():
for
connector
in
(a,
b,
c):
for
connector
in
(a,
b,
c):
for connector
in
(a,
b,
c):
connector['forget'](constraint)
connector['forget'](constraint)
connector['connect'](constraint)
constraint
=
{'new_val':
new_value,
'forget':
forget_value}
constraint
=
{'new_val':
new_value,
'forget':
forget_value}
return constraint
for
for connector
connector in
in (a,
(a, b,
b, c):
c):
connector['connect'](constraint)
12
connector['connect'](constraint)
def make_ternary_constraint(a,
b, c, ab, ca, cb):
"""The
constraint
Tuesday, September
27, 2011
return
constraint that ab(a,b)=c and ca(c,a)=b and cb(c,b) = a."""
Generalizing to a Multiplication Constraint
13
Tuesday, September 27, 2011
Generalizing to a Multiplication Constraint
13_constraints.py
elif bv and cv:
a['set_val'](constraint, cb(c['val'], b['val']))
def forget_value():
for connector in (a, b, c):
connector['forget'](constraint)
constraint = {'new_val': new_value, 'forget': forget_value}
for connector in (a, b, c):
connector['connect'](constraint)
return constraint
from operator import add, sub, mul, truediv
def adder(a, b, c):
"""The constraint that a + b = c."""
return make_ternary_constraint(a, b, c, add, sub, sub)
def multiplier(a, b, c):
"""The constraint that a * b = c."""
return make_ternary_constraint(a, b, c, mul, truediv, truediv)
def constant(connector, value):
"""The constraint that connector = value."""
constraint = {}
Tuesday, September 27, 2011
13
constraint = {'new_val': new_value, 'forget': forget_value}
for connector
in
(a, b, c):
Generalizing
to
a
Multiplication
Constraint
connector['connect'](constraint)
return constraint
def make_ternary_constraint(a, b, c, ab, ca, cb):
"""The constraint that ab(a,b)=c and ca(c,a)=b and cb(c,b)=a."""
def new_value():
13_constraints.py
av, bv, cv = [connector['has_val']() for connector in (a, b, c)]
if av and bv:
elif c['set_val'](constraint,
bv and cv:
ab(a['val'], b['val']))
cb(c['val'], b['val']))
elifa['set_val'](constraint,
av and cv:
def forget_value():
b['set_val'](constraint, ac(c['val'], a['val']))
for connector in (a, b, c):
connector['forget'](constraint)
constraint = {'new_val': new_value, 'forget': forget_value}
for connector in (a, b, c):
connector['connect'](constraint)
return constraint
from operator import add, sub, mul, truediv
def adder(a, b, c):
"""The constraint that a + b = c."""
return make_ternary_constraint(a, b, c, add, sub, sub)
def multiplier(a, b, c):
"""The constraint that a * b = c."""
return make_ternary_constraint(a, b, c, mul, truediv, truediv)
def constant(connector, value):
"""The constraint that connector = value."""
constraint = {}
Tuesday, September 27, 2011
13
constraint = {'new_val': new_value, 'forget': forget_value}
for connector
in
(a, b, c):
Generalizing
to
a
Multiplication
Constraint
connector['connect'](constraint)
return constraint
Connectors
def make_ternary_constraint(a, b, c, ab, ca, cb):
"""The constraint that ab(a,b)=c and ca(c,a)=b and cb(c,b)=a."""
def new_value():
13_constraints.py
av, bv, cv = [connector['has_val']() for connector in (a, b, c)]
if av and bv:
elif c['set_val'](constraint,
bv and cv:
ab(a['val'], b['val']))
cb(c['val'], b['val']))
elifa['set_val'](constraint,
av and cv:
def forget_value():
b['set_val'](constraint, ac(c['val'], a['val']))
for connector in (a, b, c):
connector['forget'](constraint)
constraint = {'new_val': new_value, 'forget': forget_value}
for connector in (a, b, c):
connector['connect'](constraint)
return constraint
from operator import add, sub, mul, truediv
def adder(a, b, c):
"""The constraint that a + b = c."""
return make_ternary_constraint(a, b, c, add, sub, sub)
def multiplier(a, b, c):
"""The constraint that a * b = c."""
return make_ternary_constraint(a, b, c, mul, truediv, truediv)
def constant(connector, value):
"""The constraint that connector = value."""
constraint = {}
Tuesday, September 27, 2011
13
constraint = {'new_val': new_value, 'forget': forget_value}
for connector
in
(a, b, c):
Generalizing
to
a
Multiplication
Constraint
connector['connect'](constraint)
return constraint
Connectors
Relations
def make_ternary_constraint(a, b, c, ab, ca, cb):
"""The constraint that ab(a,b)=c and ca(c,a)=b and cb(c,b)=a."""
def new_value():
13_constraints.py
av, bv, cv = [connector['has_val']() for connector in (a, b, c)]
if av and bv:
elif c['set_val'](constraint,
bv and cv:
ab(a['val'], b['val']))
cb(c['val'], b['val']))
elifa['set_val'](constraint,
av and cv:
def forget_value():
b['set_val'](constraint, ac(c['val'], a['val']))
for connector in (a, b, c):
connector['forget'](constraint)
constraint = {'new_val': new_value, 'forget': forget_value}
for connector in (a, b, c):
connector['connect'](constraint)
return constraint
from operator import add, sub, mul, truediv
def adder(a, b, c):
"""The constraint that a + b = c."""
return make_ternary_constraint(a, b, c, add, sub, sub)
def multiplier(a, b, c):
"""The constraint that a * b = c."""
return make_ternary_constraint(a, b, c, mul, truediv, truediv)
def constant(connector, value):
"""The constraint that connector = value."""
constraint = {}
Tuesday, September 27, 2011
13
connector['forget'](constraint)
constraint = {'new_val': new_value, 'forget': forget_value}
constraint = {'new_val': new_value, 'forget': forget_value}
for connector in (a, b, c):
for connector
in (a, b, c):
connector['connect'](constraint)
connector['connect'](constraint)
return constraint
Connectors
Relations
return constraint
Generalizing to a Multiplication Constraint
def make_ternary_constraint(a, b, c, ab, ca, cb):
def make_ternary_constraint(a,
b, c, ab,
cb): and cb(c,b)=a."""
"""The constraint that ab(a,b)=c
and ca,
ca(c,a)=b
"""The
constraint that ab(a,b)=c and ca(c,a)=b and cb(c,b) = a."""
def new_value():
def new_value():
13_constraints.py
av, bv, cv = [connector['has_val']() for connector in (a, b, c)]
av,
bv,and
cv bv:
= [connector['has_val']() for connector in (a, b, c)]
if av
if
avc['set_val'](constraint,
and
bv:
elif
bv
and
cv:
ab(a['val'], b['val']))
ab(a['val'],
a['set_val'](constraint,
cb(c['val'], b['val']))
elifc['set_val'](constraint,
av and cv:
av and cv:
def elif
forget_value():
b['set_val'](constraint,
ac(c['val'], a['val']))
for b['set_val'](constraint,
connector in (a, b, c): ac(c['val'], a['val']))
connector['forget'](constraint)
constraint = {'new_val': new_value, 'forget': forget_value}
for connector in (a, b, c):
connector['connect'](constraint)
return constraint
from operator import add, sub, mul, truediv
def adder(a, b, c):
"""The constraint that a + b = c."""
return make_ternary_constraint(a, b, c, add, sub, sub)
def multiplier(a, b, c):
"""The constraint that a * b = c."""
return make_ternary_constraint(a, b, c, mul, truediv, truediv)
def constant(connector, value):
"""The constraint that connector = value."""
constraint = {}
Tuesday, September 27, 2011
13
for connector['forget'](constraint)
connector in (a, b, c):
connector['forget'](constraint)
constraint
= {'new_val': new_value, 'forget': forget_value}
constraint = {'new_val': new_value, 'forget': forget_value}
constraint
= {'new_val':
new_value, 'forget': forget_value}
for connector
in (a, b, c):
for connector
in (a, b, c):
connector['connect'](constraint)
for connector['connect'](constraint)
connector in (a, b, c):
connector['connect'](constraint)
return
constraint
Connectors
Relations
return constraint
return constraint
def make_ternary_constraint(a, b, c, ab, ca, cb):
def make_ternary_constraint(a,
b, c, ab,
cb): and cb(c,b)=a."""
"""The constraint that ab(a,b)=c
and ca,
ca(c,a)=b
def make_ternary_constraint(a,
b, c, and
ab, ca(c,a)=b
ca, cb): and cb(c,b) = a."""
"""The
constraint that ab(a,b)=c
def new_value():
"""The
that ab(a,b)=c and ca(c,a)=b
and cb(c,b)
= a."""
def new_value():
13_constraints.py
av,constraint
bv, cv = [connector['has_val']()
for connector
in (a,
b, c)]
def av,
new_value():
bv,
cv
=
[connector['has_val']()
for
connector
in
(a,
b,
c)]
if av and bv:
av,
bv,
cv
=cv:
[connector['has_val']()
for connector
in (a, b, c)]
if
av
and
bv:
elif
bv
and
c['set_val'](constraint,
ab(a['val'],
b['val']))
if
av
andand
bv:cv:
c['set_val'](constraint,
ab(a['val'],
a['set_val'](constraint,
cb(c['val'], b['val']))
elif
av
c['set_val'](constraint,
ab(a['val'],
av and cv:
def elif
forget_value():
b['set_val'](constraint,
ac(c['val'], b['val']))
a['val']))
elif
av and cv:
for b['set_val'](constraint,
connector
in (a, b, c): ac(c['val'], a['val']))
b['set_val'](constraint,
ac(c['val'], a['val']))
connector['forget'](constraint)
constraint = {'new_val': new_value, 'forget': forget_value}
for connector in (a, b, c):
connector['connect'](constraint)
return constraint
Generalizing to a Multiplication Constraint
from operator import add, sub, mul, truediv
def adder(a, b, c):
"""The constraint that a + b = c."""
return make_ternary_constraint(a, b, c, add, sub, sub)
def multiplier(a, b, c):
"""The constraint that a * b = c."""
return make_ternary_constraint(a, b, c, mul, truediv, truediv)
def constant(connector, value):
"""The constraint that connector = value."""
constraint = {}
Tuesday, September 27, 2011
13
for connector['forget'](constraint)
connector in (a, b, c):
connector['forget'](constraint)
constraint
= {'new_val': new_value, 'forget': forget_value}
constraint = {'new_val': new_value, 'forget': forget_value}
constraint
= {'new_val':
new_value, 'forget': forget_value}
for connector
in (a, b, c):
for connector
in (a, b, c):
connector['connect'](constraint)
for connector['connect'](constraint)
connector in (a, b, c):
connector['connect'](constraint)
return
constraint
Connectors
Relations
return constraint
return constraint
def make_ternary_constraint(a, b, c, ab, ca, cb):
def make_ternary_constraint(a,
b, c, ab,
cb): and cb(c,b)=a."""
"""The constraint that ab(a,b)=c
and ca,
ca(c,a)=b
def make_ternary_constraint(a,
b, c, and
ab, ca(c,a)=b
ca, cb): and cb(c,b) = a."""
"""The
constraint that ab(a,b)=c
def new_value():
"""The
that ab(a,b)=c and ca(c,a)=b
and cb(c,b)
= a."""
def new_value():
13_constraints.py
av,constraint
bv, cv = [connector['has_val']()
for connector
in (a,
b, c)]
def av,
new_value():
bv,
cv
=
[connector['has_val']()
for
connector
in
(a,
b,
c)]
if av and bv:
av,
bv,
cv
=cv:
[connector['has_val']()
for connector
in (a, b, c)]
if
av
and
bv:
elif
bv
and
c['set_val'](constraint,
ab(a['val'],
b['val']))
if
av
andand
bv:cv:
c['set_val'](constraint,
ab(a['val'],
a['set_val'](constraint,
cb(c['val'], b['val']))
elif
av
c['set_val'](constraint,
ab(a['val'],
av and cv:
def elif
forget_value():
b['set_val'](constraint,
ac(c['val'], b['val']))
a['val']))
elif
av and cv:
for b['set_val'](constraint,
connector
in (a, b, c): ac(c['val'], a['val']))
b['set_val'](constraint,
ac(c['val'], a['val']))
13_constraints.py
connector['forget'](constraint)
constraint = {'new_val': new_value, 'forget': forget_value}
elif bv and
for connector
incv:
(a, b, c):
a['set_val'](constraint, cb(c['val'], b['val']))
connector['connect'](constraint)
def forget_value():
return
constraint
for connector in (a, b, c):
connector['forget'](constraint)
from operator
import add, sub, mul, truediv
constraint = {'new_val': new_value, 'forget': forget_value}
for connector
in (a, b, c):
def adder(a,
b, c):
connector['connect'](constraint)
"""The
constraint that a + b = c."""
return make_ternary_constraint(a,
constraint
b, c, add, sub, sub)
Generalizing to a Multiplication Constraint
frommultiplier(a,
operator import
add, sub, mul, truediv
def
b, c):
"""The constraint that a * b = c."""
def return
adder(a,
b, c):
make_ternary_constraint(a,
b, c, mul, truediv, truediv)
"""The constraint that a + b = c."""
return make_ternary_constraint(a,
b, c, add, sub, sub)
def constant(connector,
value):
"""The constraint that connector = value."""
def constraint
multiplier(a,
b, c):
= {}
Tuesday, September 27, 2011
13
Implementing a Connector
14
Tuesday, September 27, 2011
def constant(connector, value):
"""The constraint that connector = value."""
constraint = {}
connector['set_val'](constraint, value)
return constraint
Implementing a Connector
def make_connector(name=None):
"""A connector between constraints.
>>> celsius = make_connector('Celsius')
>>> fahrenheit = make_connector('Fahrenheit')
>>> make_converter(celsius, fahrenheit)
>>> celsius['set_val']('user', 25)
Celsius = 25
Fahrenheit = 77.0
>>> fahrenheit['set_val']('user', 212)
Contradiction detected: 77.0 vs 212
>>> celsius['forget']('user')
Celsius is forgotten
Fahrenheit is forgotten
>>> fahrenheit['set_val']('user', 212)
Fahrenheit = 212
Celsius = 100.0
"""
informant = None
constraints = []
def set_value(source, value):
nonlocal informant
val = connector['val']
if val is None:
informant, connector['val'] = source, value
if name is not None:
print(name, '=', value)
inform_all_except(source, 'new_val', constraints)
else:
if val != value:
print('Contradiction detected:', val, 'vs', value)
Tuesday, September 27, 2011
14
>>> fahrenheit['set_val']('user', 212)
def Contradiction
constant(connector,
value):
detected:
77.0 vs 212
"""The constraint that connector = value."""
constraint
= {}
>>>
celsius['forget']('user')
connector['set_val'](constraint,
value)
Celsius
is forgotten
return constraint
Fahrenheit
is forgotten
Implementing a Connector
def >>>
make_connector(name=None):
fahrenheit['set_val']('user', 212)
"""A connector
between constraints.
Fahrenheit
= 212
Celsius = 100.0
>>> celsius = make_connector('Celsius')
"""
>>> fahrenheit
= make_connector('Fahrenheit')
informant
= None
>>> make_converter(celsius,
fahrenheit)
constraints
= []
def set_value(source, value):
>>> nonlocal
celsius['set_val']('user',
25)
informant
Celsius
= connector['val']
25
val =
Fahrenheit
= 77.0
if val is
None:
informant, connector['val'] = source, value
>>> fahrenheit['set_val']('user',
212)
if name is not None:
Contradiction
detected: '=',
77.0 value)
vs 212
print(name,
inform_all_except(source, 'new_val', constraints)
>>> celsius['forget']('user')
else:
Celsius
is forgotten
if
!= value:
Fahrenheit val
is forgotten
print('Contradiction detected:', val, 'vs', value)
def
>>> forget_value(source):
fahrenheit['set_val']('user', 212)
nonlocal
Fahrenheit = informant
212
if
informant
Celsius = 100.0 == source:
informant, connector['val'] = None, None
"""
if =name
informant
Noneis not None:
'is forgotten')
constraints print(name,
= []
inform_all_except(source,
'forget', constraints)
def set_value(source,
value):
connector
= {'val':
None,
nonlocal
informant
'set_val': set_value,
val = connector['val']
forget_value,
if val is'forget':
None:
'has_val':
lambda: connector['val']
is not None,
informant,
connector['val']
= source, value
'connect':
lambda source: constraints.append(source)}
if name
is not None:
print(name, '=', value)
inform_all_except(source, 'new_val', constraints)
else:
if val != value:
print('Contradiction detected:', val, 'vs', value)
Tuesday, September 27, 2011
14
>>> fahrenheit['set_val']('user', 212)
def Contradiction
constant(connector,
value):
detected:
77.0 vs 212
"""The constraint that connector = value."""
constraint
= {}
>>>
celsius['forget']('user')
connector['set_val'](constraint,
value)
Celsius
is forgotten
return constraint
Fahrenheit
is forgotten
Implementing a Connector
def >>>
make_connector(name=None):
fahrenheit['set_val']('user', 212)
"""A connector
between constraints.
Fahrenheit
= 212
Celsius = 100.0
>>> celsius = make_connector('Celsius')
"""
>>> fahrenheit
= make_connector('Fahrenheit')
informant
= None
>>> make_converter(celsius,
fahrenheit)
constraints
= []
def set_value(source, value):
>>> nonlocal
celsius['set_val']('user',
25)
informant
Celsius
= connector['val']
25
val =
Fahrenheit
= 77.0
if val is
None:
informant, connector['val'] = source, value
>>> fahrenheit['set_val']('user',
212)
if name is not None:
Contradiction
detected: '=',
77.0 value)
vs 212
print(name,
inform_all_except(source, 'new_val', constraints)
>>> celsius['forget']('user')
else:
Celsius
is forgotten
if
!= value:
Fahrenheit val
is forgotten
print('Contradiction detected:', val, 'vs', value)
def
>>> forget_value(source):
fahrenheit['set_val']('user', 212)
nonlocal
Fahrenheit = informant
212
if
informant
Celsius = 100.0 == source:
informant, connector['val'] = None, None
"""
if =name
informant
Noneis not None:
'is forgotten')
constraints print(name,
= []
inform_all_except(source,
'forget', constraints)
def set_value(source,
value):
connector
= {'val':
None,
nonlocal
informant
'set_val': set_value,
val = connector['val']
forget_value,
if val is'forget':
None:
'has_val':
lambda: connector['val']
is not None,
informant,
connector['val']
= source, value
13_constraints.py
'connect':
lambda source: constraints.append(source)}
if name
is not None:
print(name, '=', value)
return connector
inform_all_except(source, 'new_val', constraints)
else:
def inform_all_except(source,
message, constraints):
if val != value:
"""Inform all
constraints of the message,
except
print('Contradiction
detected:',
val,source."""
'vs', value)
Tuesday, September 27, 2011
for c in constraints:
Page 4
14
>>> fahrenheit['set_val']('user', 212)
celsius['forget']('user')
def >>>
constant(connector,
value):
Contradiction
detected:
77.0 vs 212
Celsius
is
forgotten
"""The constraint that connector = value."""
Fahrenheit
is
forgotten
constraint
= {}
>>>
celsius['forget']('user')
connector['set_val'](constraint,
value)
Celsius
is forgotten
>>>
fahrenheit['set_val']('user',
212)
return constraint
Fahrenheit
is forgotten
Fahrenheit = 212
Celsius
= 100.0
def >>>
make_connector(name=None):
fahrenheit['set_val']('user',
212)
"""
"""A connector
between constraints.
Fahrenheit
= 212
informant
None
Celsius = =
100.0
constraints
>>> celsius = []
make_connector('Celsius')
"""
def
value):
>>> set_value(source,
fahrenheit
= make_connector('Fahrenheit')
informant
= None
>>> nonlocal
make_converter(celsius,
fahrenheit)
constraints
=informant
[]
= connector['val']
def val
set_value(source,
value):
val
is
None:
>>> if
celsius['set_val']('user',
25)
nonlocal informant
informant,
connector['val'] = source, value
Celsius
= connector['val']
25
val =
Fahrenheit
= 77.0
if name
is not None:
if val
is
None:
print(name,
'=', value) = source, value
informant,
connector['val']
>>> fahrenheit['set_val']('user',
212)
inform_all_except(source,
'new_val',
constraints)
if name is not None:
Contradiction
detected: '=',
77.0 value)
vs 212
else:
print(name,
if val != value:
inform_all_except(source,
'new_val', constraints)
>>> celsius['forget']('user')
print('Contradiction
detected:',
val, 'vs', value)
else:
Celsius
is forgotten
def
forget_value(source):
if
val
!= value:
Fahrenheit
isinformant
forgotten
nonlocal
print('Contradiction detected:', val, 'vs', value)
if informant == source:
def
>>> forget_value(source):
fahrenheit['set_val']('user',
212)
informant,
connector['val']
= None, None
nonlocal
informant
Fahrenheit
=
212
if name is
not
None:
if
informant
==
source:
Celsius = 100.0
print(name,
'is forgotten')
informant,
connector['val']
= None, None
"""
inform_all_except(source,
'forget',
constraints)
if =name
is not None:
informant
None
connector = {'val':
None,
'is forgotten')
constraints print(name,
='set_val':
[]
set_value,'forget', constraints)
inform_all_except(source,
def set_value(source,
value):
'forget':
forget_value,
connector
= {'val':
None,
nonlocal
informant
'has_val': set_value,
lambda: connector['val'] is not None,
'set_val':
val = connector['val']
'connect':
lambda source: constraints.append(source)}
forget_value,
if val is'forget':
None:
'has_val':
lambda: connector['val']
is not None,
informant,
connector['val']
= source, value
13_constraints.py
'connect':
lambda source: constraints.append(source)}
if name
is not None:
print(name, '=', value)
return connector
inform_all_except(source, 'new_val', constraints)
else:
def inform_all_except(source,
message, constraints):
if val != value:
"""Inform all
constraints of the message,
except
print('Contradiction
detected:',
val,source."""
'vs', value)
Tuesday, September 27, 2011
for c in constraints:
Implementing a Connector
Page 4
14
>>> fahrenheit['set_val']('user', 212)
celsius['forget']('user')
def >>>
constant(connector,
value):
Contradiction
detected:
77.0 vs 212
>>>
celsius['forget']('user')
Celsius
is
forgotten
"""The constraint
that connector = value."""
Celsius
is
forgotten
Fahrenheit
is
forgotten
constraint
= {}
>>>
celsius['forget']('user')
Fahrenheit
is
forgotten
connector['set_val'](constraint,
value)
Celsius is forgotten
>>>
fahrenheit['set_val']('user',
212)
return
constraint
Fahrenheit
is
forgotten
>>>
fahrenheit['set_val']('user',
212)
Fahrenheit
= 212
Fahrenheit
= 212
Celsius
=
100.0
def >>>
make_connector(name=None):
fahrenheit['set_val']('user',
212)
Celsius
= 100.0
"""
"""A connector
between constraints.
Fahrenheit
= 212
"""
informant
None
Celsius
= =
100.0
informant
=
None
constraints
=
[]
>>>
celsius
make_connector('Celsius')
"""
constraints
=
[]
def
value):
>>> set_value(source,
fahrenheit
= make_connector('Fahrenheit')
informant
=
None
def
value):
nonlocal
informant
>>> set_value(source,
make_converter(celsius,
fahrenheit)
constraints
=
[]
nonlocal
informant
= connector['val']
def val
set_value(source,
value):
val
= connector['val']
val
is
None:
>>> if
celsius['set_val']('user',
25)
nonlocal
informant
if
val
is
None:
informant,
connector['val'] = source, value
Celsius
= connector['val']
25
val =
informant,
connector['val']
= source, value
Fahrenheit
=
77.0
if
name
is
not
None:
if val
None:
if is
name
is not None:
print(name,
'=', value) = source, value
informant,
connector['val']
print(name,
'=', value)
>>> fahrenheit['set_val']('user',
212)
inform_all_except(source,
'new_val',
constraints)
if
name
is
not
None:
inform_all_except(source,
'new_val', constraints)
Contradiction
detected: '=',
77.0 value)
vs 212
else:
print(name,
else:
if val != value:
inform_all_except(source,
'new_val', constraints)
if val
!= value:
>>> celsius['forget']('user')
print('Contradiction
detected:',
val, 'vs', value)
else:
print('Contradiction
detected:',
val, 'vs', value)
Celsius
is forgotten
def
forget_value(source):
if val
!= value:
def
forget_value(source):
Fahrenheit
isinformant
forgotten
nonlocal
print('Contradiction
detected:', val, 'vs', value)
nonlocal
informant
if informant == source:
def
if
informant
==connector['val']
source:
>>> forget_value(source):
fahrenheit['set_val']('user',
212)
informant,
= None, None
nonlocal
informant
informant,
connector['val']
= None, None
Fahrenheit
=
212
if name is
not
None:
if
informant
==
source:
name
is not None:
Celsius if
= 100.0
print(name,
'is forgotten')
informant,
connector['val']
= None, None
print(name,
'is forgotten')
"""
inform_all_except(source,
'forget',
constraints)
if =name
is not None:
informant
None
inform_all_except(source,
'forget',
constraints)
connector = {'val':
None,
print(name,
'is
forgotten')
constraints
='set_val':
[]
connector
= {'val':
None,
set_value,'forget', constraints)
inform_all_except(source,
def set_value(source,
value):
'set_val':
set_value,
'forget':
forget_value,
connector
=
{'val':
None,
nonlocal 'forget':
informant forget_value,
'has_val':
lambda: connector['val'] is not None,
'set_val':
set_value,
val = connector['val']
'has_val':
lambda:
connector['val']
is not None,
'connect':
lambda
source:
constraints.append(source)}
'forget':
forget_value,
if val is'connect':
None:
lambda source: constraints.append(source)}
'has_val':
lambda:
connector['val']
is not None,
informant, connector['val']
= source, value
13_constraints.py
'connect':
lambda source: constraints.append(source)}
if name
is not None:
print(name, '=', value)
return connector
inform_all_except(source, 'new_val', constraints)
else:
def inform_all_except(source,
message, constraints):
if val != value:
"""Inform all
constraints of the message,
except
print('Contradiction
detected:',
val,source."""
'vs', value)
Tuesday, September 27, 2011
for c in constraints:
Implementing a Connector
Page 4
14
Contradiction
detected: 77.0 vs 212
>>>
fahrenheit['set_val']('user',
212)
>>>
celsius['forget']('user')
def Contradiction
constant(connector,
value):
detected:
77.0 vs 212
>>>
celsius['forget']('user')
Celsius
is
forgotten
>>>
celsius['forget']('user')
"""The
constraint
that connector = value."""
Celsius
is
forgotten
Fahrenheit
forgotten
constraint
= {}
Celsius
is is
forgotten
>>>
celsius['forget']('user')
Fahrenheit
is
forgotten
connector['set_val'](constraint,
value)
Fahrenheit
is
forgotten
Celsius is forgotten
>>>
fahrenheit['set_val']('user',
212)
return
constraint
Fahrenheit
is
forgotten
>>>
fahrenheit['set_val']('user',
212)
Fahrenheit
= 212
>>>
fahrenheit['set_val']('user',
212)
Fahrenheit
= 212
Celsius
=
100.0
def >>>
make_connector(name=None):
Fahrenheit
= 212
fahrenheit['set_val']('user',
212)
Celsius
= 100.0
"""
"""A connector
between constraints.
Celsius
= 100.0
Fahrenheit
= 212
"""
informant
None
"""
Celsius
= =
100.0
informant
=
None
constraints
=
[]
>>>
celsius
make_connector('Celsius')
informant
=
None
"""
constraints
=
[]
def
value):
>>> set_value(source,
fahrenheit
= make_connector('Fahrenheit')
constraints
=
[]
informant
=
None
def
value):
nonlocal
informant
>>> set_value(source,
make_converter(celsius,
fahrenheit)
def
set_value(source,
value):
constraints
=
[]
nonlocal
informant
= connector['val']
nonlocal
informantvalue):
def val
set_value(source,
val
= connector['val']
if
val
is
None:
>>> val
celsius['set_val']('user',
25)
= connector['val']
nonlocal
informant
if
val
is
None:
informant,
= source, value
Celsius
= connector['val']
25
if val
is None:connector['val']
val
=
informant,
connector['val']
= source, value
Fahrenheit
=
77.0
if
name
is
not
None:
informant,
connector['val']
= source, value
if val
None:
if is
name
is
not
None:
print(name,
'=', value) = source, value
if name
is connector['val']
not None:
informant,
print(name,
'=', value)
>>> fahrenheit['set_val']('user',
212)
inform_all_except(source,
'new_val',
constraints)
print(name,
'=',
value)
if
name
is
not
None:
inform_all_except(source,
'new_val', constraints)
Contradiction
detected: '=',
77.0 value)
vs 212
else:
inform_all_except(source,
'new_val', constraints)
print(name,
else:
if
val
!=
value:
else:
inform_all_except(source,
'new_val', constraints)
if val
!= value:
>>> celsius['forget']('user')
print('Contradiction
detected:',
val, 'vs', value)
if
val
!=
value:
else:
print('Contradiction
detected:',
val, 'vs', value)
Celsius
is forgotten
def
forget_value(source):
print('Contradiction
detected:',
val, 'vs', value)
if val
!= value:
def
forget_value(source):
Fahrenheit
is
forgotten
informant
def nonlocal
forget_value(source):
print('Contradiction
detected:', val, 'vs', value)
nonlocal
informant
if
informant
== source:
informant
def
forget_value(source):
if
informant
==connector['val']
source:
>>> nonlocal
fahrenheit['set_val']('user',
212)
informant,
= None, None
if
informant
==
source:
nonlocal
informant
informant,
connector['val']
= None, None
Fahrenheit
=
212
if name is
not
None:
if
informant
==
source:
informant,
connector['val']
= None, None
name
is not None:
Celsius if
= 100.0
print(name,
'is
forgotten')
informant,
= None, None
if name
is connector['val']
not None:
print(name,
'is forgotten')
"""
inform_all_except(source,
'forget',
constraints)
if =name
is not None:
print(name,
'is forgotten')
informant
None
inform_all_except(source,
'forget',
constraints)
connector
= {'val':
None,
print(name,
'is
forgotten')
inform_all_except(source,
'forget',
constraints)
constraints
='set_val':
[]
connector
= {'val':
None,
set_value,'forget', constraints)
inform_all_except(source,
connector
= {'val':
None,
def set_value(source,
value):
'set_val':
set_value,
'forget':
forget_value,
connector
=
{'val':
None,
'set_val':
set_value,
nonlocal 'forget':
informant
forget_value,
'has_val':forget_value,
lambda: connector['val'] is not None,
'set_val':
set_value,
'forget':
val = connector['val']
'has_val':
lambda:
connector['val']
is not None,
'connect':
lambda
source:
constraints.append(source)}
'forget':
forget_value,
'has_val':
lambda:
connector['val']
is not None,
if val is'connect':
None:
lambda source: constraints.append(source)}
'has_val':
lambda:
connector['val']
is not None,
'connect':
lambda source:
constraints.append(source)}
informant,
connector['val']
= source,
value
13_constraints.py
'connect':
lambda source: constraints.append(source)}
if name
is not None:
print(name, '=', value)
return connector
inform_all_except(source, 'new_val', constraints)
else:
def inform_all_except(source,
message, constraints):
if val != value:
"""Inform all
constraints of the message,
except
print('Contradiction
detected:',
val,source."""
'vs', value)
Tuesday, September 27, 2011
for c in constraints:
Implementing a Connector
Page 4
14