<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Hello,<br>
    <br>
    I'm trying to write intermediate solutions using a CbcEventHandler
    similarly to what is done in Cbc/examples/driver4.cpp. However, I'd
    like to output the solution to the initial, non-preprocessed model.
    I've tried to replicate what it is done in CbcMain1, after the
    B&B search finishes, in particular calling
    CglPreProcess::postProcess, along with some more handwaving based on
    what Cbc's nextBestSolution command does.<br>
    <br>
    Alas, it's not working out. Not only am I not getting a solution
    with the same number of columns as the original model, but accessing
    the the ClpSimplex's columnNames segfaults at some point.<br>
    <br>
    Here's the code I have so far. Any hints you provide would be very
    useful at this point! Am I in the right track, or should I be doing
    something completely different? (E.g., I've considered grabbing the
    solution to the preprocessed model and feed it to
    computeCompleteSolution() from CbcMipStartIO.cpp, assuming I can get
    accurate variable names from the preprocessed model.)<br>
    <br>
    <pre style="color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="preprocessor" style="color: rgb(72, 61, 139);">#include</span> <span class="string" style="color: rgb(139, 34, 82);"><algorithm></span>
<span class="preprocessor" style="color: rgb(72, 61, 139);">#include</span> <span class="string" style="color: rgb(139, 34, 82);"><fstream></span>
<span class="preprocessor" style="color: rgb(72, 61, 139);">#include</span> <span class="string" style="color: rgb(139, 34, 82);"><sstream></span>

<span class="preprocessor" style="color: rgb(72, 61, 139);">#include</span> <span class="string" style="color: rgb(139, 34, 82);">"CbcModel.hpp"</span>
<span class="preprocessor" style="color: rgb(72, 61, 139);">#include</span> <span class="string" style="color: rgb(139, 34, 82);">"OsiClpSolverInterface.hpp"</span>
<span class="preprocessor" style="color: rgb(72, 61, 139);">#include</span> <span class="string" style="color: rgb(139, 34, 82);">"CbcSolver.hpp"</span>
<span class="preprocessor" style="color: rgb(72, 61, 139);">#include</span> <span class="string" style="color: rgb(139, 34, 82);">"CbcEventHandler.hpp"</span>
<span class="preprocessor" style="color: rgb(72, 61, 139);">#include</span> <span class="string" style="color: rgb(139, 34, 82);">"CglPreProcess.hpp"</span>

<span class="keyword" style="color: rgb(160, 32, 240);">extern</span> <span class="type" style="color: rgb(34, 139, 34);">CglPreProcess</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">cbcPreProcessPointer</span>;

<span class="keyword" style="color: rgb(160, 32, 240);">class</span> <span class="type" style="color: rgb(34, 139, 34);">SolutionWriter</span> : <span class="keyword" style="color: rgb(160, 32, 240);">public</span> <span class="type" style="color: rgb(34, 139, 34);">CbcEventHandler</span> {
    <span class="type" style="color: rgb(34, 139, 34);">CbcModel</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">original_model_</span>;
    <span class="type" style="color: rgb(34, 139, 34);">string</span> <span class="variable-name" style="color: rgb(160, 82, 45);">solution_prefix_</span>;
    <span class="type" style="color: rgb(34, 139, 34);">string</span> <span class="variable-name" style="color: rgb(160, 82, 45);">solution_directory_</span>;
    <span class="constant" style="color: rgb(0, 139, 139);">std</span>::<span class="type" style="color: rgb(34, 139, 34);">set</span><<span class="type" style="color: rgb(34, 139, 34);">int</span>> <span class="variable-name" style="color: rgb(160, 82, 45);">seen_solutions_</span>;<span class="comment" style="color: rgb(178, 34, 34);">
</span>    <span class="type" style="color: rgb(34, 139, 34);">int</span> <span class="variable-name" style="color: rgb(160, 82, 45);">external_solution_id_</span> = 1;

<span class="keyword" style="color: rgb(160, 32, 240);">public</span>:
    <span class="keyword" style="color: rgb(160, 32, 240);">virtual</span> <span class="constant" style="color: rgb(0, 139, 139);">CbcEventHandler</span>::<span class="type" style="color: rgb(34, 139, 34);">CbcAction</span> <span class="function-name" style="color: rgb(0, 0, 255);">event</span>(<span class="type" style="color: rgb(34, 139, 34);">CbcEvent</span> <span class="variable-name" style="color: rgb(160, 82, 45);">whichEvent</span>) {
        <span class="comment-delimiter" style="color: rgb(178, 34, 34);">// </span><span class="comment" style="color: rgb(178, 34, 34);">If in sub tree carry on
</span>        <span class="keyword" style="color: rgb(160, 32, 240);">if</span> (<span class="negation-char">!</span>model_->parentModel()) {
            <span class="type" style="color: rgb(34, 139, 34);">int</span> <span class="variable-name" style="color: rgb(160, 82, 45);">solution_id</span> = model_->getSolutionCount();

            <span class="keyword" style="color: rgb(160, 32, 240);">if</span> ((whichEvent == solution || whichEvent == heuristicSolution)
                && seen_solutions_.find(solution_id) == seen_solutions_.end()) {

                seen_solutions_.insert(solution_id);

                <span class="keyword" style="color: rgb(160, 32, 240);">const</span> <span class="type" style="color: rgb(34, 139, 34);">double</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">incumbent_solution</span> = model_->bestSolution();

                <span class="keyword" style="color: rgb(160, 32, 240);">auto</span> <span class="type" style="color: rgb(34, 139, 34);">solver</span> = <span class="keyword" style="color: rgb(160, 32, 240);">dynamic_cast</span><OsiClpSolverInterface*> (model_->solver());
                <span class="type" style="color: rgb(34, 139, 34);">ClpSimplex</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">current_lp_solver</span> = solver->getModelPtr();
                <span class="type" style="color: rgb(34, 139, 34);">ClpSimplex</span> <span class="variable-name" style="color: rgb(160, 82, 45);">lp_solver</span>{*current_lp_solver};
                solver->swapModelPtr(&lp_solver);

                <span class="type" style="color: rgb(34, 139, 34);">double</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">lp_solver_solution</span> = lp_solver.primalColumnSolution();
                <span class="type" style="color: rgb(34, 139, 34);">double</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">lp_solver_lower</span> = lp_solver.columnLower();
                <span class="type" style="color: rgb(34, 139, 34);">double</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">lp_solver_upper</span> = lp_solver.columnUpper();
                <span class="type" style="color: rgb(34, 139, 34);">int</span> <span class="variable-name" style="color: rgb(160, 82, 45);">lp_solver_number_columns</span> = lp_solver.numberColumns();

                memcpy(lp_solver_solution, incumbent_solution,
                       <span class="type" style="color: rgb(34, 139, 34);">lp_solver_number_columns</span> * <span class="keyword" style="color: rgb(160, 32, 240);">sizeof</span>(<span class="type" style="color: rgb(34, 139, 34);">double</span>));
                <span class="keyword" style="color: rgb(160, 32, 240);">for</span> (<span class="type" style="color: rgb(34, 139, 34);">int</span> <span class="variable-name" style="color: rgb(160, 82, 45);">i</span> = 0; i < lp_solver_number_columns; i++) {
                    <span class="keyword" style="color: rgb(160, 32, 240);">if</span> (solver->isInteger(i)) {
                        <span class="type" style="color: rgb(34, 139, 34);">double</span> <span class="variable-name" style="color: rgb(160, 82, 45);">x</span> = floor(lp_solver_solution[i] + 0.5);
                        lp_solver_lower[i] = lp_solver_upper[i] = x;
                    }
                }
                lp_solver.allSlackBasis();
                lp_solver.initialSolve();
                lp_solver.computeObjectiveValue(<span class="constant" style="color: rgb(0, 139, 139);">false</span>);

                cbcPreProcessPointer->postProcess(*solver);

                <span class="comment-delimiter" style="color: rgb(178, 34, 34);">// </span><span class="comment" style="color: rgb(178, 34, 34);">write solution
</span>
                <span class="comment-delimiter" style="color: rgb(178, 34, 34);">// </span><span class="comment" style="color: rgb(178, 34, 34);"><span class="warning" style="color: rgb(255, 0, 0); font-weight: bold;">XXX</span></span><span class="comment" style="color: rgb(178, 34, 34);">: some wishful thinking here: hoping we would see the
</span>                <span class="comment-delimiter" style="color: rgb(178, 34, 34);">// </span><span class="comment" style="color: rgb(178, 34, 34);">original number of columns at this point.
</span>                lp_solver_number_columns = lp_solver.numberColumns();
                <span class="keyword" style="color: rgb(160, 32, 240);">const</span> <span class="type" style="color: rgb(34, 139, 34);">double</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">solution</span> = solver->getColSolution();
                <span class="keyword" style="color: rgb(160, 32, 240);">const</span> <span class="type" style="color: rgb(34, 139, 34);">double</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">reduced_costs</span> = solver->getReducedCost();
                assert(solution && reduced_costs);
                <span class="keyword" style="color: rgb(160, 32, 240);">auto</span> <span class="type" style="color: rgb(34, 139, 34);">column_names</span> = lp_solver.columnNames();
                <span class="constant" style="color: rgb(0, 139, 139);">string</span>::<span class="type" style="color: rgb(34, 139, 34);">size_type</span> <span class="variable-name" style="color: rgb(160, 82, 45);">max_name_length</span> = 0;
                <span class="keyword" style="color: rgb(160, 32, 240);">for</span> (<span class="keyword" style="color: rgb(160, 32, 240);">auto</span> <span class="keyword" style="color: rgb(160, 32, 240);">const</span>& <span class="variable-name" style="color: rgb(160, 82, 45);">name</span>: *column_names) {
                    max_name_length = <span class="constant" style="color: rgb(0, 139, 139);">std</span>::max(max_name_length, name.length());
                }

                <span class="type" style="color: rgb(34, 139, 34);">stringstream</span> <span class="variable-name" style="color: rgb(160, 82, 45);">filename</span>;
                filename << solution_directory_
                         << solution_prefix_
                         << external_solution_id_++
                         << <span class="string" style="color: rgb(139, 34, 82);">".txt"</span>;

                {
                    <span class="type" style="color: rgb(34, 139, 34);">ofstream</span> <span class="variable-name" style="color: rgb(160, 82, 45);">out</span>(filename.str());

                    <span class="keyword" style="color: rgb(160, 32, 240);">if</span> (<span class="negation-char">!</span>out.is_open()) {
                        <span class="constant" style="color: rgb(0, 139, 139);">std</span>::cout << <span class="string" style="color: rgb(139, 34, 82);">"Couldn't open "</span>
                                  << filename.str() << <span class="string" style="color: rgb(139, 34, 82);">" for writing "</span> << endl;
                        abort();
                    }

                    <span class="type" style="color: rgb(34, 139, 34);">char</span> <span class="variable-name" style="color: rgb(160, 82, 45);">buf</span>[100];
                    snprintf(buf, <span class="keyword" style="color: rgb(160, 32, 240);">sizeof</span> buf, <span class="string" style="color: rgb(139, 34, 82);">"Incumbent - objective value %.8f\n"</span>,
                             lp_solver.getObjValue());
                    out << buf;

                    <span class="keyword" style="color: rgb(160, 32, 240);">for</span> (<span class="type" style="color: rgb(34, 139, 34);">int</span> <span class="variable-name" style="color: rgb(160, 82, 45);">i</span> = 0; i < lp_solver_number_columns; i++) {
                        <span class="keyword" style="color: rgb(160, 32, 240);">if</span> (fabs(solution[i]) > 1.0e-8) {
                            <span class="keyword" style="color: rgb(160, 32, 240);">auto</span>& <span class="variable-name" style="color: rgb(160, 82, 45);">name</span> = (*column_names)[i];

                            <span class="type" style="color: rgb(34, 139, 34);">string</span> <span class="variable-name" style="color: rgb(160, 82, 45);">padding</span>(<span class="constant" style="color: rgb(0, 139, 139);">std</span>::max(max_name_length, name.length())
                                           - name.length(), <span class="string" style="color: rgb(139, 34, 82);">' '</span>);

                            <span class="type" style="color: rgb(34, 139, 34);">char</span> <span class="variable-name" style="color: rgb(160, 82, 45);">buf</span>[100];
                            snprintf(buf, <span class="keyword" style="color: rgb(160, 32, 240);">sizeof</span> buf,<span class="string" style="color: rgb(139, 34, 82);">"%7d %s%s %15.8g %15.8g\n"</span>,
                                     i,
                                     name.c_str(),
                                     padding.c_str(),
                                     solution[i],
                                     reduced_costs[i]);
                            out << buf;
                        }
                    }
                }

                <span class="constant" style="color: rgb(0, 139, 139);">std</span>::cout << <span class="string" style="color: rgb(139, 34, 82);">"[SolutionWriter] Solution saved to "</span> << filename.str() << <span class="constant" style="color: rgb(0, 139, 139);">std</span>::endl;

                solver->swapModelPtr(current_lp_solver);
            }
        }

        <span class="keyword" style="color: rgb(160, 32, 240);">return</span> noAction; <span class="comment-delimiter" style="color: rgb(178, 34, 34);">// </span><span class="comment" style="color: rgb(178, 34, 34);">carry on
</span>    }

    <span class="function-name" style="color: rgb(0, 0, 255);">SolutionWriter</span>() = <span class="keyword" style="color: rgb(160, 32, 240);">delete</span>;
    <span class="function-name" style="color: rgb(0, 0, 255);">SolutionWriter</span>(<span class="keyword" style="color: rgb(160, 32, 240);">const</span> <span class="type" style="color: rgb(34, 139, 34);">SolutionWriter</span>&) = <span class="keyword" style="color: rgb(160, 32, 240);">default</span>;
    <span class="function-name" style="color: rgb(0, 0, 255);">SolutionWriter</span>(<span class="keyword" style="color: rgb(160, 32, 240);">const</span> <span class="type" style="color: rgb(34, 139, 34);">SolutionWriter</span>&&) = <span class="keyword" style="color: rgb(160, 32, 240);">delete</span>;

    <span class="function-name" style="color: rgb(0, 0, 255);">SolutionWriter</span>(<span class="type" style="color: rgb(34, 139, 34);">CbcModel</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">model</span>,
                   <span class="type" style="color: rgb(34, 139, 34);">CbcModel</span>* <span class="variable-name" style="color: rgb(160, 82, 45);">original</span>,
                   <span class="keyword" style="color: rgb(160, 32, 240);">const</span> <span class="type" style="color: rgb(34, 139, 34);">string</span>& <span class="variable-name" style="color: rgb(160, 82, 45);">solution_prefix</span> = <span class="string" style="color: rgb(139, 34, 82);">"solution"</span>,
                   <span class="keyword" style="color: rgb(160, 32, 240);">const</span> <span class="type" style="color: rgb(34, 139, 34);">string</span>& <span class="variable-name" style="color: rgb(160, 82, 45);">solution_directory</span> = <span class="string" style="color: rgb(139, 34, 82);">"."</span>)
        : CbcEventHandler(model),
          original_model_(original),
          solution_prefix_(solution_prefix),
          solution_directory_(solution_directory) {
        <span class="keyword" style="color: rgb(160, 32, 240);">if</span> (solution_directory_.back() != <span class="string" style="color: rgb(139, 34, 82);">'/'</span>) solution_directory_.append(<span class="string" style="color: rgb(139, 34, 82);">"/"</span>);
    }

    <span class="keyword" style="color: rgb(160, 32, 240);">virtual</span> <span class="type" style="color: rgb(34, 139, 34);">CbcEventHandler</span>* <span class="function-name" style="color: rgb(0, 0, 255);">clone</span>() <span class="keyword" style="color: rgb(160, 32, 240);">const</span> <span class="type" style="color: rgb(34, 139, 34);">override</span> {
        <span class="keyword" style="color: rgb(160, 32, 240);">return</span> <span class="keyword" style="color: rgb(160, 32, 240);">new</span> <span class="type" style="color: rgb(34, 139, 34);">SolutionWriter</span>(*<span class="keyword" style="color: rgb(160, 32, 240);">this</span>);
    }
};</pre>
    <br>
    Thanks in advance,<br>
    Luís<br>
  </body>
</html>