私はC++とConcert Technologyを使用してCPLEXでLPモデルを解こうとしています。C++ cplexアクセス制約を追加する現在のソリューション
現在のソリューションで私の変数のうちの2つの値を照会する必要がある制約(サブトラクション排除制約)を実装したいとします。 変数配列xvarはエッジを示しています.yvarはノード。
人為的なソースとアーティファクトシンクを追加し、これらを元のグラフのすべてのノードに接続することで構成される、変更されたグラフ上のn(=ノードの数)Min-Cut-Problemsを解決することによって、
これまでに読んだことは、遅延制約やコールバックが必要なのでしょうか?
私は、溶液などの変数の値にアクセスし、モデルを作成し、それを解決し得る場所です:
// Step 2: Construct the necessary CPLEX objects and the LP model
IloCplex solver(env);
std::cout<< "Original Graph g: " <<std::endl;
std::cout<< net.g() <<std::endl;
MCFModel model(env, net);
// Step 3: Load the model into cplex and solve
solver.extract(model);
solver.solve();
// Step 4: Extract the solution from the solver
if(solver.getStatus() != IloAlgorithm::Optimal) throw "Could not solve to optimality!";
IloNumArray xsol (env, net.g().nEdges());
IloNumArray ysol (env, net.g().nNodes());
IloNumArray rsol (env, net.g().nGroups());
IloNumArray wisol (env, net.g().nGroups());
IloNum ksol;
NumMatrix wsol (env, net.g().nGroups());
for(IloInt i = 0; i < net.g().nGroups(); i++){
wsol[i] = IloNumArray(env, net.g().nGroups());
}
solver.getValues(xsol, model.xvar());
solver.getValues(ysol, model.yvar());
solver.getValues(rsol, model.rvar());
solver.getValues(wisol, model.wivar());
ksol=solver.getValue(model.kvar());
for (IloInt i = 0; i < net.g().nGroups(); i++){
wsol[i] = wisol;
}
// Step 5: Print the solution.
制約は、私は変数XVARとyvarの現在の値を必要とし、
//build subset constraint y(S) -x(E(S))>= y_i
void MCFModel::buildSubsetCons(){
IloExpr lhs(m_env);
IloCplex cplex(m_env);
IloNumArray xtemp (m_env, m_net.g().nEdges());
IloNumArray ytemp (m_env, m_net.g().nNodes());
std::vector<Edge> mg_twin;
std::vector<int> mg_weights;
int mg_s;
int mg_t;
SGraph mgraph;
std::vector<int> f;
int nOrigEdges = m_net.g().nEdges();
int nOrigNodes = m_net.g().nNodes();
cplex.getValues(xtemp, m_xvar);
cplex.getValues(ytemp, m_yvar);
mgraph = m_net.g().mod_graph();
mg_s = mgraph.nNodes()-1;
mg_t = mgraph.nNodes();
std::cout<<"modified graph:"<<std::endl;
std::cout<<mgraph<<std::endl;
// fill the weight of original edges with 1/2*x_e
foreach_edge(e, m_net.g()){
mg_weights.push_back((xtemp[e->idx()])/2);
}
// fill the weight of the edges from artificial source with zero
for(int i=0; i<m_net.g().nNodes(); i++){
mg_weights.push_back(0);
}
// fill the weight of the edges to artificial sink with f(i)
// first step: calculate f(i):
//f.resize(m_net.g().nNodes());
foreach_node(i, m_net.g()){
foreach_adj_edge(e, i, m_net.g()){
f[i] = f[i] + xtemp[e->idx()];
}
f[i] = (-1)*f[i]/2;
f[i] = f[i] + ytemp[i];
}
// second step: fill the weights vector with it
for(int i=0; i<m_net.g().nNodes(); i++){
mg_weights.push_back(f[i]);
}
// calculate the big M = abs(sum_(i in N) f(i))
int M;
foreach_node(i, m_net.g()){
M = M + abs(f[i]);
}
// Build the twin vector of the not artificial edges for mgraph
mg_twin.resize(2*nOrigEdges + 2*nOrigNodes);
for(int i=0; i < nOrigEdges ; ++i){
mg_twin[i] = mgraph.edges()[nOrigEdges + i];
mg_twin[nOrigEdges + i] = mgraph.edges()[i];
}
//Start the PreflowPush for every node in the original graph
foreach_node(v, m_net.g()){
// "contract" the edge between s and v
// this equals to higher the weights of the edge (s,v) to a big value M
// weight of the edge from v to s lies in mg_weights[edges of original graph + index of node v]
mg_weights[m_net.g().nEdges() + v] = M;
//Start PreflowPush for v
PreflowPush<int> pp(mgraph, mg_twin, mg_weights, mg_s, mg_t);
std::cout << "Flowvalue modified graph: " << pp.minCut() << std::endl;
}
}
オブジェクトppは、人工的なソースとシンクを持つ修正グラフグラフのMin-Cut-Problemを解決するためのものです。元のグラフはm_net.g()にあります。
私はコンパイルして実行すると、私は次のエラーを取得する:
terminate called after throwing an instance of 'IloCplex::Exception'
Aborted
このようXVARとyvarの値にアクセスすることはできないことを、私には思えますか? 私はこれを行う方法がかなり失われているので、私は助けていただきありがとうございます。 ありがとうございます!
であることが嬉しいです/コールバックの内側でgetValues()!そして、あなたのヒントのために、cutコンテナの.end()を使っていただきありがとうございます。以前はメモリの問題がありました! :-) – cplexstudent
私はlazyconstraintとusercutcallbackを実装し、ランダムに生成されたいくつかの例についてテストを開始しました。 1つの例が終了しない場合は、無限ループに陥っているように見えます。ある時点では、繰り返し回数が増えておらず、usercutcallbackによって検出された違反の不等式が常に存在するからです。 私のすべてのIloNumVarArraysは整数として宣言されていますが、無限ループ内で最適化プロセスを停止すると、整数ではない小数の配列のエントリがあります。これも可能ですか? – cplexstudent
コールバック内にブレークポイントを置き、すべての処理が意図したとおりに行われていることを確認する必要があります。間違ったイテレータを置くのはとても簡単です(あなたは前/後の位置をとっているかもしれません)、または何かを忘れてしまいます。エラーの余地が非常にあります。そこに何かを混乱させると、CPLEXはナッツになり、あらゆる種類の狂気のことをするでしょう。 – Jacko