Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Prolog 基于逻辑编程的共享资源任务调度_Prolog_Clpfd - Fatal编程技术网

Prolog 基于逻辑编程的共享资源任务调度

Prolog 基于逻辑编程的共享资源任务调度,prolog,clpfd,Prolog,Clpfd,你必须安排球员(这需要时间)洗三次不同的澡。获得最佳解决方案。 到目前为止,我的解决方案是: Time 5, 3, 8, 2, 7, 3, 9, 3, 3, 5, 7 如果我运行该程序: use_module(library(clpfd)). shower(S, E, D, Done) :- D = [5, 3, 8, 2, 7, 3, 9, 3, 3, 5, 7], R = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], length(D,

你必须安排球员(这需要时间)洗三次不同的澡。获得最佳解决方案。 到目前为止,我的解决方案是:

Time 5, 3, 8, 2, 7, 3, 9, 3, 3, 5, 7
如果我运行该程序:

use_module(library(clpfd)).

shower(S, E, D, Done) :- 
    D = [5, 3, 8, 2, 7, 3, 9, 3, 3, 5, 7],
    R =  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    length(D, N),
    length(S, N),
    length(E, N),
    domain(S, 0, 100),
    domain(E, 0, 100),
    Done in 0..100,
    ready(E, Done),
    tasks(S, D, E, R, Tasks),
    cumulative(Tasks, [limit(3)]),
    labeling([minimize(Done)], [Done|S]).

tasks([], [], [], [], []).
tasks([S|Ss], [D|Ds], [E|Es], [R|Rs], [T|Ts]) :-
    T = task(S, D, E, R, 0),
    tasks(Ss, Ds, Es, Rs, Ts).

ready([], _).
ready([E|Es], Done) :-
    Done #>= E,
    ready(Es, Done).
它将打印:

?- shower(S,D).
Done是总时间(最长时间),S是每个任务的开始时间,E是每个任务的结束时间,D是任务的持续时间

到目前为止,一切顺利

但现在,我正在与其他事情作斗争。确切地说:

1) 我怎样才能打印哪个播放器正在使用哪个淋浴

2) 我如何限制一个淋浴最多可以运行四名玩家

我对Prolog完全是个新手,这很可能是我在上面写的最后一个程序。到目前为止,我设法做到了这一点,但我需要完成这一点(你猜,这是一项作业)。这是我在这门课上必须做的最后一件事,我以前从未做过任何约束逻辑编程

感谢阅读并最终回复

问得好,+1

这里有一种解决方法:假设您已经找到了一个满足资源限制的计划。然后,您只需描述另外必须包含的内容,以便能够以所需的方式将任务分配给机器

例如:

D = 19,
S = [0,0,0,3,5,5,8,8,11,14,12]
让我们看看在4个时段的总持续时间内有多少独特的解决方案,我们已经知道,由于资源限制,这些解决方案是最小的:

?- shower(Starts, Ends, _, _), distribution(Starts, Ends, Machines).
Starts = [0, 0, 0, 1, 2, 3, 0],
Ends = [3, 3, 1, 2, 3, 4, 4],
Machines = [[0], [0], [0, 1, 2], [0, 3]] .

如果使用
cumulative/[2,3]
约束而不是
cumulative/1
约束,则您将获得“免费”分配的机器

通过使用
累积量
可以为每台机器提供单独的资源容量

这显示了通过使用累积量解决的问题:

distributions([
    [[1],[2,3],[4,5,6],[7]], [[1],[2,4],[3,5,6],[7]], [[1],[2,5],[3,4,6],[7]],
    [[1],[2,6],[3,4,5],[7]], [[1,3],[2],[4,5,6],[7]], [[1,3],[2,4],[5,6],[7]],
    [[1,3],[2,5],[4,6],[7]], [[1,3],[2,6],[4,5],[7]], [[1,4],[2],[3,5,6],[7]],
    [[1,4],[2,3],[5,6],[7]], [[1,4],[2,5],[3,6],[7]], [[1,4],[2,6],[3,5],[7]],
    [[1,5],[2],[3,4,6],[7]], [[1,5],[2,3],[4,6],[7]], [[1,5],[2,4],[3,6],[7]],
    [[1,5],[2,6],[3,4],[7]], [[1,6],[2],[3,4,5],[7]], [[1,6],[2,3],[4,5],[7]],
    [[1,6],[2,4],[3,5],[7]], [[1,6],[2,5],[3,4],[7]]
  ]).
启动后,您将获得:

:- use_module(library(clpfd)).
:- use_module(library(lists)).

go( Ss, Es, Ms) :-

    Ss = [S1, S2, S3, S4,S5,S6,S7], %Starttimes
    Es = [E1, E2, E3, E4,E5,E6,E7], %Endtimeds
    Ms = [M1, M2, M3, M4,M5,M6,M7], %MachineIds

    domain(Ss, 0, 10),
    domain(Es, 0, 10),
    domain(Ms, 1, 4),

    Tasks = [
        task(  S1, 3,  E1,  1, M1 ), 
        task(  S2, 4,  E2,  1, M2 ), 
        task(  S3, 1,  E3,  1, M3 ), 
        task(  S4, 1,  E4,  1, M4 ), 
        task(  S5, 1,  E5,  1, M5 ), 
        task(  S6, 1,  E6,  1, M6 ), 
        task(  S7, 4,  E7,  1, M7 )
    ],

    %All machines has resource capacity = 1
    Machines = [
        machine(  1, 1 ),
        machine(  2, 1 ),
        machine(  3, 1 ), 
        machine(  4, 1 ) 
    ],

    cumulatives(Tasks, Machines, [bound(upper)] ),
    maximum( MaxEndTime, Es ),

    %The variables to lable:
    append([Ms, Ss ], Vars),

    labeling( [minimize(MaxEndTime)], Vars).
如你所见: 任务1已分配给机器1,开始时间为0 任务2分配给机器2,开始时间为0 任务3分配给机器1,开始时间为3 . .

@MortenM

我对您的代码做了一些更改,以使其更适合我的限制(基本上,任务花费的时间不同-就像我在原始规范中所做的,添加第四台机器-更重要的是,任务在时间0开始,而不是时间1)。代码现在看起来:

| ?- go( Ss, Es, Ms) .
Ss = [0,0,3,0,1,2,0],
Es = [3,4,4,1,2,3,4],
Ms = [1,2,1,3,3,3,4] ? 
而当我运行它时,结果(正确的结果)是:

唯一的问题是这个计划没有给我其他的解决方案。这不是唯一的解决方案,但看起来程序只找到了这一个。不知道为什么,也不知道如何改变

非常感谢,你是个救命恩人


注意:在您进行最后更改之前,我发表了这篇文章:)

我已经修改了您的代码,因为我使用的是SWI prolog

?- go(Ss,Es,Ms).
Ss = [0,0,3,3,0,1,0],
Es = [3,3,4,4,1,2,4],
Ms = [1,2,1,2,3,3,4] ? 
也就是说,现在shower/4期望持续时间和机器数量,并输出开始时间和最小化的完工时间(这应该是合适的术语)

有很多可能性,固定下限

1 ?- shower([3, 3, 1, 1, 1, 1, 4], 4, S, D).
S = [0, 0, 0, 1, 2, 3, 0],
D = 4 ;
S = [0, 0, 0, 1, 3, 2, 0],
D = 4 
...
要打印所有:

?- aggregate(count,S^shower([1, 1, 1, 1, 3, 3, 4], 4, S, 4),N).
N = 348.
将机器简单地分配给任务:

?- forall(shower([1, 1, 1, 1, 3, 3, 4], 4, S, 4), writeln(S)).
分配机器(机器、启动、持续时间、甘特图):-
findall(M-[],成员(M,机器),池),
分发(开始、持续时间、池、甘特图)。
分发([]、[]、已分配、已分配)。
分发([S|Ss]、[D|Ds]、池、已分配):-
选择(M-职责、池、减少),
\+繁忙的工作,
长度(职责,L),L<3,
附加(职责,[S/D],更新),
分配(Ss、Ds、[M-更新|减少]、分配)。
忙(S,[Sd/Dd |)]:-S
我知道你把它作为练习留给了我,但我真的不知道怎么做。如果你能给我密码,我将非常感激。我通常不会在stackoverflow上发布与作业相关的问题,但考虑到它对我来说是一门陌生的语言,我感到绝望,而且我没有几个月的时间来掌握它。到目前为止,我工作了将近10天(这是灰烬)。不管你是否回复,我非常感谢你花时间在我身上。干杯如果不是太多的工作,我可以问你怎么做吗?从给出的例子中我不明白。谢谢我已经扩展了我的答案,以包括一个基于原始问题的完整示例。如果您想获得MaxEndTime=4的所有解决方案,您可以在MaxEndTime上发布一个约束,并将[minimize(MaxEndTime)]替换为[],然后使用;为了得到每一个单一的解决方案。做了你提到的更改,并且它正在工作。非常感谢你花这么多时间在我身上!
:- use_module(library(clpfd)).

shower(Durations, NumMachines, Starts, Done) :- 
    sum_list(Durations, Max),
    Done in 0..Max,
    maplist(task(Max, Done), Durations, Tasks, Starts),
    cumulative(Tasks, [limit(NumMachines)]),
    labeling([min(Done)], [Done|Starts]).

task(Max, Done, Duration, task(Start, Duration, End, 1, 0), Start) :-
    MaxStart is Max-Duration,
    Start in 0..MaxStart,
    End #= Start + Duration, %End in 0..Max,
    Done #>= End.
1 ?- shower([3, 3, 1, 1, 1, 1, 4], 4, S, D).
S = [0, 0, 0, 1, 2, 3, 0],
D = 4 ;
S = [0, 0, 0, 1, 3, 2, 0],
D = 4 
...
?- aggregate(count,S^shower([1, 1, 1, 1, 3, 3, 4], 4, S, 4),N).
N = 348.
?- forall(shower([1, 1, 1, 1, 3, 3, 4], 4, S, 4), writeln(S)).
allocate_machines(Machines, Starts, Durations, Gantt) :-
    findall(M-[], member(M, Machines), Pool),
    distribute(Starts, Durations, Pool, Gantt).

distribute([], [], Allocated, Allocated).
distribute([S|Ss], [D|Ds], Pool, Allocated) :-
    select(M-Duties, Pool, Reduced),
    \+ busy(S, Duties),
    length(Duties, L), L < 3,
    append(Duties, [S/D], Updated),
    distribute(Ss, Ds, [M-Updated|Reduced], Allocated).

busy(S, [Sd/Dd|_]) :- S < Sd+Dd, !.
busy(S, [_|Ds]) :- busy(S, Ds).