Search code examples
databaseperformancesumanswer-set-programmingclingo

ASP Clingo performance problem with sum-method


my current code aims to sum some values from a given database and select a combination of breakfast, lunch and dinner food. under the little database for testing you can find my code that is running and finding 42 answers for my given intervals. then i wanted to calculate also the other columns (proteis, fat, carbohydrates) as you can see directly below. but i am having some huge performance issues. the code is just not running (i waited one hour but no results showed up) is there any may to simplify the sum-chain sum_prot_fat_carb_bf /+lu /+di ? so that my program will finally run....im running out of ideas with this programming language. i would be glad if you could help me out. best regards

sum_prot_fat_carb_bf(BFPROT,BFFAT,BFCARB) :- BFPROT = #sum{ PROT : food_bf(_,_,PROT,_,_,_), selected_bf(NAME,CAL,PROT,FAT,CARB,VEGN) },
                                             BFFAT  = #sum{ FAT  : food_bf(_,_,_,FAT,_,_) , selected_bf(NAME,CAL,PROT,FAT,CARB,VEGN) },
                                             BFCARB = #sum{ CARB : food_bf(_,_,_,_,CARB,_), selected_bf(NAME,CAL,PROT,FAT,CARB,VEGN) }.

sum_prot_fat_carb_lu(LUPROT,LUFAT,LUCARB) :- LUPROT = #sum{ PROT : food_lu(_,_,PROT,_,_,_), selected_lu(NAME,CAL,PROT,FAT,CARB,VEGN) },
                                             LUFAT  = #sum{ FAT  : food_lu(_,_,_,FAT,_,_) , selected_lu(NAME,CAL,PROT,FAT,CARB,VEGN) },
                                             LUCARB = #sum{ CARB : food_lu(_,_,_,_,CARB,_), selected_lu(NAME,CAL,PROT,FAT,CARB,VEGN) }.

sum_prot_fat_carb_di(DIPROT,DIFAT,DICARB) :- DIPROT = #sum{ PROT : food_di(_,_,PROT,_,_,_), selected_di(NAME,CAL,PROT,FAT,CARB,VEGN) },
                                             DIFAT  = #sum{ FAT  : food_di(_,_,_,FAT,_,_) , selected_di(NAME,CAL,PROT,FAT,CARB,VEGN) },
                                             DICARB = #sum{ CARB : food_di(_,_,_,_,CARB,_), selected_di(NAME,CAL,PROT,FAT,CARB,VEGN) }.

rate_prot_fat_carb(TOTALPROT,TOTALFAT,TOTALCARB)     :- sum_prot_fat_carb_bf(BFPROT,BFFAT,BFCARB),
                                                        sum_prot_fat_carb_lu(LUPROT,LUFAT,LUCARB),
                                                        sum_prot_fat_carb_di(DIPROT,DIFAT,DICARB),
                                                        TOTALPROT = BFPROT+LUPROT+DIPROT,
                                                        TOTALFAT = BFFAT+LUFAT+DIFAT,
                                                        TOTALCARB = BFCARB+LUCARB+DICARB.

#show sum_cal_total/1.
#show rate_prot_fat_carb/3. 

%database - (different reciepes for each breakfast(bf), lunch(lu), and dinner(di)) 
%    name                           cal     prot    fat     carb    veg/~veg  
food_bf(haferflocken_milch,         116,    5,      4,      15,     v).
food_bf(kaesebrot,                  260,    11,     16,     17,     v).
food_bf(wurstbrot,                  270,    6,      14,     20,     n).
food_bf(omelett,                    154,    11,     12,     1,      v).
food_bf(obstsalat,                  53,     1,      0,      12,     v).
food_bf(studentenfutter,            485,    3,      27,     45,     v).
food_bf(nutellabrot,                199,    3,      6,      32,     v).

food_lu(codfish_with_vegetables,    380,    31,     16,     24,     n).
food_lu(chicken_with_rice,          393,    52,     13,     15,     n).
food_lu(rice_with_tofu,             397,    15,     9,      61,     v).
food_lu(mustard_eggs_with_potatos,  360,    19,     17,     31,     v).
food_lu(linguine_with_pumpkin_sauce,334,    10,     9,      51,     v).
food_lu(pork_filet_with_beans,      392,    34,     15,     27,     n).
food_lu(bulgur_salad,               400,    14,     11,     58,     v).

food_di(filled_eggplant,            372,    11,     17,     37,     v).
food_di(chickpea_curry,             419,    13,     25,     32,     v).
food_di(pork_filets_with_carrots,   400,    36,     16,     25,     n).
food_di(kale_hotpot,                222,    7,      10,     24,     v).
food_di(tarte_flambee,              320,    12,     12,     38,     n).
food_di(fish_meatball,              375,    30,     23,     9,      n).
food_di(caper_spaghetti,            346,    14,     7,      54,     v).

% check all combinations of food
{ selected_bf(NAME,CAL,PROT,FAT,CARB,VEGN) } :- food_bf(NAME,CAL,PROT,FAT,CARB,VEGN).
{ selected_lu(NAME,CAL,PROT,FAT,CARB,VEGN) } :- food_lu(NAME,CAL,PROT,FAT,CARB,VEGN).
{ selected_di(NAME,CAL,PROT,FAT,CARB,VEGN) } :- food_di(NAME,CAL,PROT,FAT,CARB,VEGN).

% sum the calories of breakfast, lunch and dinner
sum_cal_bf(BFCAL) :- BFCAL = #sum{ CAL : food_bf(_,CAL,_,_,_,_), selected_bf(NAME,CAL,PROT,FAT,CARB,VEGN) }.
sum_cal_lu(LUCAL) :- LUCAL = #sum{ CAL : food_lu(_,CAL,_,_,_,_), selected_lu(NAME,CAL,PROT,FAT,CARB,VEGN) }.
sum_cal_di(DICAL) :- DICAL = #sum{ CAL : food_di(_,CAL,_,_,_,_), selected_di(NAME,CAL,PROT,FAT,CARB,VEGN) }.
sum_cal_total(TOTALCAL) :- sum_cal_bf(BFCAL), sum_cal_lu(LUCAL), sum_cal_di(DICAL), TOTALCAL = BFCAL+LUCAL+DICAL.

:- sum_cal_bf(BFCAL), BFCAL>=575. 
:- sum_cal_bf(BFCAL), BFCAL<375.
:- sum_cal_lu(LUCAL), LUCAL>=1075.
:- sum_cal_lu(LUCAL), LUCAL<875.
:- sum_cal_di(DICAL), DICAL>=975.
:- sum_cal_di(DICAL), DICAL<775.
:- sum_cal_total(TOTALCAL), TOTALCAL>=2350.
:- sum_cal_total(TOTALCAL), TOTALCAL<2250.

#show sum_cal_total/1. ```

**clingo 0 fp.lp**
clingo version 5.4.0
Reading from fp.lp
Solving...
Answer: 1
sum_cal_total(2348)
Answer: 2
sum_cal_total(2338)
Answer: 3
sum_cal_total(2279)
Answer: 4
sum_cal_total(2334)
Answer: 5
sum_cal_total(2289)
Answer: 6
sum_cal_total(2332)
Answer: 7
sum_cal_total(2271)
Answer: 8
sum_cal_total(2342)
Answer: 9
sum_cal_total(2334)
Answer: 10
sum_cal_total(2251)
Answer: 11
sum_cal_total(2304)
Answer: 12
sum_cal_total(2324)
Answer: 13
sum_cal_total(2294)
Answer: 14
sum_cal_total(2337)
Answer: 15
sum_cal_total(2254)
Answer: 16
sum_cal_total(2327)
Answer: 17
sum_cal_total(2307)
Answer: 18
sum_cal_total(2297)
Answer: 19
sum_cal_total(2292)
Answer: 20
sum_cal_total(2345)
Answer: 21
sum_cal_total(2282)
Answer: 22
sum_cal_total(2337)
Answer: 23
sum_cal_total(2335)
Answer: 24
sum_cal_total(2274)
Answer: 25
sum_cal_total(2279)
Answer: 26
sum_cal_total(2317)
Answer: 27
sum_cal_total(2332)
Answer: 28
sum_cal_total(2269)
Answer: 29
sum_cal_total(2322)
Answer: 30
sum_cal_total(2307)
Answer: 31
sum_cal_total(2299)
Answer: 32
sum_cal_total(2318)
Answer: 33
sum_cal_total(2273)
Answer: 34
sum_cal_total(2308)
Answer: 35
sum_cal_total(2334)
Answer: 36
sum_cal_total(2263)
Answer: 37
sum_cal_total(2318)
Answer: 38
sum_cal_total(2288)
Answer: 39
sum_cal_total(2326)
Answer: 40
sum_cal_total(2278)
Answer: 41
sum_cal_total(2316)
Answer: 42
sum_cal_total(2255)
SATISFIABLE

Models       : 42
Calls        : 1
Time         : 2.500s (Solving: 0.04s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 2.469s

Solution

  • What are the constriaints at the end of the program? Are they for testing or they are really used in the problem? What about constraints on PROT,FAT and CARB? Since you can get the 42 answers with constraints on CAL, I suggest use these 42 answers as the input for solving PROT, FAT and CAB. You might as well #show selected_bf/lu/di, and use them as input. For instance:

    selected_di(filled_eggplant) selected_di(chickpea_curry) selected_lu(codfish_with_vegetables) selected_lu(mustard_eggs_with_potatos) selected_lu(linguine_with_pumpkin_sauce) selected_bf(omelett) selected_bf(obstsalat) selected_bf(nutellabrot) sum_cal_total(2271)

    is one of the 42 answers. Then the program for PROT/FAT/CAB can be:

    sum_prot_fat_carb_bf(BFPROT,BFFAT,BFCARB) :- BFPROT = #sum{ PROT : food_bf(NAME,_,PROT,_,_,_), selected_bf(NAME) },
                                                BFFAT  = #sum{ FAT  : food_bf(NAME,_,_,FAT,_,_) , selected_bf(NAME) },
                                                BFCARB = #sum{ CARB : food_bf(NAME,_,_,_,CARB,_), selected_bf(NAME) }.
    
    sum_prot_fat_carb_lu(LUPROT,LUFAT,LUCARB) :- LUPROT = #sum{ PROT : food_lu(NAME,_,PROT,_,_,_), selected_lu(NAME) },
                                                LUFAT  = #sum{ FAT  : food_lu(NAME,_,_,FAT,_,_) , selected_lu(NAME) },
                                                LUCARB = #sum{ CARB : food_lu(NAME,_,_,_,CARB,_), selected_lu(NAME) }.
    
    sum_prot_fat_carb_di(DIPROT,DIFAT,DICARB) :- DIPROT = #sum{ PROT : food_di(NAME,_,PROT,_,_,_), selected_di(NAME) },
                                                DIFAT  = #sum{ FAT  : food_di(NAME,_,_,FAT,_,_) , selected_di(NAME) },
                                                DICARB = #sum{ CARB : food_di(NAME,_,_,_,CARB,_), selected_di(NAME) }.
    
    rate_prot_fat_carb(TOTALPROT,TOTALFAT,TOTALCARB)     :- sum_prot_fat_carb_bf(BFPROT,BFFAT,BFCARB),
                                                            sum_prot_fat_carb_lu(LUPROT,LUFAT,LUCARB),
                                                            sum_prot_fat_carb_di(DIPROT,DIFAT,DICARB),
                                                            TOTALPROT = BFPROT+LUPROT+DIPROT,
                                                            TOTALFAT = BFFAT+LUFAT+DIFAT,
                                                            TOTALCARB = BFCARB+LUCARB+DICARB.
    
    
    %database - (different reciepes for each breakfast(bf), lunch(lu), and dinner(di)) 
    %    name                           cal     prot    fat     carb    veg/~veg  
    food_bf(haferflocken_milch,         116,    5,      4,      15,     v).
    food_bf(kaesebrot,                  260,    11,     16,     17,     v).
    food_bf(wurstbrot,                  270,    6,      14,     20,     n).
    food_bf(omelett,                    154,    11,     12,     1,      v).
    food_bf(obstsalat,                  53,     1,      0,      12,     v).
    food_bf(studentenfutter,            485,    3,      27,     45,     v).
    food_bf(nutellabrot,                199,    3,      6,      32,     v).
    
    food_lu(codfish_with_vegetables,    380,    31,     16,     24,     n).
    food_lu(chicken_with_rice,          393,    52,     13,     15,     n).
    food_lu(rice_with_tofu,             397,    15,     9,      61,     v).
    food_lu(mustard_eggs_with_potatos,  360,    19,     17,     31,     v).
    food_lu(linguine_with_pumpkin_sauce,334,    10,     9,      51,     v).
    food_lu(pork_filet_with_beans,      392,    34,     15,     27,     n).
    food_lu(bulgur_salad,               400,    14,     11,     58,     v).
    
    food_di(filled_eggplant,            372,    11,     17,     37,     v).
    food_di(chickpea_curry,             419,    13,     25,     32,     v).
    food_di(pork_filets_with_carrots,   400,    36,     16,     25,     n).
    food_di(kale_hotpot,                222,    7,      10,     24,     v).
    food_di(tarte_flambee,              320,    12,     12,     38,     n).
    food_di(fish_meatball,              375,    30,     23,     9,      n).
    food_di(caper_spaghetti,            346,    14,     7,      54,     v).
    
    %fact base
    selected_di(filled_eggplant). 
    selected_di(chickpea_curry). 
    selected_lu(codfish_with_vegetables). 
    selected_lu(mustard_eggs_with_potatos). 
    selected_lu(linguine_with_pumpkin_sauce). 
    selected_bf(omelett).
    selected_bf(obstsalat). 
    selected_bf(nutellabrot). 
    

    And we get:

    Answer: 1

    rate_prot_fat_carb(99,102,220)

    SATISFIABLE

    You might try use script file like python and use for loop to get the result of the 42 answers and write them into the second program file as fact base.

    Here I suggest remove other variables in selected_bf(NAME,CAL,PROT,FAT,CARB,VEGN) because if NAME is ensured, CAL,PROT,FAT,CARB,VEGN can be read from database food_bf(NAME,...), this might also takes time for clingo to do the grouding.

    For getting the answer in single program, I suggest you give more constraints on PORT/FAT/CAB.