优先约束biknapsack

时间:2016-04-29 19:03:19

标签: c++ optimization cplex

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

所以这是我的计划的工作方式:

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

其次,我实现了一个执行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;


}

如果你能帮助我找出我的逻辑出错的地方,我将非常感激

1 个答案:

答案 0 :(得分:1)

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

我缺少任何调试信息。这很简单。你添加一些变量

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

然后例如在“définitiondesvariablesdedécision”之后的代码中添加

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

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

有一天专注的工作,你将处于更好的位置。

接下来,您将构建一些示例,您可以手动找到解决方案,并了解它们的工作原理。