我正在使用Prolog为冠军联赛淘汰赛写一个自动抽奖计划。代码如下。
/* ChampionLeagueAutoDraw_KnockOutRound */
%% by Zach X.
% some "nice" prolog settings
%
:- set_prolog_flag( prompt_alternatives_on, groundness ).
:- set_prolog_flag(toplevel_print_options, [quoted(true),
portray(true), attributes(portray), max_depth(999), priority(699)]).
%% Dynamic database for team candidates.
:- dynamic team/5.
%% team(name, nationality, rank, group, bool_taken).
team(BayernMunich, Germany, 1, E, 0).
team(AtleticoMadird, Spain, 1, A, 0).
team(RealMadrid, Spain, 1, B, 0).
team(Monaco, France, 1, C, 0).
team(Dortmund, Germany, 1, D, 0).
team(Barcelona, Spain, 1, F, 0).
team(Chelsea, England, 1, G, 0).
team(Porto, Portugal, 1, H, 0).
team(Juventus, Italy, 2, A, 0).
team(Basel, Switzerland, 2, B, 0).
team(Leverkusen, Germany, 2, C, 0).
team(Arsenal, England, 2, D, 0).
team(ManCity, England, 2, E, 0).
team(PSG, France, 2, F, 0).
team(Schalke04, Germany, 2, G, 0).
team(Shaktar, Ukraine, 2, H, 0).
%% Pick the first team ready for matching.
%% When a team is picked, the bool_taken flag is set to 1.
pick(X) :-
team(X,N,R,G,0),
retract(team(X,_,_,_,_)),
assert(team(X,N,R,G,1)),
match(X,_).
%% Rules for match():
%% Teams from the same country do not meet;
%% Teams from the same group do not meet;
%% Teams with the same rank do not meet;
match(X,Y) :-
team(X,Nx,Rx,Gx,1),
team(Y,Ny,Ry,Gy,0),
X\==Y,
Nx\==Ny,
Rx\==Ry,
Gx\==Gy,
retract(team(Y,_,_,_,_)),
assert(team(Y,Ny,Ry,Gy,1)),
nl,write(X), write(' V.S '), write(Y).
%% Pick all 8 matches (pretty sure this is not the right way to
% write it...)
autodraw :-
pick(_),pick(_),pick(_),pick(_),pick(_),pick(_),pick(_),pick(_).
两个问题:
当我编译它时,16个团队数据库中有大量的单例警告,为什么?
当调用autodraw时,它应该打印出每个匹配中团队的名称,而是打印出如下内容:
_G2032 V.S _G2033
为什么?
另外,我知道在自动绘制中调用8个选择谓词不是正确的方法,我想确保所有8个匹配全部制作并立即打印。还有更好的选择吗?
===========更新============
/* ChampionLeagueAutoDraw_KnockOutRound */
%% by Zach X.
% some "nice" prolog settings
%
:- set_prolog_flag( prompt_alternatives_on, groundness ).
:- set_prolog_flag(toplevel_print_options, [quoted(true),
portray(true), attributes(portray), max_depth(999), priority(699)]).
% Dynamic database for team candidates.
:- dynamic team/5.
% team(name, nationality, rank, group, bool_taken).
team(bayernMunich, germany, 1, e, 0).
team(atleticoMadird, spain, 1, a, 0).
team(realMadrid, spain, 1, b, 0).
team(monaco, france, 1, c, 0).
team(dortmund, germany, 1, d, 0).
team(barcelona, spain, 1, f, 0).
team(chelsea, england, 1, g, 0).
team(porto, portugal, 1, h, 0).
team(leverkusen, germany, 2, c, 0).
team(basel, switzerland, 2, b, 0).
team(juventus, italy, 2, a, 0).
team(arsenal, england, 2, d, 0).
team(manCity, england, 2, e, 0).
team(psg, france, 2, f, 0).
team(schalke04, germany, 2, g, 0).
team(shaktar, ukraine, 2, h, 0).
%% Rules for match():
%% Teams from the same country do not meet;
%% Teams from the same group do not meet;
%% Teams with the same rank do not meet;
match(X,Y) :-
X\==Y,
team(X,Nx,Rx,Gx,Bx),
team(Y,Ny,Ry,Gy,By),
Bx==0,
By==0,
Nx\==Ny,
Rx\==Ry,
Gx\==Gy,
retract(team(X,Nx,Rx,Gx,Bx)),
assert(team(X,Nx,Rx,Gx,1)),
retract(team(Y,Ny,Ry,Gy,By)),
assert(team(Y,Ny,Ry,Gy,1)),
nl,write(X), write(' V.S '), write(Y).
%% Pick all 8 matches (Correct way to do it?)
autodraw :-
match(_,_), fail.
在删除了pick()并且直接调用匹配(调用pick是多余的)之后,自动绘制现在几乎按照我的预期工作,除了它只生成一个可能的结果。我希望得到所有可能的8对结果。现在它只打印一个固定的列表,因为在开始时输入的团队的顺序。例如,'bayernMunich'总是与'basel'配对,因为'bayernMunich'是第一支进入Rank == 1的球队,而basel是第一支可以与拜仁合法匹配的球队(勒沃库森来自德国)。 / p>
如何修改此程序以便程序可以为我提供所有可能的组合?看起来我需要一种让prolog随机访问团队数据库而不是按顺序搜索的方法。我怎么能这样做?
答案 0 :(得分:1)
最好将逻辑与IO分开,并避免在不需要时产生副作用(如断言/撤回)。它们可能使您的程序很难调试。
match(X,Y) :-
team(X,Nx,Rx,Gx,_Bx),
team(Y,Ny,Ry,Gy,_By),
Nx\==Ny,
Rx\==Ry,
Gx\==Gy.
autodraw :-
forall(match(X,Y), (nl, write(X), write(' V.S '), write(Y))).
team / 5的最后一个论点似乎致力于跟踪'加入',我认为它没用。
要打印格式化输出,格式化通常比多次写入更合适:
autodraw :-
forall(match(X,Y), format('~n~w V.S ~w', [X,Y])).