How can I speed up this program? It is a coin hold

2019-08-03 16:02发布

So this is a program where it calculates the fewest number of coins to carry with certain values on these coins. The program works, but it's way too slow... When you replace the length of the values 7 or less, it works... But 8 or above, it's really, really slow. Is there any way to speed up this program?

% LIBRARIES NEEDED FOR FUNCTION TO WORK
:- lib(ic).
:- lib(ic_global).
:- lib(branch_and_bound).

questionSix(Values, Coins) :-
    init_vars(Values, Coins),
    coin_cons(Values, Coins, Pockets),
    clever_cons(Values, Coins),
    Min #= sum(Coins),
    minimize((labeling(Values), labeling(Coins), check(Pockets)), Min).

init_vars(Values, Coins) :-
    length(Values, 8),
    occurrences(5, Values, 1),
    Values :: 1..99,
    increasing(Values),
    length(Coins, 8),
    Coins :: 0..99.

increasing(List) :-
    ( fromto(List, [This, Next | Rest], [Next | Rest], [_])
    do
        This #< Next
    ).

clever_cons(Values, Coins) :-
    ( fromto(Values, [V1 | NV], NV, []), 
      fromto(Coins, [N1 | NN], NN, [])
     do
        ( NV = [V2 | _]
            -> N1*V1 #< V2;
            N1*V1 #< 100
        )
    ).

coin_cons(Values, Coins, Pockets) :-
    ( for(Price, 1, 99),
    foreach(CoinsforPrice, Pockets),
    param(Coins, Values)
    do
        price_cons(Price, Coins, Values, CoinsforPrice)
    ).

price_cons(Price, Coins, Values, CoinsforPrice) :-
    ( foreach(V, Values), foreach(C, CoinsforPrice), foreach(Coin, Coins),
    foreach(Prod, ProdList)
    do
        Prod = V*C,
        0 #=< C,
        C #=< Coin
    ),
    Price #= sum(ProdList).

check(Pockets) :-
    ( foreach(CoinsforPrice, Pockets)
    do
        once(labeling(CoinsforPrice))
    ).

Any help is appreciated! Thanks!

1条回答
够拽才男人
2楼-- · 2019-08-03 16:07

First observation: if you put labeling(Coins) before labeling(Values), the time improves dramatically. Roughly speaking, that's because in this problem number of coins is much more important than values of coins.

Second observation: you can't get less than 7 coins no matter how many values you allow. That's because if you run your program with 7 values, you can see that every coin is used once in the optimal solution. So if you have more than 7 values, only 7 of them will be used, or the number of coins will be more than 7 and the solution will be not optimal.

With these observations in mind, you can just change

minimize((labeling(Values), labeling(Coins), check(Pockets)), Min).

to

bb_min((labeling(Coins), labeling(Values), check(Pockets)), Min, bb_options{from:7}).
查看更多
登录 后发表回答