<s> from . util import intersection , index <EOL> from . core import conde , reify , isvar <EOL> from toolz import merge <EOL> class Relation ( object ) : <EOL> _id = <NUM_LIT:0> <EOL> def __init__ ( self , name = None ) : <EOL> self . facts = set ( ) <EOL> self . index = dict ( ) <EOL> if not name : <EOL> name = "<STR_LIT>" % Relation . _id <EOL> Relation . _id += <NUM_LIT:1> <EOL> self . name = name <EOL> def add_fact ( self , * inputs ) : <EOL> """<STR_LIT>""" <EOL> fact = tuple ( inputs ) <EOL> self . facts . add ( fact ) <EOL> for key in enumerate ( inputs ) : <EOL> if key not in self . index : <EOL> self . index [ key ] = set ( ) <EOL> self . index [ key ] . add ( fact ) <EOL> def __call__ ( self , * args ) : <EOL> def f ( s ) : <EOL> args2 = reify ( args , s ) <EOL> subsets = [ self . index [ key ] for key in enumerate ( args ) <EOL> if key in self . index ] <EOL> if subsets : <EOL> facts = intersection ( * sorted ( subsets , key = len ) ) <EOL> else : <EOL> facts = self . facts <EOL> varinds = [ i for i , arg in enumerate ( args2 ) if isvar ( arg ) ] <EOL> valinds = [ i for i , arg in enumerate ( args2 ) if not isvar ( arg ) ] <EOL> vars = index ( args2 , varinds ) <EOL> vals = index ( args2 , valinds ) <EOL> assert not any ( var in s for var in vars ) <EOL> return ( merge ( dict ( zip ( vars , index ( fact , varinds ) ) ) , s ) <EOL> for fact in self . facts <EOL> if vals == index ( fact , valinds ) ) <EOL> return f <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" + self . name <EOL> __repr__ = __str__ <EOL> def fact ( rel , * args ) : <EOL> """<STR_LIT>""" <EOL> rel . add_fact ( * args ) <EOL> def facts ( rel , * lists ) : <EOL> """<STR_LIT>""" <EOL> for l in lists : <EOL> fact ( rel , * l ) </s>
