<commit_before>/*
 * GenModelOsi.cpp
 *
 *  Created on: 2012-10-01
 *      Author: mbouchard
 */


#include "GenModelOsi.h"

#ifdef OSI_MODULE
#include "ProblemReaderOsi.h"
#include "CbcHeuristicFPump.hpp"
#include "CbcHeuristicRINS.hpp"
#include "CbcHeuristicLocal.hpp"
#include "CbcHeuristicDiveCoefficient.hpp"
#include "CbcHeuristicDiveFractional.hpp"
#include <limits>

using namespace std;

void printmsg(char* msg, GenModelOsi* p)
{
    if(false && p->boolParam.count("log_output_stdout") > 0 && p->boolParam["log_output_stdout"])
        printf("%s", msg);
}

long GenModelOsi::WriteProblemToLpFile(string filename)
{
    if(!bcreated)
        throw string("WriteProblemToLpFile() not available : Problem not created yet;");
    
    OsiData* d = static_cast<OsiData*>(solverdata);
    d->model->writeLp(filename.c_str());
    return 0;
}

long GenModelOsi::WriteSolutionToFile(string filename)
{
    if(!bcreated)
        throw string("WriteSolutionToFile() not available : Problem not created yet;");
    
    FILE* f = fopen(filename.c_str(), "w");
    for(long i = 0; i < long(vars.n); i++)
	{
		if(fabs(vars.sol[i]) > 0.000001)
			fprintf(f, "%s :		%f\n", vars.name[i].c_str(), vars.sol[i]);
	}
    
    fclose(f);
    return 0;
}

long GenModelOsi::Solve()
{
    char tmp[4096];
    if(!bcreated)
        throw string("WriteSolutionToFile() not available : Problem not created yet;");
    OsiData* d = static_cast<OsiData*>(solverdata);
    d->model->setHintParam(OsiDoReducePrint,true,OsiHintTry);
    
    
    /*
    if(boolParam.count("mip") > 0 && boolParam["mip"])
    {
        printf("********* OSI Branch and bounds **************\n");
    	d->model->branchAndBound();
    }
    else if(boolParam.count("notroot") > 0 && boolParam["notroot"])
    {
        printf("********* OSI Resolve **************\n");
    	d->model->resolve();
    }
    else
    {
        printf("********* OSI Initial Solve **************\n");
        d->model->initialSolve();
    }
    */
    
    d->model->setHintParam(OsiDoReducePrint,true,OsiHintTry);

    // Set up some cut generators and defaults
    // Probing first as gets tight bounds on continuous

    CglProbing generator1;
    // can not use objective
    generator1.setUsingObjective(false);
    generator1.setMaxPass(3);
    generator1.setMaxProbe(100);
    generator1.setMaxLook(50);
    generator1.setRowCuts(3);
    
    CglGomory generator2;
    // try larger limit
    generator2.setLimit(30000);
    
    CglKnapsackCover generator3;
    
    CglOddHole generator4;
    generator4.setMinimumViolation(0.005);
    generator4.setMinimumViolationPer(0.00002);
    // try larger limit
    generator4.setMaximumEntries(50); //(200); //maybe originally 50
    
    CglClique generator5;
    generator5.setStarCliqueReport(false);
    generator5.setRowCliqueReport(false);
    
    CglMixedIntegerRounding mixedGen;
    CglFlowCover flowGen;
    // Add in generators (just at root)

    d->mipmodel = new CbcModel(*(d->model));
    // Add in generators
    // Only some generators work (and even then try without first)
    
    
    d->mipmodel->addCutGenerator(&generator1,1,"Probing");
    // Allow rounding heuristic

    d->mipmodel->addCutGenerator(&generator1,-99,"Probing",true,false,false,-1);
    d->mipmodel->addCutGenerator(&generator2,-99,"Gomory",true,false,false,-99);
    d->mipmodel->addCutGenerator(&generator3,-99,"Knapsack",true,false,false,-99);
    d->mipmodel->addCutGenerator(&generator4,-99,"OddHole",true,false,false,-99);
    d->mipmodel->addCutGenerator(&generator5,-99,"Clique",true,false,false,-99);
    d->mipmodel->addCutGenerator(&flowGen,-99,"FlowCover",true,false,false,-99);
    d->mipmodel->addCutGenerator(&mixedGen,-99,"MixedIntegerRounding",true,false,false,-100);
    
    CbcRounding rounding(*(d->mipmodel));
    rounding.setHeuristicName("Rounding");
    // do not add yet as don't know how to deal with quadratic objective
    d->mipmodel->addHeuristic(&rounding);
    rounding.setHeuristicName("Greedy cover");
    CbcHeuristicGreedyCover greedy(*(d->mipmodel));
    // Use original upper and perturb more
    greedy.setAlgorithm(11);
    greedy.setHeuristicName("Greedy cover");
    d->mipmodel->addHeuristic(&greedy);

    // Redundant definition of default branching (as Default == User)
    //CbcBranchUserDecision branch;
    //d->mipmodel->setBranchingMethod(&branch);

    // Definition of node choice
    //CbcCompareUser compare;
    // breadth first
    //compare.setWeight(0.0);
    //d->mipmodel->setNodeComparison(compare);


    // Do initial solve to continuous
    d->mipmodel->initialSolve();
    
    double objValue = d->mipmodel->getObjValue();
    
    CbcHeuristicDiveCoefficient heuristicDC(*(d->mipmodel));
    heuristicDC.setHeuristicName("DiveCoefficient");
    // allow to exit if close enough to optimum
    heuristicDC.setSwitches(1);
    d->mipmodel->addHeuristic(&heuristicDC);
    CbcHeuristicDiveFractional heuristicDF(*(d->mipmodel));
    heuristicDF.setHeuristicName("DiveFractional");
    heuristicDF.setSwitches(1);
    d->mipmodel->addHeuristic(&heuristicDF);
    CbcHeuristicFPump pump(*(d->mipmodel));
    // allow to exit if close enough to optimum
    // plus some dubious options
    pump.setSwitches(1+4+8);
    pump.setMaximumTime(3600);
    pump.setMaximumPasses(50); //100);
    pump.setMaximumRetries(10); //(1);
    pump.setFixOnReducedCosts(1);
    pump.setHeuristicName("Feasibility pump 1");
    pump.setFractionSmall(1.0);
    pump.setWhen(13);
        pump.setFakeCutoff(objValue+0.01*fabs(objValue));
        pump.setReducedCostMultiplier(0.1);
        pump.setFeasibilityPumpOptions(80);
    d->mipmodel->addHeuristic(&pump);
        pump.setHeuristicName("Feasibility pump 2");
        pump.setFakeCutoff(objValue+0.05*fabs(objValue));
        pump.setFeasibilityPumpOptions(80);
    d->mipmodel->addHeuristic(&pump);
        pump.setHeuristicName("Feasibility pump 3");
        pump.setFakeCutoff(objValue+0.01*fabs(objValue));
        pump.setReducedCostMultiplier(0.1);
        pump.setFeasibilityPumpOptions(80);
    d->mipmodel->addHeuristic(&pump);
        pump.setHeuristicName("Feasibility pump 4");
        pump.setFakeCutoff(objValue+0.05*fabs(objValue));
        pump.setReducedCostMultiplier(1.0);
        pump.setFeasibilityPumpOptions(80);
        pump.setMaximumTime(200);
    d->mipmodel->addHeuristic(&pump);
    CbcHeuristicRINS rins(*(d->mipmodel));
    rins.setHeuristicName("RINS");
    rins.setFractionSmall(0.5);
    rins.setDecayFactor(5.0);
    d->mipmodel->addHeuristic(&rins) ;
    CbcHeuristicLocal local(*(d->mipmodel));
    local.setHeuristicName("LOCAL");
    local.setFractionSmall(0.5);
    local.setSearchType(1);
    d->mipmodel->addHeuristic(&local) ;
    if(longParam.count("nb_threads") ==  0 && longParam["nb_threads"] >= 1)
    {
        d->mipmodel->setThreadMode(7);
        d->mipmodel->setNumberThreads(longParam["nb_threads"]);
    }
    
    // Could tune more
    d->mipmodel->setMinimumDrop(CoinMin(1.0, fabs(d->mipmodel->getMinimizationObjValue())*1.0e-3+1.0e-4));
    
    d->mipmodel->setMaximumCutPassesAtRoot(1); // (50);
    d->mipmodel->setMaximumCutPasses(10); //(100);
    
    // Switch off strong branching if wanted
    //d->mipmodel->setNumberStrong(5);
    
    d->mipmodel->solver()->setIntParam(OsiMaxNumIterationHotStart,10000);
    
    // If time is given then stop after that number of minutes
    if (dblParam.count("time_limit") > 0)
    {
        snprintf(tmp,4096,"Stopping after %f seconds\n", dblParam["time_limit"]); printmsg(tmp, this);
        d->mipmodel->setDblParam(CbcModel::CbcMaximumSeconds, dblParam["time_limit"]);
    }

    // Switch off most output
    if (d->mipmodel->getNumCols()<3000)
    {
        if(false && boolParam.count("log_output_stdout") > 0 && boolParam["log_output_stdout"])
            d->mipmodel->messageHandler()->setLogLevel(1);
        else
            d->mipmodel->messageHandler()->setLogLevel(0);
        //d->model->solver()->messageHandler()->setLogLevel(0);
    }
    else
    {
        if(false && boolParam.count("log_output_stdout") > 0 && boolParam["log_output_stdout"])
        {
            d->mipmodel->messageHandler()->setLogLevel(2);
            //d->mipmodel->solver()->messageHandler()->setLogLevel(1);
        }
        else
        {
            d->mipmodel->messageHandler()->setLogLevel(0);
            //d->mipmodel->solver()->messageHandler()->setLogLevel(0);
        }
    }
    
    if(false && boolParam.count("log_output_stdout") > 0 && boolParam["log_output_stdout"])
        d->mipmodel->setPrintFrequency(1);//(50);
    else
        d->mipmodel->setPrintFrequency(0);

    double time1 = CoinCpuTime();
    
    // Do complete search
    d->mipmodel->branchAndBound();
    
    snprintf(tmp,4096," took %f seconds, %d nodes with objective %f, %s\n",
           CoinCpuTime()-time1, d->mipmodel->getNodeCount(), d->mipmodel->getObjValue(), (!d->mipmodel->status() ? " Finished" : " Not finished")); printmsg(tmp, this);

    // Print more statistics
    snprintf(tmp,4096,"Cuts at root node changed objective from %f to %f\n",
                             d->mipmodel->getContinuousObjective(), d->mipmodel->rootObjectiveAfterCuts()); printmsg(tmp, this);
    
    int numberGenerators = d->mipmodel->numberCutGenerators();
    for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++)
    {
        CbcCutGenerator * generator = d->mipmodel->cutGenerator(iGenerator);
        snprintf(tmp,4096,"%s was tried %d times and created %d cuts of which %d were active after adding rounds of cuts\n", generator->cutGeneratorName(),
               generator->numberTimesEntered(),generator->numberCutsInTotal(), generator->numberCutsActive()); printmsg(tmp, this);<commit_msg>Fix the log message bug and lp output filename bug<commit_after>/*
 * GenModelOsi.cpp
 *
 *  Created on: 2012-10-01
 *      Author: mbouchard
 */


#include "GenModelOsi.h"

#ifdef OSI_MODULE
#include "ProblemReaderOsi.h"
#include "CbcHeuristicFPump.hpp"
#include "CbcHeuristicRINS.hpp"
#include "CbcHeuristicLocal.hpp"
#include "CbcHeuristicDiveCoefficient.hpp"
#include "CbcHeuristicDiveFractional.hpp"
#include <limits>

using namespace std;

void printmsg(char* msg, GenModelOsi* p)
{
    if(p->boolParam.count("log_output_stdout") > 0 && p->boolParam["log_output_stdout"])
        printf("%s", msg);
}

long GenModelOsi::WriteProblemToLpFile(string filename)
{
    if(!bcreated)
        throw string("WriteProblemToLpFile() not available : Problem not created yet;");
    
    size_t pos = filename.rfind(".lp");
    OsiData* d = static_cast<OsiData*>(solverdata);
    d->model->writeLp(str.filename(0,pos).c_str());
    return 0;
}

long GenModelOsi::WriteSolutionToFile(string filename)
{
    if(!bcreated)
        throw string("WriteSolutionToFile() not available : Problem not created yet;");
    
    FILE* f = fopen(filename.c_str(), "w");
    for(long i = 0; i < long(vars.n); i++)
	{
		if(fabs(vars.sol[i]) > 0.000001)
			fprintf(f, "%s :		%f\n", vars.name[i].c_str(), vars.sol[i]);
	}
    
    fclose(f);
    return 0;
}

long GenModelOsi::Solve()
{
    char tmp[4096];
    if(!bcreated)
        throw string("WriteSolutionToFile() not available : Problem not created yet;");
    OsiData* d = static_cast<OsiData*>(solverdata);
    d->model->setHintParam(OsiDoReducePrint,true,OsiHintTry);
    
    
    /*
    if(boolParam.count("mip") > 0 && boolParam["mip"])
    {
        printf("********* OSI Branch and bounds **************\n");
    	d->model->branchAndBound();
    }
    else if(boolParam.count("notroot") > 0 && boolParam["notroot"])
    {
        printf("********* OSI Resolve **************\n");
    	d->model->resolve();
    }
    else
    {
        printf("********* OSI Initial Solve **************\n");
        d->model->initialSolve();
    }
    */
    
    d->model->setHintParam(OsiDoReducePrint,true,OsiHintTry);

    // Set up some cut generators and defaults
    // Probing first as gets tight bounds on continuous

    CglProbing generator1;
    // can not use objective
    generator1.setUsingObjective(false);
    generator1.setMaxPass(3);
    generator1.setMaxProbe(100);
    generator1.setMaxLook(50);
    generator1.setRowCuts(3);
    
    CglGomory generator2;
    // try larger limit
    generator2.setLimit(30000);
    
    CglKnapsackCover generator3;
    
    CglOddHole generator4;
    generator4.setMinimumViolation(0.005);
    generator4.setMinimumViolationPer(0.00002);
    // try larger limit
    generator4.setMaximumEntries(50); //(200); //maybe originally 50
    
    CglClique generator5;
    generator5.setStarCliqueReport(false);
    generator5.setRowCliqueReport(false);
    
    CglMixedIntegerRounding mixedGen;
    CglFlowCover flowGen;
    // Add in generators (just at root)

    d->mipmodel = new CbcModel(*(d->model));
    // Add in generators
    // Only some generators work (and even then try without first)
    
    
    d->mipmodel->addCutGenerator(&generator1,1,"Probing");
    // Allow rounding heuristic

    d->mipmodel->addCutGenerator(&generator1,-99,"Probing",true,false,false,-1);
    d->mipmodel->addCutGenerator(&generator2,-99,"Gomory",true,false,false,-99);
    d->mipmodel->addCutGenerator(&generator3,-99,"Knapsack",true,false,false,-99);
    d->mipmodel->addCutGenerator(&generator4,-99,"OddHole",true,false,false,-99);
    d->mipmodel->addCutGenerator(&generator5,-99,"Clique",true,false,false,-99);
    d->mipmodel->addCutGenerator(&flowGen,-99,"FlowCover",true,false,false,-99);
    d->mipmodel->addCutGenerator(&mixedGen,-99,"MixedIntegerRounding",true,false,false,-100);
    
    CbcRounding rounding(*(d->mipmodel));
    rounding.setHeuristicName("Rounding");
    // do not add yet as don't know how to deal with quadratic objective
    d->mipmodel->addHeuristic(&rounding);
    rounding.setHeuristicName("Greedy cover");
    CbcHeuristicGreedyCover greedy(*(d->mipmodel));
    // Use original upper and perturb more
    greedy.setAlgorithm(11);
    greedy.setHeuristicName("Greedy cover");
    d->mipmodel->addHeuristic(&greedy);

    // Redundant definition of default branching (as Default == User)
    //CbcBranchUserDecision branch;
    //d->mipmodel->setBranchingMethod(&branch);

    // Definition of node choice
    //CbcCompareUser compare;
    // breadth first
    //compare.setWeight(0.0);
    //d->mipmodel->setNodeComparison(compare);


    // Do initial solve to continuous
    d->mipmodel->initialSolve();
    
    double objValue = d->mipmodel->getObjValue();
    
    CbcHeuristicDiveCoefficient heuristicDC(*(d->mipmodel));
    heuristicDC.setHeuristicName("DiveCoefficient");
    // allow to exit if close enough to optimum
    heuristicDC.setSwitches(1);
    d->mipmodel->addHeuristic(&heuristicDC);
    CbcHeuristicDiveFractional heuristicDF(*(d->mipmodel));
    heuristicDF.setHeuristicName("DiveFractional");
    heuristicDF.setSwitches(1);
    d->mipmodel->addHeuristic(&heuristicDF);
    CbcHeuristicFPump pump(*(d->mipmodel));
    // allow to exit if close enough to optimum
    // plus some dubious options
    pump.setSwitches(1+4+8);
    pump.setMaximumTime(3600);
    pump.setMaximumPasses(50); //100);
    pump.setMaximumRetries(10); //(1);
    pump.setFixOnReducedCosts(1);
    pump.setHeuristicName("Feasibility pump 1");
    pump.setFractionSmall(1.0);
    pump.setWhen(13);
        pump.setFakeCutoff(objValue+0.01*fabs(objValue));
        pump.setReducedCostMultiplier(0.1);
        pump.setFeasibilityPumpOptions(80);
    d->mipmodel->addHeuristic(&pump);
        pump.setHeuristicName("Feasibility pump 2");
        pump.setFakeCutoff(objValue+0.05*fabs(objValue));
        pump.setFeasibilityPumpOptions(80);
    d->mipmodel->addHeuristic(&pump);
        pump.setHeuristicName("Feasibility pump 3");
        pump.setFakeCutoff(objValue+0.01*fabs(objValue));
        pump.setReducedCostMultiplier(0.1);
        pump.setFeasibilityPumpOptions(80);
    d->mipmodel->addHeuristic(&pump);
        pump.setHeuristicName("Feasibility pump 4");
        pump.setFakeCutoff(objValue+0.05*fabs(objValue));
        pump.setReducedCostMultiplier(1.0);
        pump.setFeasibilityPumpOptions(80);
        pump.setMaximumTime(200);
    d->mipmodel->addHeuristic(&pump);
    CbcHeuristicRINS rins(*(d->mipmodel));
    rins.setHeuristicName("RINS");
    rins.setFractionSmall(0.5);
    rins.setDecayFactor(5.0);
    d->mipmodel->addHeuristic(&rins) ;
    CbcHeuristicLocal local(*(d->mipmodel));
    local.setHeuristicName("LOCAL");
    local.setFractionSmall(0.5);
    local.setSearchType(1);
    d->mipmodel->addHeuristic(&local) ;
    if(longParam.count("nb_threads") ==  0 && longParam["nb_threads"] >= 1)
    {
        d->mipmodel->setThreadMode(7);
        d->mipmodel->setNumberThreads(longParam["nb_threads"]);
    }
    
    // Could tune more
    d->mipmodel->setMinimumDrop(CoinMin(1.0, fabs(d->mipmodel->getMinimizationObjValue())*1.0e-3+1.0e-4));
    
    d->mipmodel->setMaximumCutPassesAtRoot(1); // (50);
    d->mipmodel->setMaximumCutPasses(10); //(100);
    
    // Switch off strong branching if wanted
    //d->mipmodel->setNumberStrong(5);
    
    d->mipmodel->solver()->setIntParam(OsiMaxNumIterationHotStart,10000);
    
    // If time is given then stop after that number of minutes
    if (dblParam.count("time_limit") > 0)
    {
        snprintf(tmp,4096,"Stopping after %f seconds\n", dblParam["time_limit"]); printmsg(tmp, this);
        d->mipmodel->setDblParam(CbcModel::CbcMaximumSeconds, dblParam["time_limit"]);
    }

    // Switch off most output
    if (d->mipmodel->getNumCols()<3000)
    {
        if(boolParam.count("log_output_stdout") > 0 && boolParam["log_output_stdout"])
            d->mipmodel->messageHandler()->setLogLevel(1);
        else
            d->mipmodel->messageHandler()->setLogLevel(0);
        //d->model->solver()->messageHandler()->setLogLevel(0);
    }
    else
    {
        if(boolParam.count("log_output_stdout") > 0 && boolParam["log_output_stdout"])
        {
            d->mipmodel->messageHandler()->setLogLevel(2);
            //d->mipmodel->solver()->messageHandler()->setLogLevel(1);
        }
        else
        {
            d->mipmodel->messageHandler()->setLogLevel(0);
            //d->mipmodel->solver()->messageHandler()->setLogLevel(0);
        }
    }
    
    if(boolParam.count("log_output_stdout") > 0 && boolParam["log_output_stdout"])
        d->mipmodel->setPrintFrequency(1);//(50);
    else
        d->mipmodel->setPrintFrequency(0);

    double time1 = CoinCpuTime();
    
    // Do complete search
    d->mipmodel->branchAndBound();
    
    snprintf(tmp,4096," took %f seconds, %d nodes with objective %f, %s\n",
           CoinCpuTime()-time1, d->mipmodel->getNodeCount(), d->mipmodel->getObjValue(), (!d->mipmodel->status() ? " Finished" : " Not finished")); printmsg(tmp, this);

    // Print more statistics
    snprintf(tmp,4096,"Cuts at root node changed objective from %f to %f\n",
                             d->mipmodel->getContinuousObjective(), d->mipmodel->rootObjectiveAfterCuts()); printmsg(tmp, this);
    
    int numberGenerators = d->mipmodel->numberCutGenerators();
    for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++)
    {
        CbcCutGenerator * generator = d->mipmodel->cutGenerator(iGenerator);
        snprintf(tmp,4096,"%s was tried %d times and created %d cuts of which %d were active after adding rounds of cuts\n", generator->cutGeneratorName(),
               generator->numberTimesEntered(),generator->numberCutsInTotal(), generator->numberCutsActive()); printmsg(tmp, this);
{'fraction_non_alphanumeric': 0.15579119086460033, 'fraction_numerical': 0.02390905383360522, 'mean_word_length': 3.5044776119402985, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 299, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4795524', 'n_tokens_mistral': 6920, 'n_tokens_neox': 6565, 'n_words': 1037}