如何通过findall将Prolog中solution的输出转换为列表的列表?
解决Prolog中收集解为列表的列表问题
你的核心问题在于原有的solution/2谓词最后用了false,导致它永远无法成功(每次匹配到有效解后,执行writeln(T)就会触发false让谓词失败),所以findall/3根本收集不到任何结果。咱们可以把解的验证逻辑和输出/收集逻辑分开来处理:
步骤1:拆分验证与输出逻辑
先把判断一个T是否是有效解的逻辑抽成单独的谓词,这样不管是输出还是收集都能复用:
% 验证T是否是G的有效解 valid_solution(G, T) :- comb(G, T), allPos(T, G), not(cycle(T)).
然后原来的输出功能可以改成一个专门的输出谓词(保持你原来的逐行输出效果):
% 逐行输出所有有效解 print_solutions(G) :- valid_solution(G, T), writeln(T), false. % 触发回溯,输出下一个解
调用?- print_solutions([a-b,a-c,a-d,b-c,c-d]).就能得到和之前一样的逐行输出结果。
步骤2:收集所有解为列表的列表
现在用findall/3直接调用valid_solution/2,就能把所有有效解收集成一个列表的列表了:
findall_call(Input, Solutions) :- findall(T, valid_solution(Input, T), Solutions).
调用?- findall_call([a-b,a-c,a-d,b-c,c-d], X0).,X0就会是你想要的所有解组成的嵌套列表,比如[[c-d], [b-c], [b-c,c-d], ...]这样的形式。
为什么原来的写法不行?
原solution/2里的false是为了强制回溯输出所有解,但这也导致solution(Input, X0)这个目标永远不会成功(每次匹配到解后都会因为false失败),而findall/3只会收集那些让目标成功的X0值,所以自然拿不到结果。拆分逻辑后,valid_solution/2会在找到有效解时成功,findall就能正确收集所有成功的T了。
内容的提问来源于stack exchange,提问作者user7303261
相关产品推荐
相关产品推荐

