我正在尝试使用LogicBlox作为Datalog求解器的功能。我遇到性能问题,我认为我在使用LB错误,因为它的行为就好像在实现所有关系(带有魔术集的Datalog求解器无法做到)。
正如我所说,我可能没有按预期使用LB,但这是我的测试。我想创建一些二进制关系e(x,y)的传递闭包c(x,y)。出于测试目的,我使用创建为简单循环的e进行游戏,即我将LB的e(i,(i + 1)%1000)添加为0≤i <1000。
当我仅对from0(x)<-c(0,x)感兴趣时,则不需要实际实现c,而魔术设置方法将创建谓词c_ {bound,free}(x,y)并从from0(0)计算,然后从from0(1)导出,依此类推。整个操作大约需要1000步。
如果我用程序做例子:
e(x,y) -> int(x), int(y).
// fill e with data
c(x,y) -> int(x), int(y).
c(x,y) <- e(x,y) ; c(x,z),e(z,y).
from0(x) <- c(0,x).
然后,很明显,我正在生成c的物化版本,并且c将包含所有对元素;因此,整个操作大约要花费1000 ^ 2的时间(当我运行查询时,我发现计算实际上需要一些时间)。
在文档中,LogicBlox允许将谓词定义为“派生”,但对于c来说,由于c自身递归,因此似乎不可能。
现在,我还尝试在查询或exec块中使用“本地谓词”定义此可传递闭包,但没有成功。我尝试过的示例:
query '
_c(x,y)->int(x),int(y).
_c(x,y) <- e(x,y) ; e(x,z),_c(z,y).
_(x) <- _c(0,x).'
显然,在此示例中,我可以手动优化查询并定义一个块:
f0(x)->int(x).
f0(y)<- e(0,y) ; f0(x),e(x,y).
但是,如果我正确理解LB,应该有一种方法可以将优化留给LB。
答案 0 :(得分:2)
我不确定您如何定义“数据日志求解器”,但这也许是 更好地将LogicBlox理解为使用源自数据日志的数据库 语言作为查询语言。
您注意到,LogicBlox不会自动应用任何类型的 优化类似于魔术集。此外,不幸的是 命名为“ Derived”的派生类型在您的情况下不起作用,因为它避免了 通过内联实现。但是,不可能内联 递归谓词。
如果您使用的平台版本早于4.4.9,则可以, 不幸的是,您唯一的选择是手动执行某种方式的 魔术可以改变您的逻辑。
如果您使用的是LogicBlox 4.4.9或更高版本,我们添加了一个新 派生类型“ OnDemand”将执行您想要的操作。它将重写 内部谓词的规则,这样唯一的“需求” 计算元组。这与古典魔术不太一样 设置重写,类似于所谓的“需求” 转换”中的最新文献(请参见 http://doi.acm.org/10.1145/1836089.1836094。
但是,这仍然需要您的示例进行一些小的更改。必须为谓词的所有键(而不是值)自变量提供一个“需求”。因此,您需要将示例重写为
e(x,y) -> int(x), int(y).
e(x, int:mod[x + 1,1000]) <- int:range(0,1000,1,x).
nodes(x) <- e(x, _); e(_, x).
c(x,y) -> int(x), int(y).
c(x,y) <- e(x,y); c(x,z), e(z,y).
//lang:derivationType[`c]="OnDemand".
from0(x) <- c(0,x), nodes(x).
取消注释以上行将应用转换。这产生 在笔记本电脑上运行时,速度提高了7倍。
另一个例子是斐波那契函数
fib[i]=f -> int(i), int(f).
lang:derivationType[`fib]="OnDemand".
fib[0]=0.
fib[1]=1.
fib[i]=f1+f2 <- i >= 2, fib[i-1]=f1, fib[i-2]=f2.
我们还使用了“ OnDemand”谓词来实现更详尽的描述 关系和函数,例如CYK解析或评估lambda演算。