Pyke 逻辑编程入门(12):“方案”


“方案”与程序自动生成


明白了反向推理是怎么回事,自动生成程序也就不难了。

把“方案”加入反向推理规则

用到的办法,是把 Python 的函数弄成反向推理规则。这些函数是在 .krb 文件中,每个规则结尾处的 with 子句处。它们不影响规则对目标的证明,而是一起形成“流程图”,返回相应的模式变量,其中约束的值,是证明最终目标的证据。

示例

有个小小的规则库,用于实现银行帐户之间的转帐。转出、转入帐户采取以下形式之一:

  • (户名, 帐户类型)
    • 这是本行帐户。
    • 例如:('bruce', 'checking')。
  • (银行名称,户名, 帐户类型)
    • 这是其他银行的帐户。
    • 例如:('my_other_bank', 'bruce', 'checking').

其中至少有一个帐户,必须是本银行的。

下面是规则库的示例:

1  transfer1
 2      use transfer($from_acct, $to_acct) taking (amount)
 3      when
 4          withdraw($from_acct)
 5              $$(amount)
 6          deposit($to_acct)
 7              $$(amount)

 8  transfer2
 9      use transfer($from_acct, $to_acct) taking (amount)
10      when
11          transfer_ach($from_acct, $to_acct)
12              $$(amount)

13  withdraw
14      use withdraw(($who, $acct_type)) taking (amount)
15      with
16          print "withdraw", amount, "from", $who, $acct_type

17  deposit
18      use deposit(($who, $acct_type)) taking (amount)
19      with
20          print "deposit", amount, "to", $who, $acct_type

21  transfer_ach1
22      use transfer_ach($from_acct, ($bank, $who, $acct_type)) taking (amount)
23      when
24          withdraw($from_acct)
25              $$(amount)
26          deposit((central_accts, ach_send_acct))
27              $$(amount)
28      with
29          print "send", amount, "to bank", $bank, "acct", $who, $acct_type

30  transfer_ach2
31      use transfer_ach($from_acct, $to_acct) taking (amount)
32      when
33          get_ach($from_acct)
34              $$(amount)
35          withdraw((central_accts, ach_recv_acct))
36              $$(amount)
37          deposit($to_acct)
38              $$(amount)

39  get_ach
40      use get_ach(($bank, $who, $acct_type)) taking (amount)
41      with
42          print "get", amount, "from bank", $bank, "acct", $who, $acct_type

示例中方案函数的产生

其中每一规则,都会产生一个“方案函数”。方案函数的名称与对应规则的名称相同,例如,第一个规则产生的方案函数,叫做“transfer1”。

示例中,第一个规则产生的方案函数,内容包括第5行和第7行。事实withdraw($from_acct)和deposit($to_acct)证明为真(匹配)后,会分别产生方案函数。按照第2行taking子句的规定,函数会有个“amount”参数。

示例第13行规则“withdraw”产生的方案函数,只有在 with 子句里的第 16 行语句。其中模式变量 $who 和 $acct_type,它们的值会在终极目标证明后,得到相应的约束(赋值)。

第21行规则产生的方案函数“transfer_ach1”,内容有3行,其中2行在 when 子句里,另外一句是在 with 子句的第 29 行。从语法上看,这些语句在同一级别的块块里,但在 .krb 文件中不是这样。

运行示例

“方案”是目标证明过程中产生的副产品:

>>> from pyke import knowledge_engine
>>> engine = knowledge_engine.engine(__file__)
>>> engine.activate('plan_example')
>>> no_vars, plan1 = /
...   engine.prove_1_goal(
...     'plan_example.transfer((bruce, checking), (bruce, savings))')

现在,plan1 成了转账程序,用以把 bruce 帐户里的支票,转成存款。plan1 也从规则名,变成了函数名:

Plan1

可以像调用标准函数那样,用参数向定义在 taking 子句中的变量传值。taking 子句,处于终极目标规则(transfer)里。

>>> plan1(100)
withdraw 100 from bruce checking
deposit 100 to bruce savings

这段程序可以多次调用:

>>> plan1(50)
withdraw 50 from bruce checking
deposit 50 to bruce savings

注意输出的字符串:obruce, checking 和 savings。它们是模式变量,经过调制置入函数调用图的方案中。

再来写第二个程序:

>>> no_vars, plan2 = /
...   engine.prove_1_goal(
...     'plan_example.transfer((bruce, checking), '
...                           '(my_other_bank, bruce, savings))')

现在,plan2 这个程序,用以把 bruce 在其他银行的支票,转为本银行的存款:

Plan2

它的运行与 plan1 相同,但产生的结果不一样:

>>> plan2(200)
withdraw 200 from bruce checking
deposit 200 to central_accts ach_send_acct
send 200 to bank my_other_bank acct bruce savings

最后一个用例:

>>> no_vars, plan3 = /
...   engine.prove_1_goal(
...     'plan_example.transfer((my_other_bank, bruce, checking), '
...                           '(bruce, savings))')
>>> plan3(150)
get 150 from bank my_other_bank acct bruce checking
withdraw 150 from central_accts ach_recv_acct
deposit 150 to bruce savings

程序 paln3 是这样的:

Plan3

注意,在程序 plan2 和 plan3 里,函数 transfer2 调用两个不同的函数 transfer_ach1 和 transfer_ach2。这说明根据推理规则不同,可以选择不同函数。还有,在 plan3 生成后,plan2 仍可运行使用;它俩都能调用成功,并根据函数 transfer2 设置的初始值,产生不同结果。

结论

可见,把 Pyke 和 Python 函数自动整合到程序中,非常容易!

允许在 Python 函数中,用模式变量设置数据,供 Pyke 匹配操作时使用。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值