【发布时间】:2016-05-31 03:01:46
【问题描述】:
所以,这是一个我已经尝试解决了一段时间的练习。我得到一个像[a-b,b-c] 这样的输入列表,它们是节点和连接节点的弧。条件是:
节点需要有一个唯一的关联编号,从1到N,
并且弧需要有一个唯一的关联数字,从 1 到 N-1,并且该数字必须是减去弧连接的节点的结果。
所以答案是:
EnumNodos = [enum(3,a), enum(1,b), enum(2,c)],
EnumArcos = [enum(2,a‐b), enum(1,b‐c)]
因此,由于我无法为此提出算法,也不知道是否有算法,所以我想,我可以尝试每一种可能性,因为我知道如果输入是正确的,那样我迟早会得到它。
我发现了一个 prolog 排列的例子,如果我给它一些输入列表,它会给出它的排列。然后(在控制台中),如果我点击 ';'它给了我另一个,依此类推。我正在尝试自己包含该代码。
我还没有完成,但我会提供一些帮助,特别是我尝试置换选项的“循环”方法。我真的不知道您会怎么说,在序言中,如果此操作失败,请尝试另一种新的排列,与之前尝试过的每个排列不同(不提供';'作为解决方案的输入。因为有很多排列正在进行要失败,我想检查它是否失败,如果失败,请尝试另一个。
EDIT 所以我刚刚发现了 setof... 我一直在尝试它,但我认为我仍然缺少一个关键部分。截至目前,我觉得我可以通过以下方式获得我需要的所有可能性的列表:setof(Out,perm(ListaEnum, SalidaPerm),X),
但是我仍然对失败然后重试的想法有疑问。到目前为止,我的想法是:我得到 X 结果,然后像对待任何列表一样进行旅行。我检查它是否有唯一的数字等等,如果没有,我想继续旅行那个X。所以我会努力失败而不是成功?我应该这样做吗??
% enumerate(CONNECTIONS_IN, NODES_OUT, ARCS_OUT)
%TODO query example of call: enumerate([a-b,b-c], EnumNodos, EnumArcos).
enumerate(C, EnumNodos, EnumArcos) :-
enum_nodes(C, [], NodeListUnique, [], PermNodes, 1),
loopPerm(C, NodeListUnique, EnumArcos, PermNodes, SalidaPerm).
% enum_nodes(CONNECTIONS_IN, NODES_IN, NODES_OUT, IDS_IN, IDS_OUT, START_ID)
% Fills up NODES_OUT with unique nodes, and PERMOUT with IDS. New IDs start at START_ID...
enum_nodes([], N, N, M, M, _).
enum_nodes([A-B | T], N, NOUT, M, PERMOUT, ID) :-
ensure_node(A, N, NTMP1, M, PERMNODESOUTA, ID, ID1),
ensure_node(B, NTMP1, NTMP2, PERMNODESOUTA, PERMNODESOUTB, ID1, ID2),
enum_nodes(T, NTMP2, NOUT, PERMNODESOUTB, PERMOUT, ID2).
% ensure_node(NODE, NODES_IN, NODES_OUT,IDS_IN, IDS_OUT, ID_IN, ID_OUT)
% Adds enum(ID_IN, NODE) to NODES_IN to produce NODES_OUT if NODE does not already exist in NODES_IN
ensure_node(NODE, NODES_IN, NODES_IN, PermNodesNOVALENin, PermNodesNOVALENin, ID, ID) :-
member(NODE, NODES_IN), !.
ensure_node(NODE, NODES_IN, [NODE | NODES_IN], PERMIN, [ID_IN|PERMIN], ID_IN, ID_OUT) :-
ID_OUT is ID_IN + 1.
%At this point I have a list of unique nodes and a list of IDs for said nodes, and I want to start calculatin permutations of this two lists until I find one that works.
loopPerm(C, NodeListUnique, EnumArcos, PermNodes, SalidaPerm):-
crearEnum(NodeListUnique, PermNodes, ListaEnum),
perm(ListaEnum, SalidaPerm),
create_arcs(C, SalidaPerm, []),
%%here is where code stops working properly
loopPerm(C, EnumNodos, EnumArcos, PermNodes, SalidaPerm).
%crear_enum(NODES_IN, IDS_IN, enumLISTout)
%creates a list of enums to be permuted, TODO the idea here is that each call will change the list, so if it failed before, it should try a new one.
crearEnum([], [], []).
crearEnum([H1 | NodeListUnique], [H2| PermNodes], [enum(H2,H1)|Salida]):-
crearEnum(NodeListUnique, PermNodes, Salida).
% create_arcs(CONNECTIONS_IN, NODES_IN, ARCS_OUT).
% Create arcs - makes a list of arc(NODE_ID_1, NODE_ID_2)...
create_arcs([], _, _).
create_arcs([A-B | T], NODES, LISTARCS) :-
ensure_arcs(A,B,NODES, LISTARCS, LISTARCS2),
create_arcs(T, NODES, LISTARCS2).
%ensure_arcs(NODE_A, NODE_B, NODELIST, LISTARCSIN, LISTARCSOUT)
%builds a list of arcs TODO works WRONG when arc already was in the input. It should fail, but it just checks that is a member and moves on. So basically it works when arcs are new, because they are added properly, but not when arcs were already found (and as per the exercise it should fail and try another permutation).
ensure_arcs(A,B,NODES, LISTARCSIN, LISTARCSIN):-
member(enum(NODE_ID_A, A), NODES),
member(enum(NODE_ID_B, B), NODES),
REMAINDER is abs(NODE_ID_A-NODE_ID_B),
member(enum(REMAINDER,_), LISTARCSIN), !.
ensure_arcs(A,B,NODES, LISTARCSIN,[enum(REMAINDER, A-B) | LISTARCSIN]):-
member(enum(NODE_ID_A, A), NODES),
member(enum(NODE_ID_B, B), NODES),
REMAINDER is abs(NODE_ID_A-NODE_ID_B).
perm([H|T], Perm) :-
perm(T, SP),
insert(H, SP, Perm).
perm([], []).
insert(X, T, [X|T]).
insert(X, [H|T], [H|NT]) :-
insert(X, T, NT).
以下是我手工编写的其他一些示例,以备不时之需。我也想道歉,因为我对代码一点也不满意,只是我需要继续前进,而不是修复我确定是痛苦的错误(但我无法真正修复,截至现在,我需要很长时间才能获得任何有效的代码,即使几乎没有)。
6a
5 4
1b 2e
2 3
3c 5f
1
4d
EnumNodos = [enum(6,a), enum(1,b), enum(2,e), enum(3,c), enum(5,f), enum(4,d)],
EnumArcos = [enum(5,a‐b), enum(4,a-e), enum(3,e-f), , enum(2,b-c), enum(1,c-d)]
5a
4 3
1b 2e
1 2
3c 4f
EnumNodos = [enum(5,a), enum(1,b), enum(2,e), enum(3,c), enum(4,f)],
EnumArcos = [enum(4,a‐b), enum(3,a-e), enum(1,b-c), , enum(2,e-f)]
5a
4 3
1b 2e
2
3c
1
4d
【问题讨论】: