2016-10-14 13 views
1

私は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の値にアクセスすることはできないことを、私には思えますか? 私はこれを行う方法がかなり失われているので、私は助けていただきありがとうございます。 ありがとうございます!

答えて

0

2つのこと...

I.私は強く、あなたがより良いCPLEX例外を理解するためのtry-catchを使用することをお勧めします。あなたはおそらくこのような例外の性質を理解することができます。実際、私は試しにキャッチキャッチの設定をお勧めします:

try { 
//... YOUR CODE ...// 
} 
catch(IloException& e) { 
    cerr << "CPLEX found the following exception: " << e << endl; 
    e.end(); 
} 
catch(...) { 
    cerr << "The following unknown exception was found: " << endl; 
} 

II。最適化プロセス中にCPLEXと対話する唯一の方法は、コールバックを使用する方法です.Subsour Elimination Constraints(SEC)の場合は、整数型と小数型のSECの両方を分離する必要があります。

II.1 INTEGER:最初のものは、最も簡単な1、であるあなたは、あなたがに表示されてから、この特定のSECを防ぐために、後続のカットを追加することができ、ノードソリューションのすべての接続されたコンポーネントを識別するのに役立つだろうO(n)ルーチン他のノード。現在のサブツリーでのみaddLocal()関数を使用してローカルに、または全体的に、つまりブランチアンドカットツリー全体で、add()関数を使用して、ローカルにカットを適用できます。いずれにしても、切断された容器を終了させるために必ず.end()を追加することを忘れないでください。さもなければ、あなたは重大なメモリリークの問題を抱えています。二つ目は、はるかに複雑である:このコールバックは、レイジー制約コールバック(ILOLAZYCONSTRAINTCALLBACK)フラクショナル

II.2 を介して行われる必要があります。それを動作させる最も簡単な方法は、Lysgaard教授のCVRPSEPライブラリを使うことです。これは、現在、容量削減、Multistar、一般化されたマルチスター、フレーム化された容量、強化された櫛とハイパーカットの削減を計算する最も効率的な方法です。また、既存のコードとリンクするのは簡単です。リンケージもソリューションプロセスに組み込む必要があるため、コールバックも必要です。この場合、ユーザーカットコールバック(ILOUSERCUTCALLBACK)になります。

一つは、私は、織部はただのgetValue()を介して液の現在の値にアクセスすることができLazyconstraintcallbackとUsercutcallbackで行わでそれを得たサービス Y

+0

であることが嬉しいです/コールバックの内側でgetValues()!そして、あなたのヒントのために、cutコンテナの.end()を使っていただきありがとうございます。以前はメモリの問題がありました! :-) – cplexstudent

+0

私はlazyconstraintとusercutcallbackを実装し、ランダムに生成されたいくつかの例についてテストを開始しました。 1つの例が終了しない場合は、無限ループに陥っているように見えます。ある時点では、繰り返し回数が増えておらず、usercutcallbackによって検出された違反の不等式が常に存在するからです。 私のすべてのIloNumVarArraysは整数として宣言されていますが、無限ループ内で最適化プロセスを停止すると、整数ではない小数の配列のエントリがあります。これも可能ですか? – cplexstudent

+0

コールバック内にブレークポイントを置き、すべての処理が意図したとおりに行われていることを確認する必要があります。間違ったイテレータを置くのはとても簡単です(あなたは前/後の位置をとっているかもしれません)、または何かを忘れてしまいます。エラーの余地が非常にあります。そこに何かを混乱させると、CPLEXはナッツになり、あらゆる種類の狂気のことをするでしょう。 – Jacko

関連する問題