1

私は、Weather Underground からの気象データを分析する pyDatalog プログラムを作成しています (現時点では、私自身と社内の他の人のためのデモとして)。開始時間と終了時間の間の読み取り値を返すカスタム述語リゾルバーを作成しました。

# 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() >= makeTime(t1.id)) and (dt.id.Time.time() <= 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) > makeTime(t1.id):
              op = 'and'
            else:
              op = 'or'
            sqlWhere = "time(Time) >= '%s' %s time(Time) <= '%s'" % (t1.id, op, t2.id)
            for instance in cls.session.query(cls).filter(sqlWhere):
              yield(instance, t1.id, t2.id)

これは、t1 と t2 が特定の値にバインドされている場合にうまく機能します。

:> easterly(X) <= (Reading.WindDirection[X] == 'East')
:> + rideAfter('11:00:00')
:> + rideBefore('15:00:00')
:> goodTime(X) <= rideAfter(Y) & rideBefore(Z) & Reading.timeBetween(X, Y, Z)
:> 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,)]

ただし、別の順序で条件を指定して goodTime ルールを宣言すると (つまり、timeBetween を解決しようとする時点で Y と Z がバインドされていない場合)、空のセットが返されます。

:> atoms('niceTime')
:> niceTime(X) <= Reading.timeBetween(X, Y, Z) & rideAfter(Y) & rideBefore(Z)
<pyDatalog.pyEngine.Clause object at 0x0adfa510>
:> niceTime(X)
[]

これは間違っているようです。2 つのクエリは同じ結果セットを返すはずです。

私の質問は、pyDatalog でこの状況を処理する方法があるかどうかです。必要なことは、 timeBetween 述語がエンジンに何らかの方法で後退し、これを試す前に最初に他のルールを解決しようとするように指示できることだと思いますが、ドキュメントでこれへの参照が見当たりません。

4

1 に答える 1

0

pyDatalog リファレンスには、「pyDatalog ステートメントの順序は重要ではありませんが、本体内のリテラルの順序は重要です」と記載されています。

そうは言っても、バインドされた変数を持つ述語を最初に解決するように pyDatalog を改善することは可能ですが、なぜこれが重要なのかはわかりません。

于 2013-03-04T12:02:40.677 に答える