Note that there are some explanatory texts on larger screens.

plurals
  1. POpyDatalog: handling unbound variables in a custom predicate
    text
    copied!<p>I'm writing a pyDatalog program to analyse weather data from Weather Underground (just as a demo for myself and others in the company at the moment). I have written a custom predicate resolver which returns readings between a start and end time:</p> <pre><code># class for the reading table. class Reading(Base): __table__ = Table('reading', Base.metadata, autoload = True, autoload_with = engine) def __repr__(self): return str(self.Time) # predicate to resolve 'timeBetween(X, Y, Z)' statements # matches items as X where the time of day is between Y and Z (inclusive). # if Y is later than Z, it returns the items not between Z and Y (exclusive). # TODO - make it work where t1 and t2 are not bound. # somehow needs to tell the engine to try somewhere else first. @classmethod def _pyD_timeBetween3(cls, dt, t1, t2): if dt.is_const(): # dt is already known if t1.is_const() and t2.is_const(): if (dt.id.Time.time() &gt;= makeTime(t1.id)) and (dt.id.Time.time() &lt;= makeTime(t2.id)): yield (dt.id, t1.id, t2.id) else: # dt is an unbound variable if t1.is_const() and t2.is_const(): if makeTime(t2.id) &gt; makeTime(t1.id): op = 'and' else: op = 'or' sqlWhere = "time(Time) &gt;= '%s' %s time(Time) &lt;= '%s'" % (t1.id, op, t2.id) for instance in cls.session.query(cls).filter(sqlWhere): yield(instance, t1.id, t2.id) </code></pre> <p>This works fine in the case where t1 and t2 are bound to specific values:</p> <pre><code>:&gt; easterly(X) &lt;= (Reading.WindDirection[X] == 'East') :&gt; + rideAfter('11:00:00') :&gt; + rideBefore('15:00:00') :&gt; goodTime(X) &lt;= rideAfter(Y) &amp; rideBefore(Z) &amp; Reading.timeBetween(X, Y, Z) :&gt; goodTime(X) [(2013-02-19 11:25:00,), (2013-02-19 12:45:00,), (2013-02-19 12:50:00,), (2013-02-19 13:25:00,), (2013-02-19 14:30:00,), (2013-02-19 15:00:00,), (2013-02-19 13:35:00,), (2013-02-19 13:50:00,), (2013-02-19 12:20:00,), (2013-02-19 12:35:00,), (2013-02-19 14:05:00,), (2013-02-19 11:20:00,), (2013-02-19 11:50:00,), (2013-02-19 13:15:00,), (2013-02-19 14:55:00,), (2013-02-19 12:00:00,), (2013-02-19 13:00:00,), (2013-02-19 14:20:00,), (2013-02-19 14:15:00,), (2013-02-19 13:10:00,), (2013-02-19 12:10:00,), (2013-02-19 14:45:00,), (2013-02-19 14:35:00,), (2013-02-19 13:20:00,), (2013-02-19 11:10:00,), (2013-02-19 13:05:00,), (2013-02-19 12:55:00,), (2013-02-19 14:10:00,), (2013-02-19 13:45:00,), (2013-02-19 13:55:00,), (2013-02-19 11:05:00,), (2013-02-19 12:25:00,), (2013-02-19 14:00:00,), (2013-02-19 12:05:00,), (2013-02-19 12:40:00,), (2013-02-19 14:40:00,), (2013-02-19 11:00:00,), (2013-02-19 11:15:00,), (2013-02-19 11:30:00,), (2013-02-19 11:45:00,), (2013-02-19 13:40:00,), (2013-02-19 11:55:00,), (2013-02-19 14:25:00,), (2013-02-19 13:30:00,), (2013-02-19 12:30:00,), (2013-02-19 12:15:00,), (2013-02-19 11:40:00,), (2013-02-19 14:50:00,), (2013-02-19 11:35:00,)] </code></pre> <p>However if I declare the goodTime rule with the conditions in the other order (i.e. where Y and Z are unbound at the point it tries to resolve timeBetween), it returns an empty set:</p> <pre><code>:&gt; atoms('niceTime') :&gt; niceTime(X) &lt;= Reading.timeBetween(X, Y, Z) &amp; rideAfter(Y) &amp; rideBefore(Z) &lt;pyDatalog.pyEngine.Clause object at 0x0adfa510&gt; :&gt; niceTime(X) [] </code></pre> <p>This seems wrong - the two queries should return the same set of results.</p> <p>My question is whether there is a way of handling this situation in pyDatalog? I think what needs to happen is that the timeBetween predicate should be able to tell the engine to back off somehow and try to resolve other rules first before trying this one, but I can't see any reference to this in the docs.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload