如何在SWI-prolog中覆盖字典(键 - 值对列表)?

时间:2018-02-27 22:12:38

标签: dictionary prolog

这是我的问题:

我有一个类似于此的key-val对字典(实际代码中有更多对):

args = [(score, 0), (multiplier, 1), (reward, 0), (prior_prob, 1)].

我定义了两个函数来处理字典:

% look up the Val of a Key in a Dict 
lookup(Key,Dict,Val):-
    member((Key,Val), Dict).

% update(Key, NewVal, Dict, NewDict) updates the value of a key in the dict

update(Key,Val,[],[(Key,Val)]).               % Add new pair to current dict
update(Key,Val,[(Key,_)|Rest], [(Key,Val)|Rest]):- !. % Found the key and update the value
update(Key,Val,[KV|Rest],[KV|Result]) :-      % recursively look for the key 
    update(Key,Val,Rest,Result).

我需要字典的原因是我有许多需要这些参数的函数(例如"得分","乘数"等等)。这些函数相互调用并传递参数。并非每个函数都需要所有参数,但其中许多函数都是,并且有些参数比其他函数更新。所以这个字典基本上是一个包含在需要经常传递和覆盖的包的参数列表。例如,没有字典,我可能有这个(虚构的)函数:

calculate('cond1', 'cond2', S0, S1, Multiplier, Reward, Prior):-
    getscore('cond1', 'cond2', S0, S1, Multiplier, Reward, Prior).

getscore('cond1', 'cond2', S0, S1, Multiplier, Reward, Prior):-
    reward('cond1', 'cond2', Reward),  % look up rewards based on conditions
    MultNew is Multiplier*Prior,       % calculate the new multiplier
    S1 is (S0+Rewards*MultNew).        % update score

但是有了字典,我可以:

calculate2('cond1', 'cond2', Args, NewArgs):-
    getscore2('cond1', 'cond2', Args, NewArgs).

getscore2('cond1', 'cond2', Args, NewArgs):-
    reward('cond1', 'cond2', Reward), 
    lookup(prior, Args, Prior),
    lookup(multiplier, Args, Mult),
    update(reward, Reward, Args),
    MultNew is Multiplier*Prior,
    update(multiplier, MultNew, Args, NewArgs),
    update(score, S0+Reward*MultNew, Args, NewArgs).

(第二种方式看起来比第一种方式更长更慢,但实际上并非所有的args都需要一次更新或查找,因为以后添加更多参数会更灵活,我认为拥有字典会更好.Plz让我知道是否有更好的设计选择)当我运行时,我得到:

No permission to modify static procedure `(=)/2'

在我定义字典args的行号。

我尝试了:-dynamic(arg/0, update/4, lookup/3).,这没用。

(=)/ 2是什么意思?如何允许覆盖Prolog中的字典?提前谢谢!

1 个答案:

答案 0 :(得分:1)

以下是针对您的问题的(可能的)解决方案(在 SWI-Prolog 中)。 该词典使用 SWI-Prolog 嵌入式数据库(非持久性)

实现

它是一组术语链。条款与用户提供的密钥

相关联
%key `small int` or `atom`-
lookup(Key, Value) :-
    current_key( Key ),
    recorded( Key, Value, _ ) -> 
    true
    ;
    recordz(Key, Value).

update( Key, OldValue, NewValue ) :-
    same_term( OldValue, NewValue ) -> 
    true
    ;
    (current_key( Key ),
    recorded( Key, OldValue, Ref ase( Ref )
        ; 
        true,
    recordz( Key, NewValue, _ )).

修改 您还可以使用全局变量,可回溯和非可回溯。 例如 nb_setval/2, nb_getval/2

所以你的第一个陈述可能如下所示

:- nb_setval(score, 0),    
    nb_setval(multiplier, 1), 
    nb_setval(reward, 0), 
    nb_setval(prior_prob, 1),

    nb_setval(args, [score, multiplier, reward, prior_prob]).

<强> EDIT2

=/2是谓词调用Prolog的统一程序unify/2。 如果您的意思是在字典覆盖下重新分配变量组,您可以使用以下任一解决方案:

<强> EDIT3

%我认为它应该是这样的:

update_dict(Dict):- 
    update(args, Dict). 

update(Key, Val):- 
    (nb_getval(Key, OldVal), 
    exists(Val, OldVal)) -> true; 
    nb_setval(Key, Val). 

update(Key, Val, Dict):- 
    update_dict( Dict ), 
    update( Key, Val ). 

exists(Val, OldVal) :-
    nonvar(OldVal),
    same_term(Val, OldVal).

%======================================   
lookup_dict( Dict):- 
    lookup(args, Dict). 

lookup(Key, Val):- 
    nb_getval(Key, OldVal),
    exists( Val, OldVal ) -> 
       true
        ; 
        nb_setval(Key, Val).

lookup( Key, Val, Dict ):- 
     lookup_dict( Dict ), 
     lookup( Key, Val ).