首页 > 解决方案 > 使用序言中的列表打印出动态大小的真值表

问题描述

在给定 2 个前提和 3 个谓词和一个结论的情况下,我创建了一个table用于创建真值表的子句:

bool(true).
bool(false).
% Function for printing out the table
table(P,Q,R,E1,E2,Conclusion):-
    write('P\tQ\tR\t'), 
    write(E1), write('\t'), 
    write(E2), write('\t'), 
    write(Conclusion), 
    write('\tCheck'), nl,
    printValues(P,Q,R,E1,E2,Conclusion).

% Function prints out the truth tables.
printValues(P,Q,R,E1,E2,Conclusion):-
    bool(P), bool(Q), bool(R),  % Get the permutations of all the possible combinations of true and false.
    write(P), format(P), write('\t'), % Print each true/false.
    write(Q), format(Q), write('\t'),
    write(R), format(R), write('\t'),
    writePremise(E1), write('\t'), % Evaluate the premises and write out the result.
    writePremise(E2), write('\t\t'),
    writePremise(Conclusion), write('\t\t'),    % Evaluate the conclusion and write out the result.
    writeCheck(E1, E2, Conclusion). % perform check to see if valid.
% Evalutes a given premise and writes out true or false.
writePremise(E):-
    (E -> write('true'); write('false')).
writeCheck(E1, E2, Conclusion):-
    ((E1,E2 -> (Conclusion -> write('okay'); write('invalid')));
    write('okay')), nl, fail.

给定这样的查询会创建一个真值表:

| ?- table(P,Q,R,and(P,Q),P,my_not(Q)).
P       Q       R       and(_26,_27)    _26     my_not(_27)     Check
true    true    true    true    true            false           invalid
true    true    false   true    true            false           invalid
true    false   true    false   true            true            okay
true    false   false   false   true            true            okay
false   true    true    false   false           false           okay
false   true    false   false   false           false           okay
false   false   true    false   false           true            okay
false   false   false   false   false           true            okay

no

现在我想更改创建一个可以包含两个列表的新子句 - 一个用于谓词,一个用于前提。

它目前看起来像这样:

tableMoreDynamic(Predicates,Premises, Conclusion):-
    writePredicates(Predicates),
    writePremises(Premises),
    writePremise(Conclusion), write('\t\t'),
    writeDynamicCheck(Premises, Conclusion),
    nl, fail.

writePredicates([]):- true.
writePredicates([HEAD|TAIL]):-
    bool(HEAD), 
    write(HEAD) , write('\t'),
    writePredicates(TAIL).

writePremises([]):- true.
writePremises([HEAD|TAIL]):-    
    writePremise(HEAD), write('\t'),
    writePremises(TAIL).

writeDynamicCheck(Premises, Conclusion):-
    (checkList(Premises) -> (Conclusion -> write('okay'); write('invalid')); 
    write('okay')).

checkList([]):- true.
checkList([HEAD|TAIL]):-
    HEAD,
    checkList(TAIL).

它目前的工作原理是打印出前提、结论和有效检查的正确值。然而,由于 writePredicates 子句中的回溯,它不会在每一行打印出所有不同的谓词:

| ?- tableMoreDynamic([P,Q],[P],my_not(P)).
true    true    true    false           invalid
false   true    false           invalid
false   true    false   true            okay
false   false   true            okay

因此,我想知道是否有办法知道您是否在此函数中回溯(以便我们可以重新打印该行上的早期值)。或者也许是一种将 bool 子句映射到列表的方法,这样我们就可以打印出该列表。为代码墙道歉。谢谢

标签: prolog

解决方案


因此,我想知道是否有办法知道您是否在此函数中回溯(以便我们可以重新打印该行上的早期值)。

可能有一些巧妙的技巧可以做到这一点,但对于对问题的令人困惑的解释来说,这将是一个非常令人困惑的解决方案。问题本身很简单:

或者也许是一种将 bool 子句映射到列表的方法,这样我们就可以打印出该列表。

是的。而且您已经知道该怎么做,因为writePredicates无论如何这就是您在里面做的事情!您唯一缺少的是,您应该在开始打印之前对完整的布尔列表进行“标记”,而不是交错标记和打印单个元素。

所以你只需要这样:

bools([]).
bools([Bool | Bools]) :-
    bool(Bool),
    bools(Bools).

tableMoreDynamic(Predicates,Premises, Conclusion):-
    bools(Predicates),
    writePredicates(Predicates),
    ...

保持其余代码不变。(你可以删除bool里面的调用writePredicates,它不再做任何事情。)

这将打印完整的表格:

?- tableMoreDynamic([P,Q],[P],my_not(P)).
true    true    true    false       invalid
true    false   true    false       invalid
false   true    false   true        okay
false   false   false   true        okay
false.

如果您不想自己写出整个递归bools,如果您的 Prolog 提供了一些高阶谓词,则可能会有更短的解决方案。例如,在 SWI-Prolog 中,您可以调用:

maplist(bool, Predicates)

根本不需要定义bools谓词。


推荐阅读