我有以下问题要解决。

我有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(C​​olA,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:

这是我在示例序言代码中尝试使用的数据的直观表示:

matrix - 如何在Prolog中找到列表的最佳组合-LMLPHP

最佳答案

我给您提供一些构建基块来解决此任务。

首先,让我们决定对有理数字进行推理。请避免混乱的浮点数,这将给您带来无尽的麻烦。

要在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/3findall/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/3keysort/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/

10-11 17:41