我有以下问题要解决。
我有2个(或更多)矩阵; a和b。
每个矩阵都有列,行和值(利润)。
我想使用Prolog从2种不同的矩阵中找到2列的组合,这些组合将为我带来最多的正利润。
即矩阵A中的ColumnX +矩阵B中的ColumnY,然后计算结果列中具有正数的值的数量。即我添加同一行中的值。
我将代码放在下面到目前为止已经尝试过的代码(及其链接)上,但是我的函数 count_profits(ColA,ColB,P)没有返回预期的结果。以下查询应返回 P = 2 ,但它返回 P = 1 。
count_profits(66,65.5,P).
现在,我为每个要使用的矩阵提供列索引。最终,我希望有一个名为 best_profit(ColA,ColB)的函数,该函数应该给我矩阵A的列和矩阵B的列,合并后得到的阳性结果最多。根据我的测试数据,如果我是正确的话,这应该导致 ColA = 66 和 ColB = 65.5 。
https://pastebin.com/rKG8twE1
% Data sets
% a(Column, Row, Profit)
% b(Column, Row, Profit)
a(65, 66, -0.82).
a(65, 65.5, -1.32).
a(65, 65, -1.82).
a(65.5, 66, -1.07).
a(65.5, 65.5, -1.57).
a(65.5, 65, -1.57).
a(66, 66, -1.3).
a(66, 65.5, -1.3).
a(66, 65, -1.3).
b(65, 66, -1).
b(65, 65.5, -0.5).
b(65, 65, 1.72).
b(65.5, 66, -0.5).
b(65.5, 65.5, 1.48).
b(65.5, 65, 1.48).
b(66, 66, 1.25).
b(66, 65.5, 1.25).
b(66, 65, 1.25).
min_row(Row) :-
a(Col, Row, _),
\+ (a(_,Row2,_), Row2 < Row),!.
max_row(Row) :-
a(Col, Row, _),
\+ (a(_,Row2,_), Row2 > Row),!.
is_profit(ColA, ColB, Row, P) :-
a(ColA, Row, Profit1),
b(ColB, Row, Profit2),
Profit is Profit1 + Profit2,
( Profit > 0 -> P is 1 ; P is 0),!.
count_profits(ColA, ColB, Row1, P) :-
max_row(Row),
Row1 =:= Row,
is_profit(ColA, ColB, Row1, P).
count_profits(ColA, ColB, Row1, P) :-
a(ColA,Row2,_),
Row2 > Row1,
count_profits(ColA, ColB, Row2, P2),
is_profit(ColA, ColB, Row1, P1),
P is P1+P2.
count_profits(ColA, ColB, P) :-
min_row(Row1),
count_profits(ColA, ColB, Row1, P),!.
更新1:
这是我在示例序言代码中尝试使用的数据的直观表示:
最佳答案
我给您提供一些构建基块来解决此任务。
首先,让我们决定对有理数字进行推理。请避免混乱的浮点数,这将给您带来无尽的麻烦。
要在Prolog中推理有理数,请查看 CLP(Q),约束对有理数的求解。
就您而言,您从涉及浮点数的矩阵开始。让我们首先为它们使用更方便的表示形式,例如:
矩阵(a,[[-0.82,-1.07,-1.3],
[-1.32,-1.57,-1.3],
[-1.82,-1.57,-1.3]]。
矩阵(b,[[-1,-0.5,1.25],
[-0.5,1.48,1.25],
[1.72,1.48,1.25]]。
您可以使用setof/3
和findall/3
之类的所有解决方案谓词将您当前的演示文稿转换为此类行列表。
如前所述,我们应该首先将其转换为有理数,以消除后续步骤中的许多问题。顺便说一下,我们无法保证即使您当前拥有的数字也能准确显示!另外,在您的情况下,我们主要对列感兴趣,因此我们可以转置矩阵,也可以使用rationalize/1
获取有理数列的列表:
:-use_module(library(clpq))。
:-use_module(library(clpfd))。
to_rational(F,R):-R是合理化的(F)。
Rational_columns(Name,Cols):-
矩阵(名称,行),
转置(行,Cols0),
maplist(maplist(to_rational),Cols0,Cols)。
让我们看看目前为止:
?-Rational_columns(a,Cols)。
Cols = [[-41 rdiv 50,-33 rdiv 25,-91 rdiv 50],[-107 rdiv 100,-157 rdiv 100,-157 rdiv 100],[-13 rdiv 10,-13 rdiv 10,-13 rdiv 10]]。
继续,让我们定义列的加法意味着什么:
column_column_plus(As,Bs,Ps):-
maplist(添加,As,Bs,Ps)。
加法运算(A,B,Sum):-{Sum = A + B}。
这使用CLP(Q)约束来定义列表的元素逐项添加。可以在所有方向使用!
使用这些构建块,我们已经可以描述我们感兴趣的列的组合:
组合编号(A-B,N):-
Rational_columns(a,ACs),
合理列(b,BCs),
成员(A,AC),
成员(B,BC),
column_column_plus(A,B,Ps),
包括( Gs0 = [_ | _],
长度(Gs0,N)。
在回溯中可以找到解决方案:
α-combination_number(Cs,N)。
Cs = [-41 rdiv 50,-33 rdiv 25,-91 rdiv 50]-[-1 rdiv 2、37 rdiv 25、37 rdiv 25],
N = 1;
Cs = [-41 rdiv 50,-33 rdiv 25,-91 rdiv 50]-[5 rdiv 4,5 rdiv 4,5 rdiv 4],
N = 1;
Cs = [-107 rdiv 100,-157 rdiv 100,-157 rdiv 100]-[-1,-1 rdiv 2、43 rdiv 25],
N = 1;
Cs = [-107 rdiv 100,-157 rdiv 100,-157 rdiv 100]-[5 rdiv 4,5 rdiv 4,5 rdiv 4],
N = 1;
Cs = [-13 rdiv 10,-13 rdiv 10,-13 rdiv 10]-[-1,-1 rdiv 2、43 rdiv 25],
N = 1;
Cs = [-13 rdiv 10,-13 rdiv 10,-13 rdiv 10]-[-1 rdiv 2、37 rdiv 25、37 rdiv 25],
N = 2;
假。
要选择最佳组合,可以将findall/3
与keysort/2
结合使用:
?-findall(N-Cs,组合编号(Cs,N),NCs0),
keysort(NCs0,NCs),
最后(NC,最佳)。
屈服:
最佳= 2-([[-13 rdiv 10,-13 rdiv 10,-13 rdiv 10]-[-1 rdiv 2,37 rdiv 25,37 rdiv 25])。
关于matrix - 如何在Prolog中找到列表的最佳组合,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43542284/