首页 > 解决方案 > Prolog收回不止一个事实,然后断言

问题描述

:- dynamic flat/3.
addr('Nollendorfstr',5).
addr('Nollendorfstr',14).
addr('Nollendorfstr',18).
addr('Maxplanckstr',2).

flat([16,12,4],400.35, addr('Nollendorfstr',14)).
flat([14,13,4],380.00, addr('Nollendorfstr',18)).
flat([20,18,4,5],650.80, addr('Nollendorfstr',5)).
flat([9,17,19,20],870.70, addr('Maxplanckstr',2)).

对于每个平面,我们有三个参数。所以flat(array of rooms, price, address)

changeprice(Street):-
   retract(flat(Rooms,Price,addr(Street,Num))),
   Newprice is Price - (Price / 10),                         
   asserta(flat(Rooms,Newprice,addr(Street,Num))).

我想更改这条街上所有公寓的价格。

所以当我把它放在那里时,changeprice('Nollendorfstr'). 它只会改变其中一个。我怎样才能改变所有这些?

标签: prolog

解决方案


您可以使用失败驱动的循环(它的名称来自在处理一个项目后使用显式失败以回溯到处理下一个项目):

changeprice(Street) :-
    retract(flat(Rooms,Price,addr(Street,Num))),
    Newprice is Price - (Price / 10),                      
    asserta(flat(Rooms,Newprice,addr(Street,Num))),
    fail.
changeprice(_).

或事实上的标准forall/2元谓词(其中第一个参数可以解释为由第二个参数验证的候选解决方案的生成器,测试部分):

changeprice(Street) :-
    forall(
        retract(flat(Rooms,Price,addr(Street,Num))),
        (   Newprice is Price - (Price / 10),                      
            asserta(flat(Rooms,Newprice,addr(Street,Num)))
        )
    ).

在这种特殊情况下,两种解决方案都是等效的。但请注意,失败驱动的循环和forall/2调用具有不同的语义。故障驱动的循环可以掩盖意外故障。但是forall/2如果第二个参数失败,调用将失败而不是成功。


推荐阅读