【问题标题】:Prolog List Represented Graph TraversalProlog 列表表示图遍历
【发布时间】:2023-12-31 18:46:01
【问题描述】:

我正在尝试遍历我在 prolog 中构建的图表。该图表示为以下形式的转换列表: next(FromState, ToState, Symbol) 其中 FromState 和 ToState 是图的节点,表示为:state(Number, IrrelevantVariable)。 Symbol 可以采用许多值,但我只对以 epsilon 作为符号的转换感兴趣。给定一组 StartState,我需要查看哪些转换具有 FromState = StartState 和 Symbol = epsilon。如果这两个条件为真,我会将 ToState 添加到结束 StartStates 并将 FromState 添加到访问节点列表中。我在这样做时遇到了麻烦,并且我当前的程序由于某种原因无法正常工作。任何想法为什么它不起作用?一个问题似乎是当我使用成员谓词查看我是否访问了列表头部的状态时,它最终统一以使成员谓词为真,而不是在第一次调用 espsilon_closure_helper3 时实际检查已访问头部

epsilon_closure_helper3([], [Transitions], Visited).

epsilon_closure_helper3([Head|Tail], Transitions, Visited) :-
  member(Head, Visited)
  ->
  epsilon_closure_helper2(Tail, Transitions, Visited)
  ;
  epsilon_closure_helper2(Head, Transitions, ClosureStates1),
  append(Tail, ClosureStates1, Tail1),
  sort(Tail1, Tail2),
  append(Vistited, [Head], Visited1),
  epsilon_closure_helper3(Tail2, Transitions, Visited1).


epsilon_closure_helper2(State, [], States) :-
  States = [State].

epsilon_closure_helper2(State, Transitions, States) :-
   Transitions = [Head|Tail],
   epsilon_closure_helper2(State, Tail, States1),
   Head = next(A, B, Symbol),
   (
   test_state(State, A, Symbol) -> append(States1, [B], States) ; 
   States = States1
   ).

  test_state(TargetState, State, Symbol) :-
    State = TargetState,
    Symbol = epsilon.

示例输入: epsilon_closure_helper3([state(0, iv)], [next(state(0, iv), state(1, iv), epsilon), next(state(1, iv), state(2, iv), epsilon] , 闭包)。

输出: 闭包 = [state(0, iv), state(1, iv), state(2, iv)]

【问题讨论】:

  • 有什么问题?
  • @DanielLyons 我的程序目前无法运行。任何想法为什么?
  • @DanielLysons 知道如何解决成员谓词的问题,以阻止它在递归的第一次迭代中与已访问列表统一吗?我在上面加了一点解释。
  • 您的输入和输出是否必须与您在问题中的输入和输出完全相同,因为它是一项作业,还是可以更改?我很确定我理解你写的作业,但我觉得你的结构有点混乱。
  • 感兴趣的:Rosetta 代码 - Prolog 中的Floyd-Warshall_algorithm

标签: prolog finite-automata transitive-closure


【解决方案1】:

我知道结构与问题中给出的不一样,但我也知道您是学生,需要理解和学习代码,所以这里有一个与您的结构不同的解决方案,但应该可以帮助您学习和完成作业。

图表来自这个page

transistion(a,b,0).
transistion(a,c,0).
transistion(a,a,1).
transistion(a,b,epsilon).
transistion(b,b,1).
transistion(b,c,epsilon).
transistion(c,c,0).
transistion(c,c,1).

epsilon_closure(End_state,States) :-
    epsilon_closure(End_state,[],States).

epsilon_closure(End_state,States0,States) :-
    bagof([Start,End,Transistion],transistion(Start,End,Transistion),Transitions),
    epsilon_closure_rec(End_state,Transitions,States0,States), !.

epsilon_closure_rec(End,[[Start_state,End,epsilon]|Transitions],States0,States) :-
    \+ memberchk(Start_state,States0),
    epsilon_closure(Start_state,States0,States1),
    epsilon_closure_rec(End,Transitions,States1,States).
epsilon_closure_rec(End,[[_,_,_]|Transitions],States0,States) :-
    epsilon_closure_rec(End,Transitions,States0,States).
% A state is an epsilon transition to itself
epsilon_closure_rec(End_state,[],States0,[End_state|States0]).

请注意,该代码没有任何append/3sort/2=/2->/2

示例运行:

?- epsilon_closure(a,States).
States = [a].

?- epsilon_closure(b,States).
States = [b, a].

?- epsilon_closure(c,States).
States = [c, b, a].

【讨论】:

  • 虽然我还没有尝试过,但可以通过更改 bagof(如 bagof(Start,transistion(Start,End_state,epsilon),Starts))然后从那里重构来进一步优化代码。
  • @jewelltaylor9430 如果您自己解决了这些问题,那么您应该将它们作为附加答案发布,并且 1) 帮助发现此问题的其他人,2) 为自己赚取积分。对一个问题投赞成票可获得 5 分,但对答案投赞成票可获得 10 分。
  • @jewelltaylor9430 您可以做的另一件事是将您的代码发布到Code Review 并获取有关您可以进行哪些更改的指示。
  • 不幸的是,由于它与学校有关,我不希望其他学生能够看到我的答案并可能复制它
  • @jewelltaylor9430 明白,但他们已经可以看到我的答案了。你应该在几个月后发布它。