clorm
clorm copied to clipboard
Refining/constraining predicates based on combination of fields
Is there a mechanism to impose constraints on the predicate sub-class based on combinations of fields?
In the following example, I would like any predicate intance that unifies with the Data class to be such that if the info type is "height"
then the value is of type int
and if the info type is "firstname"
then the value is of type str
. I would like the user3
facts not to unify with Data
. A suitable solution to my problem would let me avoid the additional filtering condition in function print_data
because the querying mechanism should have already filtered out the bad data.
infotype(height;firstname).
person(user1;user2;user3;user4).
data(user1,height,170).
data(user1,firstname,"Anna").
data(user2,height,180).
data(user2,firstname,"Robert").
data(user3,height,"Charlie").
data(user3,firstname,175).
data(user4,firstname,"Richard").
missing(USER,INFO) :- person(USER), infotype(INFO), not data(USER,INFO,_).
#show missing/2.
#script(python)
import clorm
import typing
from clorm.clingo import Control
InfotypeField = clorm.refine_field(clorm.ConstantField,["height","firstname"])
class Data(clorm.Predicate):
user: clorm.ConstantStr
type: clorm.ConstantStr = clorm.field(InfotypeField)
value: typing.Union[int,str]
def print_data(model):
query=model.facts(atoms=True).query(Data)
for d in query.all():
if (d.type == "height" and type(d.value) == int)\
or (d.type == "firstname" and type(d.value) == str):
print(d)
def main(ctrl_):
ctrl = Control(control_=ctrl_, unifier=[Data])
ctrl.ground([("base",[])])
ctrl.solve(on_model=print_data)
#end.
I know that I could turn data
to an arity-2 predicate and turn height
and firstname
into arity-1 function symbols. For example data(user1,height(170)). data(user1,firstname("Anna")).
This would let me define a suitably constrained Data
class directly, but it is undesirable for other reasons (e.g., it messes up the missing/2
rule).