Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Newbie and first difficulties

109 views
Skip to first unread message

lassenza73

unread,
May 12, 2024, 6:14:45 AM5/12/24
to Picat
Hi all,
i'm trying to setup the following model , it works fine until i try to maxime the number of empty boxes , where am i doing wrong? and how to remove equivalent solutions ?

import sat, util.
main =>
    MaxEl =300, %  max number of element in a box
    MinEl=60, %  min number of element in a box
    Articles = [ ['A', 1000],   %code article , number of elements
                 ['B', 400],
                 ['C', 150],
                 ['D', 500],
                 ['E', 500],
                 ['F', 500],
                 ['G', 500],
                 ['H', 500],
                 ['I', 100] ],
                 
    N=Articles.length,
    ArticlesT=Articles.transpose(),
    NumArticles=sum([ArticlesT[2,I] : I in 1.. N]),
    println(NumArticles),
    MaxBoxes=ceiling(NumArticles / MinEl),
    println(MaxBoxes),
    Boxes = new_array(MaxBoxes,N),
    Boxes :: 0 .. MaxEl,
   
    %check  all element in boxes
    foreach(I in 1.. N)
        ArticlesT[2,I] #= sum( [Boxes[R,I] : R in 1 .. MaxBoxes])
    end,
   
    % check range boxes
    foreach(I in 1 .. MaxBoxes)
        Sum #= sum([Boxes[I,J] : J in 1 .. N]),
        (Sum #=0 #\/ (Sum #>=MinEl #/\ Sum #<=MaxEl))
    end,
   
    %maximize empty boxes
   %NumBoxes #= sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])#=0]),
   %Vars = Boxes ++ {NumBoxes},
   %solve($[max(NumBoxes),report(printf("NumBoxes: %w\n",NumBoxes))],Boxes),        
   
    solve(Boxes),
    println(sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])>0])),
    println(Boxes).    


Thank you

Luca

Hakan Kjellerstrand

unread,
May 13, 2024, 3:00:18 AM5/13/24
to Picat
Hi Luca.

Something is strange with this.  

As the model stand, none of solvers (SAT, CP, MIP, SMT) give any solution to the optimization problem using
   % ...
   NumBoxes #= sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])#=0]),
   Vars = Boxes ++ {NumBoxes},
   solve($[max(NumBoxes),report(printf("NumBoxes: %w\n",NumBoxes))],Vars),       


However, with some adjustment of the domain of Boxes as well as commenting the disjunction constraint in the loop, then the CP solver - but only the CP solver - yields a solution. Here are the changes:

   %
    % Boxes :: 0 .. MaxEl, % ORIG
    Boxes :: [0] ++ MinEl..MaxEl, % hakank

     % check range boxes
    foreach(I in 1 .. MaxBoxes)
        Sum #= sum([Boxes[I,J] : J in 1 .. N]),
        % (Sum #=0 #\/ (Sum #>=MinEl #/\ Sum #<=MaxEl)), % hakank: Commenting this.
    end,
  
   % ...

The CP solver gives the optimal value of NumBoxes of 66 (in 0.06s), which seems to be correct (I checked it with a more complex model).
But, no other solver give any solution.


Here's my complete version:
"""
% import sat, util. % no solution
import cp, util. % gives a solution
% import mip, util. % no solution
% import smt, util. % no solution


main =>
    MaxEl =300, %  max number of element in a box
    MinEl=60, %  min number of element in a box
    Articles = [ ['A', 1000],   %code article , number of elements
                 ['B', 400],
                 ['C', 150],
                 ['D', 500],
                 ['E', 500],
                 ['F', 500],
                 ['G', 500],
                 ['H', 500],
                 ['I', 100] ],
                 
    N=Articles.length,
    ArticlesT=Articles.transpose(),
    NumArticles=sum([ArticlesT[2,I] : I in 1.. N]),
    println(num_articles=NumArticles),
    MaxBoxes=ceiling(NumArticles / MinEl),
    println(max_boxes=MaxBoxes),
    Boxes = new_array(MaxBoxes,N),
    % Boxes :: 0 .. MaxEl, % ORIG
    Boxes :: [0] ++ MinEl..MaxEl, % hakank

   
    %check  all element in boxes
    foreach(I in 1.. N)
        ArticlesT[2,I] #= sum( [Boxes[R,I] : R in 1 .. MaxBoxes])
    end,
   
    % check range boxes
    foreach(I in 1 .. MaxBoxes)
        Sum #= sum([Boxes[I,J] : J in 1 .. N]),
        % (Sum #=0 #\/ (Sum #>=MinEl #/\ Sum #<=MaxEl)), % hakank: Commented this
    end,
   
    %maximize empty boxes

   NumBoxes #= sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])#=0]),
   Vars = Boxes,
   println(solve=NumBoxes),  
   solve($[max(NumBoxes),report(printf("NumBoxes: %w\n",NumBoxes))],Vars),        
  
    println(sum_filled=sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])>0])),
    println(num_boxes=NumBoxes),    
    println(Boxes).   
"""
 
The output is:
"""
num_articles = 4150
max_boxes = 70
solve = 66
NumBoxes: 66
sum_filled = 4
num_boxes = 66
{{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{100,0,0,0,0,0,0,0,0},{300,0,0,0,0,0,0,0,0},{300,100,0,200,200,200,200,200,0},{300,300,150,300,300,300,300,300,100}}
"""

Perhaps Neng-Fa can give some light on this?

Best,

Hakan

lassenza73

unread,
May 13, 2024, 11:43:16 AM5/13/24
to Picat
Hi Hakan,
thank you very match,
but the result seems wrong the boxes exceed the max number of elements:
we have 4150 elements and the MaxEl =300 so i think the solution should be at least 14 boxes

Thank you
Luca

Hakan Kjellerstrand

unread,
May 13, 2024, 1:02:20 PM5/13/24
to Picat
Hi again, Luca.

Sorry about that.

The issues is how you calculate the value of NumBoxes. The following works:
   NumBoxes #= sum([sum( [Boxes[R,I] : I in 1 ..N])#=0 : R in 1 .. MaxBoxes]),


Here's the full model
"""
% import sat, util.
% import cp, util.
import mip, util.
% import smt, util.


main =>
    nolog,

    MaxEl =300, %  max number of element in a box
    MinEl=60, %  min number of element in a box
    Articles = [ ['A', 1000],   %code article , number of elements
                 ['B', 400],
                 ['C', 150],
                 ['D', 500],
                 ['E', 500],
                 ['F', 500],
                 ['G', 500],
                 ['H', 500],
                 ['I', 100] ],
                 
    N=Articles.length,
    ArticlesT=Articles.transpose(),
    NumArticles=sum([ArticlesT[2,I] : I in 1.. N]),
    println(num_articles=NumArticles),
    MaxBoxes=ceiling(NumArticles / MinEl),
    println(max_boxes=MaxBoxes),
    Boxes = new_array(MaxBoxes,N),
    Boxes :: 0 .. MaxEl,

    %check  all element in boxes
    foreach(I in 1.. N)
        ArticlesT[2,I] #= sum( [Boxes[R,I] : R in 1 .. MaxBoxes])
    end,
   
    % check range boxes
    foreach(I in 1 .. MaxBoxes)
        Sum #= sum([Boxes[I,J] : J in 1 .. N]),
        (Sum #=0 #\/ (Sum #>=MinEl #/\ Sum #<=MaxEl))
    end,

   % maximize empty boxes
   % NumBoxes #= sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])#=0]),  % ORIG
   NumBoxes #= sum([sum( [Boxes[R,I] : I in 1 ..N])#=0 : R in 1 .. MaxBoxes]), % hakank

   Vars = Boxes ++ {NumBoxes},
   solve($[down,max(NumBoxes),report(printf("NumBoxes: %w\n",NumBoxes))],Vars),        
   
    % solve(Vars),
    println(filled_boxes=sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])>0])),
    foreach(I in 1..MaxBoxes)
      foreach(J in 1..N)
        printf("%4d ", Boxes[I,J])
      end,
      nl
    end,
    println(num_boxes=NumBoxes),    
    nl.

"""

What I can see, the best solver is MIP (SCIP) which solves the problem in 0.1s. The SAT and CP solvers are slower.

Here's the output:
"""
num_articles = 4150
max_boxes = 70
filled_boxes = 14
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
 100    0    0    0    0    0  200    0    0
   0    0    0    0    0    0  300    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
 100    0    0    0  200    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0  200    0    0    0  100    0
   0  300    0    0    0    0    0    0    0
 100  100    0    0    0    0    0    0  100
  50    0    0    0    0    0    0  200    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
 300    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
 150    0  150    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
 100    0    0    0    0    0    0  200    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0  300    0    0    0    0    0
   0    0    0    0    0  300    0    0    0
 100    0    0    0    0  200    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0  300    0    0    0    0
   0    0    0    0    0    0    0    0    0
num_boxes = 56
"""

Note: The exact boxes that are not empty are placed at "random". Personally I would a add a list to ensure that the non empty boxes are placed first in Boxes.
Here's the model for that. The added list is the boolean EmptyBoxes and the increasing/1 constraint,, noted by "<---"
"""
% import sat, util.
% import cp, util.
import mip, util.
% import smt, util.


main =>
    nolog,

    MaxEl =300, %  max number of element in a box
    MinEl=60, %  min number of element in a box
    Articles = [ ['A', 1000],   %code article , number of elements
                 ['B', 400],
                 ['C', 150],
                 ['D', 500],
                 ['E', 500],
                 ['F', 500],
                 ['G', 500],
                 ['H', 500],
                 ['I', 100] ],
                 
    N=Articles.length,
    ArticlesT=Articles.transpose(),
    NumArticles=sum([ArticlesT[2,I] : I in 1.. N]),
    println(num_articles=NumArticles),
    MaxBoxes=ceiling(NumArticles / MinEl),
    println(max_boxes=MaxBoxes),
    Boxes = new_array(MaxBoxes,N),
    Boxes :: 0 .. MaxEl,

  
    EmptyBoxes = new_list(MaxBoxes),  % <---
    EmptyBoxes :: 0..1, % 1: This is an empty box  <---


    %check  all element in boxes
    foreach(I in 1.. N)
        ArticlesT[2,I] #= sum( [Boxes[R,I] : R in 1 .. MaxBoxes])
    end,
   
    % check range boxes
    foreach(I in 1 .. MaxBoxes)
        Sum #= sum([Boxes[I,J] : J in 1 .. N]),
        (Sum #=0 #\/ (Sum #>=MinEl #/\ Sum #<=MaxEl)),
        EmptyBoxes[I] #= 1 #<=> Sum #= 0 % <---
    end,

    increasing(EmptyBoxes), % <---

   % maximize empty boxes
   % NumBoxes #= sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])#=0]),  % ORIG
   NumBoxes #= sum([sum( [Boxes[R,I] : I in 1 ..N])#=0 : R in 1 .. MaxBoxes]), % hakank
   Vars = EmptyBoxes ++ Boxes ++ {NumBoxes}, % <---
   solve($[down,max(NumBoxes),report(printf("NumBoxes: %w\n",NumBoxes))],Vars),        
   
    % solve(Vars),
    println(filled_boxes=sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])>0])),
    foreach(I in 1..MaxBoxes)
      foreach(J in 1..N)
        printf("%4d ", Boxes[I,J])
      end,
      nl
    end,
    println(num_boxes=NumBoxes),   
    println(empty_boxes=EmptyBoxes), % <---
    nl.
"""

The solution takes a little longer (0.3s with MIP/SCIP) but - IMHO - it looks neater.
"""
num_articles = 4150
max_boxes = 70
filled_boxes = 14
 100    0    0    0    0  200    0    0    0
   0    0  100    0    0    0    0  200    0
 300    0    0    0    0    0    0    0    0
   0    0    0    0    0  300    0    0    0
   0    0    0    0    0    0  200    0  100
   0    0    0    0    0    0  250    0    0
   0    0   50  250    0    0    0    0    0
 300    0    0    0    0    0    0    0    0
   0  100    0    0  200    0    0    0    0
   0    0    0  250    0    0   50    0    0
   0    0    0    0  300    0    0    0    0
   0  300    0    0    0    0    0    0    0
   0    0    0    0    0    0    0  300    0
 300    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
   0    0    0    0    0    0    0    0    0
  ... 
num_boxes = 56
empty_boxes = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
"""

Hope this helps.

Best,

Hakan

lassenza73

unread,
May 13, 2024, 1:21:17 PM5/13/24
to Picat
Thank you
i'll study your solution
Luca

Message has been deleted

Neng-Fa Zhou

unread,
May 13, 2024, 5:41:53 PM5/13/24
to Picat
Thank you, Hakan, for making the program run.  As you rightfully corrected it, the issue occurs in 

NumBoxes #= sum([1 : R in 1 .. MaxBoxes, sum( [Boxes[R,I] : I in 1 ..N])#=0]),  

which unconditionally posts the constraint "sum( [Boxes[R,I] : I in 1 ..N])#=0" in the loop. The cp solver behaves differently from other solvers because cp does more propagation and consistency checking than other solvers.

Cheers,
NF

lassenza73

unread,
May 19, 2024, 1:24:33 PM5/19/24
to Picat

Hi everyone,
I modified the program by introducing three types of boxes ( A, B, C) and an objective function (Cost) but the performance is not exceptional,
Could you suggest me how to improve the performance?
Thank you
Luca

import mip, util.


main =>
    MaxEl =300, %  max number of element in a box
    MinEl=40, %  min number of element in a box
    %            ArticleCode , ArticleType, Quantity
     Articles = [ ['A',1, 10],
                  ['B',1, 20],
                  ['C',2, 15],
                  ['D',2, 20],
                  ['E',3, 25],
                  ['F',3, 25],
                  ['G',1, 50],
                  ['H',4, 350],  
                  ['I',4, 12],
                  ['J',4, 10],
                  ['K',4, 206],
                  ['L',5,23],
                  ['M',5,123],
                  ['N',6,123],
                  ['O',6,13],
                  ['P',7,613],
                  ['Q',8,103],
                  ['R',8,1],
                  ['S',9,11],
                  ['T',9,130],
                  ['T',9,33]
                ],
 
    ArticleTypes=[1,2,3,4,5,6,7,8,9],                
    N=Articles.length,
    ArticlesT=Articles.transpose(),
    println(articlesT=ArticlesT),
    ArticleTypesMatrix=[[cond(ArticlesT[2,J]==ArticleTypes[I],1,0) : J in 1.. N ] : I in 1 .. ArticleTypes.length],
    NumArticles=sum([ArticlesT[3,I] : I in 1.. N]),
    println(num_Articles=NumArticles),
    MaxBoxes=ceiling(NumArticles / MinEl),
    println(maxBoxes=MaxBoxes),
   
    % BoxesA have only one article(AtricleCode) and quantity >=MinEl ad <=MaxEl
    MaxBoxesA=0,
    foreach (T in 1.. N)
        if ArticlesT[3,T]>=MinEl then
            MaxBoxesA := MaxBoxesA + ceiling(ArticlesT[3,T]/MaxEl)
        end
    end,
   
    %select only possible element for boxesA
    BoxesAIdx =[ I : I in 1 .. N , ArticlesT[3,I]>=MinEl],    
    println(boxesAIdx=BoxesAIdx),
   
   
    % BoxesB have only articles of one ArticleType and  sum of quantities >=MinEl ad <=MaxEl
    MaxBoxesB=0,
    foreach (T in 1.. ArticleTypes.length)
        PartialSum=sum([ArticlesT[3,I] : I in 1.. N, ArticlesT[2,I]==ArticleTypes[T]]),
        if PartialSum>=MinEl then
            MaxBoxesB := MaxBoxesB + ceiling(PartialSum/MaxEl)
        end
    end,
   
   
    %select only possible element for boxesB
    BoxesBIdx =[],
    foreach (T in 1.. ArticleTypes.length)
        PartialSum=sum([ArticlesT[3,I] : I in 1.. N, ArticlesT[2,I]==ArticleTypes[T]]),
        if PartialSum>=MinEl then
            BoxesBIdx := BoxesBIdx  ++ [I : I in 1.. N, ArticlesT[2,I]==ArticleTypes[T]]
        end
    end,
   
    println(boxesBIdx=BoxesBIdx),
   
    % BoxesC have only the constraint sum of quantities >=MinEl ad <=MaxEl
    MaxBoxesC=ceiling(NumArticles / MaxEl),
   
    println(max_boxesA=MaxBoxesA),
    println(max_boxesB=MaxBoxesB),
    println(max_boxesC=MaxBoxesC),
   
   
    BoxesA = new_array(MaxBoxesA,N),
    BoxesA :: [0] ++ MinEl.. MaxEl,
   
    BoxesB = new_array(MaxBoxesB,N),
    BoxesB ::  0.. MaxEl,    
   
    BoxesC = new_array(MaxBoxesC,N),
    BoxesC ::  0.. MaxEl,
   
    %set to zero  element  boxesA
    foreach(I in 1.. N)
        if ArticlesT[3,I] <MinEl then
            foreach(J in 1 .. MaxBoxesA)
                BoxesA[J,I]  #=0
            end
        end
    end,  
   
    %set to zero  element  boxesB
    foreach(T in 1.. ArticleTypes.length)
        PartialSum=sum([ArticlesT[3,I] : I in 1.. N, ArticlesT[2,I]==ArticleTypes[T]]),
        if PartialSum<MinEl then
            foreach(J in 1.. MaxBoxesB, I in 1 ..N )
                if ArticlesT[2,I]==ArticleTypes[T] then
                    BoxesB[J,I]  #=0
                end
            end    
        end
    end,

    % check BoxesA only one element>0
    foreach(I in 1 .. MaxBoxesA)
        Sum #= sum([BoxesA[I,J] : J in  BoxesAIdx]),
        foreach(J in  BoxesAIdx)
            (BoxesA[I,J] #=0 #\/ Sum #= BoxesA[I,J])
         end  
    end,
   
    % check  BoxesB only element same Type
    foreach(I in 1 .. MaxBoxesB)
        SumB #= sum([BoxesB[I,J] : J in BoxesBIdx]),
       (SumB #=0 #\/ (SumB #>=MinEl #/\ SumB #<=MaxEl)),
        foreach( T in 1 .. ArticleTypes.length)
            L #=sum([ ArticleTypesMatrix[T,J] * BoxesB[I,J]  : J in BoxesBIdx]),
            L #=0 #\/ L #=SumB
        end
    end,
   
    % check range BoxesC
    foreach(I in 1 .. MaxBoxesC)
        SumC #= sum([BoxesC[I,J] : J in 1 .. N]),
        (SumC #=0 #\/ (SumC #>=MinEl #/\ SumC #<=MaxEl))  
    end,

   
      %check  all element in boxes
    foreach(I in 1.. N)
        ArticlesT[3,I] #= sum( [BoxesA[R,I] : R in 1 .. MaxBoxesA]) + sum( [BoxesB[R,I] : R in 1 .. MaxBoxesB]) + sum( [BoxesC[R,I] : R in 1 .. MaxBoxesC])
    end,  
 
   
    %objective function
    Cost#= 10*sum([BoxesA[R,I] : R in 1 .. MaxBoxesA, I in  BoxesAIdx]) +  15*sum( [BoxesB[R,I] : R in 1 .. MaxBoxesB, I in BoxesBIdx]) + 20*sum( [BoxesC[R,I] : R in 1 .. MaxBoxesC, I in 1 ..N ]),
   
    Vars=BoxesA ++ BoxesB ++ BoxesC ++ {Cost},
 
    solve($[min(Cost)],Vars),
    println(cost=Cost),
   
    println("BoxesA"),
    foreach(I in 1 .. MaxBoxesA)
        Sum = sum([BoxesA[I,J] : J in 1 .. N]),
        if Sum>0 then
            foreach( J in 1 ..N)
                printf("%4d",BoxesA[I,J] )
            end,nl
        end
    end,  
    nl,
   
    println("BoxesB"),
    foreach(I in 1 .. MaxBoxesB)
        Sum = sum([BoxesB[I,J] : J in 1 .. N]),
        if Sum>0 then
            foreach( J in 1 ..N)
                printf("%4d",BoxesB[I,J] )
            end,nl
        end
     end,  
    nl,
   
    println("BoxesC"),
    foreach(I in 1 .. MaxBoxesC)
        Sum = sum([BoxesC[I,J] : J in 1 .. N]),
        if Sum>0 then
            foreach( J in 1 ..N)
                printf("%4d",BoxesC[I,J] )
            end,nl
        end
    end,
    nl.


Hakan Kjellerstrand

unread,
May 20, 2024, 3:36:10 AM5/20/24
to Picat

Hi Luca.

Which MIP solver do you use? What's the solve time?

The SCIP MIP solver solves the problem in 2.0s. For using the SCIP solve you have to download the C source (from http://picat-lang.org/download.html) and the compile it.
See the file INSTALL for how to compile it. Note that this is supported for Linux (which I happen to use use) and MacOS.

I don't  fully understand the specific constraints for the A, B, and C boxes. Can you describe them in more detail?

Best,

Hakan

lassenza73

unread,
May 20, 2024, 9:17:37 AM5/20/24
to Picat
Hi Hakan,
i used the Cbc solver and after an hour i stopped the process
I try to explain the constraints:
A box "A"  may contains  only elements of one Article  for example a box may contain only article K ['K',4, 206] so all the elements are zero except one (K).  
A box "B" may contains only elements of Atricles of the same Type for example  for type 3 the box may contains only the articles E or F  ['E',3, 25]and  ['F',3, 25]
A box C has only the constraint on the total number of elements  as the other type of boxes

Thank you

Luca

lassenza73

unread,
May 20, 2024, 1:04:22 PM5/20/24
to Picat
Hi,
using SCIP solver is realy faster
So now i'm tring to increment the number of Articles  but the program is stil running after 10 minutes 

   Articles = [ ['A',1, 210],

                  ['B',1, 20],
                  ['C',2, 15],
                  ['D',2, 20],
                  ['E',3, 25],
                  ['F',3, 25],
                  ['G',1, 50],
                  ['H',4, 350],
                  ['I',4, 120],

                  ['J',4, 10],
                  ['K',4, 206],
                  ['L',5,230],

                  ['M',5,123],
                  ['N',6,123],
                  ['O',6,13],
                  ['P',7,613],
                  ['Q',8,103],
                  ['R',8,1000],

                  ['S',9,11],
                  ['T',9,130],
                  ['T',9,33],
                  ['U',10,130],
                  ['U',11,233],
                  ['V',12,13],
                  ['V',13,3],
                  ['Z',14,65],
                  ['Z',14,41]

                ],

    ArticleTypes=[1,2,3,4,5,6,7,8,9,10,11,12,13,14],


Luca
Reply all
Reply to author
Forward
0 new messages