我在组合优化和编程方面没有强大的背景,我必须编写一些代码来解决具有优先约束的双背包(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;
}
如果你能帮助我找出我的逻辑出错的地方,我将非常感激
答案 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。
有一天专注的工作,你将处于更好的位置。
接下来,您将构建一些示例,您可以手动找到解决方案,并了解它们的工作原理。