先例制约双背包
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。
集中精力工作一天,你会处于一个更好的位置。
接下来,您构建一些示例,在这些示例中您可以手动找到解决方案,并查看它们是如何工作的。
相关文章:
- 0-1背包代码中的错误.我的代码中有什么错误
- 分数背包边缘箱
- 具有多种约束(例如重量、体积等)的背包
- 背包问题,视觉工作室问题
- 分段故障背包问题
- 0-1 大重量背包
- 具有最小值和最大值的多维背包
- 此背包代码显示浮点[float]无效类型错误.可能是什么原因
- 背包问题根据单位重量的利润对数组进行排序
- Python到C++:使用递归列出背包的所有组合的算法
- 蛮力背包的C 一部分
- 重量总和约为10^9的背包
- 可以使用 1D 数组实现 0-1 背包吗?
- 有没有解决方案而不是在C++中移动背包回溯算法
- 回溯背包实施与C++
- 背包 - 如何识别使用的重量
- 背包的变体
- 使用动态规划的值无关背包问题
- 先例制约双背包
- 具有双重数据类型的背包