先例制约双背包

Precedence constrainted biknapsack

本文关键字:背包      更新时间:2023-10-16

我既没有组合优化也没有编程背景,我必须写一些代码来解决具有优先级约束的双背包(2个容量)。。我已经做了3个月了,我无法调试它,也无法找出为什么它还没有返回正确的答案。。。我在C++上使用了CONCERT配置

以下是我的程序的工作原理:

首先,我使用CPLEX求解线性松弛,输出返回目标函数的值+分数变量的索引+指示松弛是否可行的变量+指示所有变量是否为整数的变量。

第二,我实现了一个分支和绑定函数,用于BFS树搜索

因此,它首先验证松弛是否可行,然后如果是,并且存在分数变量,它在它们上分支。。

每个节点都有2个特征:它的界,意味着这个节点中松弛的值+一个值列表,指示是否对变量做出了决定(如果我们决定不选择元素,它等于0,如果我们决定选择它,它等于1,如果我们还没有做出任何决定,它等于2…)

这是我的代码,问题是它只在第一个节点上分支

#include <queue>
#include<cmath>
#include<ilcplex/ilocplex.h>
#include <iostream>
#include<typeinfo>
using namespace std;
IloEnv env;
IloCplex cplex;
IloModel model;

struct node
{
    double bound;
    int val[100];
    int profit;
};

/***************************BORNE***************************/

double *bound(node u,int T,int W,int n,int Pre[],int CapaciteTemps[],int CapaciteSac[],int CoutObj[]){
    int indicefrac=0;
    double *resultat=new double[4];
    try{
        env = IloEnv();
        model=IloModel(env);

        //définition des variables de décision
        IloNumVarArray x(env,n);
        for (IloInt i=0; i<n;i++){
            x[i]=IloNumVar(env);
        }

        //contrainte 1: Capacité temps
        IloExpr Contr1(env);
        for (IloInt i=0; i<n;i++){
            Contr1 += CapaciteTemps[i]*x[i];
        }
        model.add(Contr1<=T);

        //contrainte 2: Capacité volume
        IloExpr Contr2(env);
        for (IloInt i=0; i<n;i++){
            Contr2 += CapaciteSac[i]*x[i];
        }
        model.add(Contr2<=W);

        //contrainte 3: Relaxation des variables entre 0 et 1 les variables peuvent prendre des valeurs continues mais que sur l'intervalle 0,1
        for (IloInt i=0; i<n;i++){
            model.add(0<=x[i]<=1);
        }

        //contrainte 4: Contrainte de précédence si l'on veut prendre un élément il faut avoir nécéssairement avoir pris tout ses prédécesseurs
/*
        for(IloInt i=0;i<n;i++)
        {
            for(IloInt j=0;j<n;j++){
                if(Pre[i]<=Pre[j])
                {
                    model.add(x[i]>=x[j]);
                }
            }
        }

*/
        //élément pris ou non on force sa valeur a être égale à 0 ou à 1
        for (IloInt i=0;i<n;i++){
            if(u.val[i]==0){
                model.add(x[i]<=0);}
            else if(u.val[i]==1){
                model.add(x[i]>=1);
            }

        }
        //fonction objectif
        IloExpr obj(env);
        for (IloInt i=0;i<n;i++){
            obj += CoutObj[i]*x[i];
        }
        model.add(IloMaximize(env,obj));
        cplex=IloCplex(model);
        cplex.solve();

        //affichage de la valeur des variables

        for(IloInt i=0; i<n; i++){
            cout<<"x["<<i<<"]= "<<cplex.getValue(x[i])<<endl;
        }
        if ( ! (cplex.getStatus() == IloAlgorithm::Infeasible ) ) {
            bool isfractionnelb=false;
            double isfractionneli;
            for(IloInt i=1;i<n;i++){
                if(cplex.getValue(x[i]) != (int)cplex.getValue(x[i]))
                    isfractionnelb=true;
            }

            if(isfractionnelb==true){
                for(IloInt i=1;i<n;i++){

                    if(abs(cplex.getValue(x[i])-0.5)<abs(cplex.getValue(x[indicefrac])-0.5) ){
                        indicefrac=i;
                    }
                }
            }

            if(isfractionnelb==true)
            {isfractionneli=1;}
            else{isfractionneli=0;}

            resultat[0]=cplex.getObjValue(); // borne , valeur de la relaxation
            resultat[1]=(double)indicefrac;  //indice fractionnaire
            resultat[2]=isfractionneli; // indique si une valeur fractionnaire existe après la relaxation
            resultat[3]=1;  // indique si la relaxation linéaire est réalisable

        }
        if (  (cplex.getStatus() == IloAlgorithm::Infeasible ) ){cout<<"infeasable";}

    }catch(IloException& e){

        e.print(cout);

    }

    return resultat;
}


int knapsack(int n, int p[],int t[],int T,int w[], int W, int Pre[])
{
    queue<node> Q;
    node v,ug,ud;
    vector<int> pV;
    vector<int> wV;
    vector<int> tV;
    vector<int> tPre;
    Q.empty();
    double *borneg;
    double *borned;

    for (int i = 0; i < n; i++)
    {
        pV.push_back(p[i]);
        wV.push_back(w[i]);
        tV.push_back(t[i]);
        tPre.push_back(Pre[i]);
    }
v.profit=0;
    for(int i=0;i<n;i++)
    {v.val[i]=2;}
    int maxProfit = 0;
    double *borne=bound(v,T, W, n,Pre, t, w, p) ;
    v.bound=borne[0];
    cout<<"borne "<<borne[0]<<endl;

    if(borne[2]==1){
        cout<<"indice fractionnaire : "<<borne[1]<<endl;}
    Q.push(v); // adds at top of list

    if( borne[3]==1 ){
        if(borne[2]==0){
            cout<<"la solution optimale est : "<<endl;
            maxProfit=borne[0];
            v = Q.front(); // reference a l'élement suivant dans la liste
            Q.pop(); // supprime l'élément suivant de la liste
        }
        else{
            // v = Q.front(); // reference a l'élement suivant dans la liste
            // Q.pop(); // supprime l'élément suivant de la liste
            //Q.push(v); // adds at top of list
            while (!Q.empty())
            {
                v = Q.front(); // reference a l'élement suivant dans la liste
                Q.pop(); // supprime l'élément suivant de la liste
                cout << "Noeud courant:";
                for(int i = 0 ; i < n ; ++i)
                    cout << " " << v.val[i];
                cout << endl;
                cout << "Objet fractionnaire: " << borne[1] << endl;

                int indice=(int)(borne[1]);
                node ug;
                node ud;
                int k[n];
for(int i=0;i<n;i++)
{
if (ud.val[i]==0)
k[i]=0;
else if (ud.val[i]==1)
k[i]=1;
else
k[i]=0;
}
for(int i=0;i<n;i++)
{ud.profit+=p[i]*k[i];}
for(int i=0;i<n;i++)
{
    int k[n];
if (ug.val[i]==0)
k[i]=0;
else if (ug.val[i]==1)
k[i]=1;
else
k[i]=0;
}
for(int i=0;i<n;i++)
{ug.profit+=p[i]*k[i];}
                for(int i=0;i<n;i++)
                {ug.val[i]=v.val[i];
                ug.val[indice]=1;
                }

                for(int i=0;i<n;i++)
                {ud.val[i]=v.val[i];}
                ud.val[indice]=0;

                borneg=bound(ug,T, W, n,Pre, t, w, p) ;
                borned=bound(ud,T, W, n,Pre, t, w, p) ;

cout<<"borne fils gauche"<<borneg[0]<<endl;
cout<<"borne fils droite"<<borned[0]<<endl;

                if(borned[3]==1)
                {if (borned[2]==0){
if(ud.profit>maxProfit)
{maxProfit=ud.profit;}
                    if (borned[0]>maxProfit)
                    {
                     borne[1]=borned[1];
            //  for(int i=0;i<n;i++)
                        //      {v.val[i]=fil[1].val[i];}
                         //     v.bound=fil[1].bound;
Q.push(ud);
                    }
                }
                }
            //  else {ud = Q.front(); // reference a l'élement suivant dans la liste
            //  Q.pop();
            //  cout<<"aaaaa";}

                if(borneg[3]==1)
                {if (borneg[2]==0){
                    if(ug.profit>maxProfit)
                    {maxProfit=ug.profit;}
                    if (borneg[0]>maxProfit)
                    {Q.push(ug);
                    borne[1]=borneg[1];
            //      for(int i=0;i<n;i++)
            //      {v.val[i]=fil[0].val[i];}
             //     v.bound=fil[0].bound;
               //   borne[1]=borneg[1];
                    }
                }
                }
                //else {
                //ug = Q.front(); // reference a l'élement suivant dans la liste
                //Q.pop();
                //}
cout<<"debug1"<<endl;

            }
            cplex.exportModel("/net/cremi/sbounejmate/prog1.lp");
        }}
    else{cout <<"problème irréalisable"<<endl;
    maxProfit =0;
    }
    return maxProfit;
}
int main()
{
    vector<int> pV;
    vector<int> wV;
    vector<int> tV;
    vector<int> tPre;
    int n = 6;
    int W = 6;
    int T= 3;
    int p[6]= {15,5,15,15,3,5};
    int w[6]= {1,5,5,10,2,3};
    int t[6]={2,1,3,2,2,3};
    int Pre[6]={1,1,5,1,18,1};
    for (int i = 0; i < n; i++){
        pV.push_back(p[i]);
        wV.push_back(w[i]);
        tV.push_back(t[i]);
    }
    //double *b=bound(u,T, W, n, t, w, p) ;
    int k=knapsack(n,p,t,T,w,W,Pre);
    cout<<"knapsack"<<k<<endl;
    //cout<<"La valeur de la relaxation de l'objectif est : "<<b[0]<<endl;
    //cout<<"L'indice fractionnaire le plus proche de 0.5 est : "<<b[1]<<endl;

    return 0;

}

如果你能帮我找出我的逻辑哪里出了问题,我将不胜感激。

我不会解决你的问题,但如果你为此工作了三个月,那么你需要一些策略。

我缺少任何类型的调试信息。这很容易。您添加了一些变量

static bool debug_thisthing = true;
static bool debug_thatthing = true;
... and so on

然后,例如,在"决策变量的定义"之后的代码中,添加

if (debug_thisthing) {
    ... print out stuff to make sure that you can check 
    ... that these values are correct. 
}

在每一步之后都要这样做,确保每一步都有预期的结果,并且一旦检查了一位,就可以将该部分的调试代码设置为false。

集中精力工作一天,你会处于一个更好的位置。

接下来,您构建一些示例,在这些示例中您可以手动找到解决方案,并查看它们是如何工作的。