Search code examples
constraint-programmingminizinc

Select matching raws in table with Minizinc


I have a table of Projects with 4 features (name, value, cost, people). I want to describe a model in Minizinc that selects the projects that maximize the total value but with a total budget of 255 and I can choose almost 9 projects between 20.

I write a data file: data.dzn

%       name       value    cost  people
data = [
      | PRJ0,      6000,    35,    5
      | PRJ1,      4000,    34,    3
      | PRJ2,      1000,    26,    4
      ...
      | PRJ20,     1200,    18,    2    
      |];


PRJ = {PRJ0,...,PRJ20};
FEATURE = {name, value, budget, personnel};
max_budget = 225;
max_prj=9;

So my constraints are:

choose_project <= 9 /\ budget<=255 s.t solve maximize tot_value;

How can I select a non-arbitrary number (1 to 9) of decision variables among projects raw in the table? Until now this is my code: invest.mzn

include "data.dzn";
int: max_budget;  %255
int: max_prj;     %9
enum FEATURE;
enum PRJ;
array[PRJ,FEATURE] of int: data;
constraint ...
...
solve maximize tot_value;

Solution

  • You can declare an array of Boolean variables, say selected_projects, that encodes whether or not a project PRJ_k is selected or not.

    Then you can simply count how many projects in this array are being selected at the same time.

    Example:

    enum FEATURE = {name, value, budget, personnel};
    enum PRJ = { PRJ0, PRJ1 };
    
    array[PRJ,FEATURE] of int: data =
         [| PRJ0,      6000,    35,    5
          | PRJ1,      4000,    34,    3
          |];
    
    array[PRJ] of var bool: selected_projects;
    
    var int: tot_value;
    
    % The total number of selected projects must be in [1, 9]
    constraint let {
            var int: tot_selected = sum(prj in PRJ) ( selected_projects[prj] )
        } in
            1 <= tot_selected /\ tot_selected <= 9;
    
    constraint tot_value = sum(prj in PRJ) ( selected_projects[prj] * data[prj, value] );
    
    % ...
    % encoding of budget and personnel constraints
    % ...
    
    solve maximize tot_value;