Producer#
#class Producer
Instances of the Producer class act as variables in a rule or query context.
When the context is evaluated, all possible values for the variable are produced.
Instead of constructing Producer instances directly, they are returned as the result of various operations.
The Producer class is the base class for different kinds of producers, including:
Instance, returned when you call aType.InstanceProperty, returned when you access a property of an object.Expression, returned as the result of an operation on a producer, such as a mathematical or Boolean expression, or an aggregation.
Methods#
The following methods support mathematical operations on producers:
| Name | Description | Returns |
|---|---|---|
__add__() | Supports the + operator between producers and other values. | Expression |
__sub__() | Supports the - operator between producers and other values. | Expression |
__mul__() | Supports the * operator between producers and other values. | Expression |
__truediv__() | Supports the / operator between producers and other values. | Expression |
__floordiv__() | Supports the // operator between producers and other values. | Expression |
__pow__() | Supports the ** operator between producers and other values. | Expression |
__mod__() | Supports the % operator between producers and other values. | Expression |
The following methods support comparison operations on producers:
| Name | Description | Returns |
|---|---|---|
__eq__() | Supports == comparison between producers and other values. | Expression |
__ne__() | Supports != comparison between producers and other values. | Expression |
__ge__() | Supports >= comparison between producers and other values. | Expression |
__gt__() | Supports > comparison between producers and other values. | Expression |
__le__() | Supports <= comparison between producers and other values. | Expression |
__lt__() | Supports < comparison between producers and other values. | Expression |
Instances of Producer support arbitrary attribute access
and can be used as a context manager
in a with statement:
| Name | Description | Returns |
|---|---|---|
__getattribute__() | Get a property of an object. | InstanceProperty |
__enter__() | Enter the producer’s context. | None |
__exit__() | Exit the producer’s context. | None |
Example#
The key idea behind the Producer class is that it is used to represent a variable
in a rule or query context:
#import relationalai as rai
# Create a model named 'people' with Person and Adult types.
model = rai.Model("people")
Person = model.Type("Person")
Adult = model.Type("Adult")
# Add some people to the model.
with model.rule():
# Type.add() returns an Instance, which is a producer.
alice = Person.add(name="Alice", age=8)
bob = Person.add(name="Bob", age=36)
# Instance producers have a .set() method for setting properties and
# additional types on objects.
bob.set(parent_of=alice)
# Create a rule that sets the Adult type on each person whose age is at least 18.
with model.rule():
# Calling a type returns an Instance producer.
person = Person() # person produces Person objects.
# person.age returns an InstanceProperty, which is also a producer.
# Comparing the age to 18 returns an Expression, yet another producer.
person.age >= 18 # Filter to people who are 18 or older.
person.set(Adult) # Set the adult type on the people who pass the filter.
You can think of the rule as executing once for each Person object in the model.
Each line in the rule describes a step in a pipeline that the objects produced by person pass through:
personProduces aPersonobject.person.age >= 18only lets through objects with an age of 18 or more.person.set(Adult)sets theAdulttype on the objects that pass through.
The object for Alice never reaches the last step because her age is less than 18.
But the object for Bob does reach the last step, and the Adult type is set on it.
Multiple producers may be mixed in the same rule or query:
## Get pairs of people where the first person is younger than the second.
with model.query() as select:
person1, person2 = Person(), Person()
person1.age < person2.age
response = select(person1.name, person2.name)
print(response.results)
# Output:
# name1 name2
# 0 Alice Bob
Both person1 and person2 produce Person objects.
The query is evaluated for each pair of possible values for person1 and person2, of which there are four:
- Alice and Alice
- Alice and Bob
- Bob and Alice
- Bob and Bob
Only the pair (Alice, Bob) passes through the comparison and into select() since Alice is 8 and Bob is 36.
Producers can be used as context managers.
This is especially useful for Expression producers, which can be used to create a subcontext that applies to a subset of objects:
#Minor = model.Type("Minor")
with model.rule():
person = Person()
# If the person's age is less than 18, set the Minor type.
with person.age < 18:
person.set(Minor)
# If the person's age is at least 18, set the Adult type.
with person.age >= 18
person.set(Adult)
Thinking of the rule as a pipeline, the with statement creates a subcontext
whose contents only apply to objects for which the Expression is true,
but doesn’t block objects from passing through to the rest of the rule.
For example, the Alice object passes through the first with statement and gets the Minor type set on it since she is 8.
Her object still passes through to the second with statement, but the Adult type is not set on her because the expression is false.
Bob, on the other hand, passes through the first with statement without setting the Minor type, but the Adult type is set on him in the second with statement.