написание программ на C ++ с использованием CPLEX с технологией Concert - PullRequest
0 голосов
/ 15 апреля 2020

Это мой первый вопрос на сайте переполнения стека. Я изучал концертные технологии на C ++. После того, как я получил некоторое понимание, я попытался решить следующую проблему. Я закодировал проблему, но я получаю неосуществимое решение. Может кто-то взглянуть на это и попытаться найти, где я делаю ошибку? Большое спасибо!

Вот проблема:
Компания по производству кормов для домашних животных производит корма для собак, кошек и кроликов. Для этого они смешивают кукурузу, известняк, сою и фантастическую еду. Эти ингредиенты содержат следующие питательные вещества: витамины, белок, кальций и сырой жир. Содержание питательных веществ в стандартных единицах измерения для каждого килограмма ингредиентов приведено в следующей таблице.

Ingredient Vitamins Protein Calcium  Crude Fat   Amount Available    Price per kg
Corn         8       10      6         8           9  tons            $0.20
Limestone    6       5       10        6           12 tons            $0.12
Soybeans     10      12      6         6           5  tons            $0.24
Fish meal     4      8       6         9           6  tons            $0.1

Компания заключила контракт на производство 12, 8 и 9 (метри c) тонн корм для собак, кошек и кроликов. Тем не менее, компания может получить только ту сумму, которая указана в таблице выше для каждого ингредиента и указана цена за килограмм. Чтобы обеспечить целостность своего продукта, они должны придерживаться минимальных и максимальных единиц различных питательных веществ для килограмма пищи для собак, кошек и кроликов.

Vitamins        Protein     Calcium      Crude      Fat
Product        Min  Max     Min Max     Min Max    Min Max
Dog Food       6    ∞       6   ∞       7    ∞      4  8
Cat Food       6    ∞       6   ∞       6    ∞      4  6
Rabbit Food    4    6       6   ∞       6    ∞      4  5

Сформулируйте эту проблему как линейную программу таким образом, что компания минимизирует затраты.

Как вы можете видеть, я делал cout после каждого блока кода для проверки содержимого массивов. Содержание, казалось, было в порядке. И причина, по которой я использовал 50000 в IloIntVarArray(env, nbIngr, 0, 50000), заключается в том, что это просто очень большой верхний предел для моей переменной решения. Это может быть бесконечность.

Вот код:

using namespace std;
#include <ilcplex/ilocplex.h>
#include <iostream>;


typedef IloArray<IloIntVarArray> IloIntVarArray2; // creating two-dimentional array


int main() {
    IloEnv env;
    try {
        IloInt i,j,k;
        IloInt nbFood = 3; // Number of food type (Dog food, Cat food, Rabbit food)
        IloInt nbIngr = 4; // Number of ingredient type (Corn, Limestone, Soybeans, Fish meal)
        IloInt nbNut = 4; // Number of nutrient type (Vitamins, Protein, Calcium, Crude fat)

        // Decision variable
        // kgs of ingredient j in food i
        IloIntVarArray2 ingredientInFoodX(env, nbFood);
        for (i = 0; i < nbFood; i++) {
            ingredientInFoodX[i] = IloIntVarArray(env, nbIngr, 0, 50000);          
        }
        for (i = 0; i < nbFood; i++) {
            for (j = 0; j < nbIngr; j++) {
                cout << "content is: " << ingredientInFoodX[i][j] << endl;
            }                 

        }
        cout << typeid(ingredientInFoodX).name() << endl;
        cout << endl;

        // Parametrs
        IloNumArray costIngr(env, nbIngr, 0.2, 0.12, 0.24, 0.12); // cost per kg of ingredient
        for (j = 0; j < nbIngr; j++) {
            cout << "content is: " << costIngr[j] << endl;
        }
        cout << endl;

        IloArray<IloNumArray> nutrientPerIngr(env, nbIngr); // amount of nutrient k for each kg of ingredient j
        nutrientPerIngr[0] = IloNumArray(env, nbNut, 8, 10, 6, 8);
        nutrientPerIngr[1] = IloNumArray(env, nbNut, 6, 5, 10, 6);
        nutrientPerIngr[2] = IloNumArray(env, nbNut, 10, 12, 6, 6);
        nutrientPerIngr[3] = IloNumArray(env, nbNut, 4, 8, 6, 9);
        for (j = 0; j < nbIngr; j++) {
            for (k = 0; k < nbNut; k++) {
                cout << "content is: " << nutrientPerIngr[j][k] << endl;
            }
        }
        cout << endl;
        IloNumArray availableIngr(env, nbIngr, 9000, 12000, 5000, 6000);  // amount available (kg) of ingredient j
        for (j = 0; j < nbIngr; j++) {
            cout << "content is: " << availableIngr[j] << endl;
        }
        cout << endl;
        IloNumArray foodDemand(env, nbFood, 12000, 8000, 9000); // demand for food i
        for (i = 0; i < nbFood; i++) {
            cout << "content is: " << foodDemand[i] << endl;
        }
        cout << endl;

        IloNumArray2 foodMinNutrient(env, nbFood); // minimum nutrient k requirement in food i
        foodMinNutrient[0] = IloNumArray(env, nbNut, 6, 6, 7, 4);
        foodMinNutrient[1] = IloNumArray(env, nbNut, 6, 6, 6, 4);
        foodMinNutrient[2] = IloNumArray(env, nbNut, 4, 6, 6, 4);
        for (i = 0; i < nbFood; i++) {
            for (k = 0; k < nbNut; k++) {
                cout << "content is: " << foodMinNutrient[i][k] << endl;
            }
        }
        cout << endl;
        IloNumArray2 foodMaxNutrient(env, nbFood); // maximum nutrient k requirement in food i
        foodMaxNutrient[0] = IloNumArray(env, nbNut, 10000, 10000, 10000, 8);
        foodMaxNutrient[1] = IloNumArray(env, nbNut, 10000, 10000, 10000, 6);
        foodMaxNutrient[2] = IloNumArray(env, nbNut, 6, 10000, 10000, 5);
        for (i = 0; i < nbFood; i++) {
            for (k = 0; k < nbNut; k++) {
                cout << "content is: " << foodMaxNutrient[i][k] << endl;
            }
        }
        cout << endl;

        IloModel model(env);

        // Objective function (minimize production cost)
        IloExpr objective_func(env);
        for (i = 0; i < nbFood; i++) {
            for (j = 0; j < nbIngr; j++)
                objective_func += costIngr[j] * ingredientInFoodX[i][j];
        }
        model.add(IloMinimize(env, objective_func));
        objective_func.end();

        // Constraints

        //limit amount of available ingredient k
        for (j = 0; j < nbIngr; j++) {
            IloExpr expr(env);
            for (i = 0; i < nbFood; i++) {
                expr += ingredientInFoodX[i][j];
            }
            model.add(expr <= availableIngr[j]);
            expr.end();
        }

        // Ensure demand for food i is satisfied
        for (i = 0; i < nbFood; i++) {
            IloExpr expr(env);
            for (j = 0; j < nbIngr; j++) {
                expr += ingredientInFoodX[i][j];
            }
            model.add(expr >= foodDemand[i]);
            expr.end();
        }

        // Min and Max nutrient requirement in food i
        for (i = 0; i < nbFood; i++) {
            for (k = 0; k < nbNut; k++) {
                IloExpr expr(env);                
                for (j = 0; j < nbIngr; j++) {
                    expr += nutrientPerIngr[j][k] * ingredientInFoodX[i][j];                    
                }
                model.add(foodMinNutrient[i][k] * foodDemand[i] <= expr <= foodMaxNutrient[i][k] * foodDemand[i]);
                expr.end();               
            }
        }
        cout << model << endl;
        IloCplex cplex(model);          
        cplex.solve();
        cplex.setOut(env.getNullStream()); // removes unnecessary information from the output window
        cout << "Solution status is: " << cplex.getStatus() << endl;
        cout << "Objective function value is: " << cplex.getObjValue() << endl;
        cout << ingredientInFoodX[i][j] << endl; 

    }
    catch (IloException & ex) {
        cerr << "Error: " << ex << endl;
    }
    catch (...) {
        cerr << "Error" << endl;
    }
    env.end();   
}

Вот вывод:

content is: IloIntVar(0)[0..50000]
content is: IloIntVar(1)[0..50000]
content is: IloIntVar(2)[0..50000]
content is: IloIntVar(3)[0..50000]
content is: IloIntVar(4)[0..50000]
content is: IloIntVar(5)[0..50000]
content is: IloIntVar(6)[0..50000]
content is: IloIntVar(7)[0..50000]
content is: IloIntVar(8)[0..50000]
content is: IloIntVar(9)[0..50000]
content is: IloIntVar(10)[0..50000]
content is: IloIntVar(11)[0..50000]
class IloArray<class IloIntVarArray>

content is: 0.2
content is: 0.12
content is: 0.24
content is: 0.12

content is: 8
content is: 10
content is: 6
content is: 8
content is: 6
content is: 5
content is: 10
content is: 6
content is: 10
content is: 12
content is: 6
content is: 6
content is: 4
content is: 8
content is: 6
content is: 9

content is: 9000
content is: 12000
content is: 5000
content is: 6000

content is: 12000
content is: 8000
content is: 9000

content is: 6
content is: 6
content is: 7
content is: 4
content is: 6
content is: 6
content is: 6
content is: 4
content is: 4
content is: 6
content is: 6
content is: 4

content is: 10000
content is: 10000
content is: 10000
content is: 8
content is: 10000
content is: 10000
content is: 10000
content is: 6
content is: 6
content is: 10000
content is: 10000
content is: 5

IloModel model12 = {
obj14 = (0.2 * IloIntVar(0)[0..50000]  + 0.12 * IloIntVar(1)[0..50000]  + 0.24 * IloIntVar(2)[0..50000]  + 0.12 * IloIntVar(3)[0..50000]  + 0.2 * IloIntVar(4)[0..50000]  + 0.12 * IloIntVar(5)[0..50000]  + 0.24 * IloIntVar(6)[0..50000]  + 0.12 * IloIntVar(7)[0..50000]  + 0.2 * IloIntVar(8)[0..50000]  + 0.12 * IloIntVar(9)[0..50000]  + 0.24 * IloIntVar(10)[0..50000]  + 0.12 * IloIntVar(11)[0..50000] , IloObjective, Minimize);

IloIntVar(0)[0..50000]  + IloIntVar(4)[0..50000]  + IloIntVar(8)[0..50000]  <= 9000
IloIntVar(1)[0..50000]  + IloIntVar(5)[0..50000]  + IloIntVar(9)[0..50000]  <= 12000
IloIntVar(2)[0..50000]  + IloIntVar(6)[0..50000]  + IloIntVar(10)[0..50000]  <= 5000
IloIntVar(3)[0..50000]  + IloIntVar(7)[0..50000]  + IloIntVar(11)[0..50000]  <= 6000
12000 <= IloIntVar(0)[0..50000]  + IloIntVar(1)[0..50000]  + IloIntVar(2)[0..50000]  + IloIntVar(3)[0..50000]
8000 <= IloIntVar(4)[0..50000]  + IloIntVar(5)[0..50000]  + IloIntVar(6)[0..50000]  + IloIntVar(7)[0..50000]
9000 <= IloIntVar(8)[0..50000]  + IloIntVar(9)[0..50000]  + IloIntVar(10)[0..50000]  + IloIntVar(11)[0..50000]
72000 <= 8 * IloIntVar(0)[0..50000]  + 6 * IloIntVar(1)[0..50000]  + 10 * IloIntVar(2)[0..50000]  + 4 * IloIntVar(3)[0..50000]  <= 1.2e+08
72000 <= 10 * IloIntVar(0)[0..50000]  + 5 * IloIntVar(1)[0..50000]  + 12 * IloIntVar(2)[0..50000]  + 8 * IloIntVar(3)[0..50000]  <= 1.2e+08
84000 <= 6 * IloIntVar(0)[0..50000]  + 10 * IloIntVar(1)[0..50000]  + 6 * IloIntVar(2)[0..50000]  + 6 * IloIntVar(3)[0..50000]  <= 1.2e+08
48000 <= 8 * IloIntVar(0)[0..50000]  + 6 * IloIntVar(1)[0..50000]  + 6 * IloIntVar(2)[0..50000]  + 9 * IloIntVar(3)[0..50000]  <= 96000
48000 <= 8 * IloIntVar(4)[0..50000]  + 6 * IloIntVar(5)[0..50000]  + 10 * IloIntVar(6)[0..50000]  + 4 * IloIntVar(7)[0..50000]  <= 8e+07
48000 <= 10 * IloIntVar(4)[0..50000]  + 5 * IloIntVar(5)[0..50000]  + 12 * IloIntVar(6)[0..50000]  + 8 * IloIntVar(7)[0..50000]  <= 8e+07
48000 <= 6 * IloIntVar(4)[0..50000]  + 10 * IloIntVar(5)[0..50000]  + 6 * IloIntVar(6)[0..50000]  + 6 * IloIntVar(7)[0..50000]  <= 8e+07
32000 <= 8 * IloIntVar(4)[0..50000]  + 6 * IloIntVar(5)[0..50000]  + 6 * IloIntVar(6)[0..50000]  + 9 * IloIntVar(7)[0..50000]  <= 48000
36000 <= 8 * IloIntVar(8)[0..50000]  + 6 * IloIntVar(9)[0..50000]  + 10 * IloIntVar(10)[0..50000]  + 4 * IloIntVar(11)[0..50000]  <= 54000
54000 <= 10 * IloIntVar(8)[0..50000]  + 5 * IloIntVar(9)[0..50000]  + 12 * IloIntVar(10)[0..50000]  + 8 * IloIntVar(11)[0..50000]  <= 9e+07
54000 <= 6 * IloIntVar(8)[0..50000]  + 10 * IloIntVar(9)[0..50000]  + 6 * IloIntVar(10)[0..50000]  + 6 * IloIntVar(11)[0..50000]  <= 9e+07
36000 <= 8 * IloIntVar(8)[0..50000]  + 6 * IloIntVar(9)[0..50000]  + 6 * IloIntVar(10)[0..50000]  + 9 * IloIntVar(11)[0..50000]  <= 45000
}


Solution status is: Infeasible
Error: CPLEX Error  1217: No solution exists.

1 Ответ

1 голос
/ 15 апреля 2020

Вы можете использовать уточнение конфликта для анализа невозможности. Это можно сделать, позвонив по номеру cplex.refineConflict(). Для небольших проблем, однако, проще экспортировать модель и анализировать конфликт в интерактивном оптимизаторе. Для этого позвоните cplex.exportModel("food.lp"), прежде чем звонить cplex.solve(). Затем в консоли вызовите интерактивный оптимизатор (cplex.exe на Windows и cplex для других операционных систем) и выполните в командной строке следующее:

CPLEX> read food.lp
CPLEX> tools conflict
CPLEX> display conflict all

Это позволит найти минимальный набор конфликтующих ограничения и отображать их. В вашем случае конфликт выглядит так:

Subject To
 c7:  x9 + x10 + x11 + x12 >= 9000
 c19: 8 x9 + 6 x10 + 6 x11 + 9 x12 - Rgc19  = 36000
\Sum of equality rows in the conflict:
\ sum_eq: 8 x9 + 6 x10 + 6 x11 + 9 x12 - Rgc19  = 36000
Bounds
      x9 >= 0
      x10 Free
      x11 Free
      x12 >= 0
 -Inf <= Rgc19 <= 9000
Generals
 x9  x10  x11  x12

Вы можете сделать это более читабельным, если назначите имена своим переменным и ограничениям в вашей программе.

В любом случае вы можете видеть, что c7 требует, чтобы четыре переменные суммировались до 9000 или более. Это означает, что во втором ограничении сумма 8 x9 + 6 x10 + 6 x11 + 9 x12 будет по крайней мере 6 * 9000 = 54000. Учитывая, что верхняя граница Rgct19 равна 9000, ясно, что это ограничение никогда не может быть выполнено, поскольку 54000 - 9000 <= 36000 никогда не может быть правда. Кажется, с вашими данными что-то не так.

...