#!/usr/bin/perl -w

sub usage;

if (scalar(@ARGV) > 2 || scalar(@ARGV) == 0) {
  usage();
}

$Cformat = 0;
$fn = shift @ARGV;

if (scalar(@ARGV)) {
  if ($fn eq "-C") {
      $Cformat = 1;
  } else {
      usage();
  }
  $fn = shift @ARGV;
}


open IN, "< $fn" or die "Cannot open file '$fn'";

while (<IN>) {

  chomp;

  if (m/Final best parameter configuration: (.*)/) {

    @values = split(', ', $1);

    foreach (@values) {

      s/advance/(IloCplex::IntParam) CPX_PARAM_ADVIND/;
      s/barrier_algorithm/(IloCplex::IntParam) CPX_PARAM_BARALG/;
      s/barrier_colnonzeros/(IloCplex::IntParam) CPX_PARAM_BARCOLNZ/;
      s/barrier_convergetol/(IloCplex::NumParam) CPX_PARAM_BAREPCOMP/;
      s/barrier_crossover/(IloCplex::IntParam) CPX_PARAM_BARCROSSALG/;
      s/barrier_limits_corrections/(IloCplex::IntParam) CPX_PARAM_BARMAXCOR/;
      s/barrier_limits_growth/(IloCplex::NumParam) CPX_PARAM_BARGROWTH/;
      s/barrier_ordering/(IloCplex::IntParam) CPX_PARAM_BARORDER/;
      s/barrier_qcpconvergetol/(IloCplex::NumParam) CPX_PARAM_BARQCPEPCOMP/;
      s/barrier_startalg/(IloCplex::IntParam) CPX_PARAM_BARSTARTALG/;
      s/emphasis_memory/(IloCplex::BoolParam) CPX_PARAM_MEMORYEMPHASIS/;
      s/emphasis_mip/(IloCplex::IntParam) CPX_PARAM_MIPEMPHASIS/;
      s/emphasis_numerical/(IloCplex::BoolParam) CPX_PARAM_NUMERICALEMPHASIS/;
      s/feasopt_mode/(IloCplex::IntParam) CPX_PARAM_FEASOPTMODE/;
      s/feasopt_tolerance/(IloCplex::NumParam) CPX_PARAM_EPRELAX/;
      s/lpmethod/(IloCplex::IntParam) CPX_PARAM_LPMETHOD/;
      s/mip_cuts_cliques/(IloCplex::IntParam) CPX_PARAM_CLIQUES/;
      s/mip_cuts_covers/(IloCplex::IntParam) CPX_PARAM_COVERS/;
      s/mip_cuts_disjunctive/(IloCplex::IntParam) CPX_PARAM_DISJCUTS/;
      s/mip_cuts_flowcovers/(IloCplex::IntParam) CPX_PARAM_FLOWCOVERS/;
      s/mip_cuts_gomory/(IloCplex::IntParam) CPX_PARAM_FRACCUTS/;
      s/mip_cuts_gubcovers/(IloCplex::IntParam) CPX_PARAM_GUBCOVERS/;
      s/mip_cuts_implied/(IloCplex::IntParam) CPX_PARAM_IMPLBD/;
      s/mip_cuts_mircut/(IloCplex::IntParam) CPX_PARAM_MIRCUTS/;
      s/mip_cuts_pathcut/(IloCplex::IntParam) CPX_PARAM_FLOWPATHS/;
      s/mip_limits_aggforcut/(IloCplex::IntParam) CPX_PARAM_AGGCUTLIM/;
      s/mip_limits_cutpasses/(IloCplex::IntParam) CPX_PARAM_CUTPASS/;
      s/mip_limits_cutsfactor/(IloCplex::NumParam) CPX_PARAM_CUTSFACTOR/;
      s/mip_limits_gomorycand/(IloCplex::IntParam) CPX_PARAM_FRACCAND/;
      s/mip_limits_gomorypass/(IloCplex::IntParam) CPX_PARAM_FRACPASS/;
      s/mip_limits_polishtime/(IloCplex::NumParam) CPX_PARAM_POLISHTIME/;
      s/mip_limits_probetime/(IloCplex::NumParam) CPX_PARAM_PROBETIME/;
      s/mip_limits_repairtries/(IloCplex::IntParam) CPX_PARAM_REPAIRTRIES/;
      s/mip_limits_strongcand/(IloCplex::IntParam) CPX_PARAM_STRONGCANDLIM/;
      s/mip_limits_strongit/(IloCplex::IntParam) CPX_PARAM_STRONGITLIM/;
      s/mip_limits_submipnodelim/(IloCplex::IntParam) CPX_PARAM_SUBMIPNODELIM/;
      s/mip_ordertype/(IloCplex::IntParam) CPX_PARAM_MIPORDTYPE/;
      s/mip_strategy_backtrack/(IloCplex::NumParam) CPX_PARAM_BTTOL/;
      s/mip_strategy_bbinterval/(IloCplex::IntParam) CPX_PARAM_BBINTERVAL/;
      s/mip_strategy_branch/(IloCplex::IntParam) CPX_PARAM_BRDIR/;
      s/mip_strategy_dive/(IloCplex::IntParam) CPX_PARAM_DIVETYPE/;
      s/mip_strategy_file/(IloCplex::IntParam) CPX_PARAM_NODEFILEIND/;
      s/mip_strategy_heuristicfreq/(IloCplex::IntParam) CPX_PARAM_HEURFREQ/;
      s/mip_strategy_lbheur/(IloCplex::BoolParam) CPX_PARAM_LBHEUR/;
      s/mip_strategy_nodeselect/(IloCplex::IntParam) CPX_PARAM_NODESEL/;
      s/mip_strategy_order/(IloCplex::BoolParam) CPX_PARAM_MIPORDIND/;
      s/mip_strategy_presolvenode/(IloCplex::IntParam) CPX_PARAM_PRESLVND/;
      s/mip_strategy_probe/(IloCplex::IntParam) CPX_PARAM_PROBE/;
      s/mip_strategy_rinsheur/(IloCplex::IntParam) CPX_PARAM_RINSHEUR/;
      s/mip_strategy_startalgorithm/(IloCplex::IntParam) CPX_PARAM_STARTALG/;
      s/mip_strategy_subalgorithm/(IloCplex::IntParam) CPX_PARAM_SUBALG/;
      s/mip_strategy_variableselect/(IloCplex::IntParam) CPX_PARAM_VARSEL/;
      s/network_netfind/(IloCplex::IntParam) CPX_PARAM_NETFIND/;
      s/network_pricing/(IloCplex::IntParam) CPX_PARAM_NETPPRIIND/;
      s/preprocessing_aggregator/(IloCplex::IntParam) CPX_PARAM_AGGIND/;
      s/preprocessing_boundstrength/(IloCplex::IntParam) CPX_PARAM_BNDSTRENIND/;
      s/preprocessing_coeffreduce/(IloCplex::IntParam) CPX_PARAM_COEREDIND/;
      s/preprocessing_dependency/(IloCplex::IntParam) CPX_PARAM_DEPIND/;
      s/preprocessing_dual/(IloCplex::IntParam) CPX_PARAM_PREDUAL/;
      s/preprocessing_fill/(IloCplex::IntParam) CPX_PARAM_AGGFILL/;
      s/preprocessing_numpass/(IloCplex::IntParam) CPX_PARAM_PREPASS/;
      s/preprocessing_presolve/(IloCplex::IntParam) CPX_PARAM_PREIND/;
      s/preprocessing_qpmakepsd/(IloCplex::BoolParam) CPX_PARAM_QPMAKEPSDIND/;
      s/preprocessing_reduce/(IloCplex::IntParam) CPX_PARAM_REDUCE/;
      s/preprocessing_relax/(IloCplex::IntParam) CPX_PARAM_RELAXPREIND/;
      s/preprocessing_repeatpresolve/(IloCplex::IntParam) CPX_PARAM_REPEATPRESOLVE/;
      s/preprocessing_symmetry/(IloCplex::IntParam) CPX_PARAM_SYMMETRY/;
      s/qpmethod/(IloCplex::IntParam) CPX_PARAM_QPMETHOD/;
      s/read_scale/(IloCplex::IntParam) CPX_PARAM_SCAIND/;
      s/sifting_algorithm/(IloCplex::IntParam) CPX_PARAM_SIFTALG/;
      s/simplex_crash/(IloCplex::IntParam) CPX_PARAM_CRAIND/;
      s/simplex_dgradient/(IloCplex::IntParam) CPX_PARAM_DPRIIND/;
      s/simplex_limits_perturbation/(IloCplex::IntParam) CPX_PARAM_PERLIM/;
      s/simplex_limits_singularity/(IloCplex::IntParam) CPX_PARAM_SINGLIM/;

      if (m/simplex_perturbation=([^ ]*).*/) {
	$_ = "(IloCplex::BoolParam) CPX_PARAM_PERIND=$1";
      }

      s/simplex_pgradient/(IloCplex::IntParam) CPX_PARAM_PPRIIND/;
      s/simplex_pricing/(IloCplex::IntParam) CPX_PARAM_PRICELIM/;
      s/simplex_refactor/(IloCplex::IntParam) CPX_PARAM_REINV/;
      s/simplex_tolerances_feasibility/(IloCplex::NumParam) CPX_PARAM_EPINT/;
      s/simplex_tolerances_markowitz/(IloCplex::NumParam) CPX_PARAM_EPMRK/;
      s/simplex_tolerances_optimality/(IloCplex::NumParam) CPX_PARAM_EPOPT/;
      s/=no/=0/;
      s/=yes/=1/;

      s/=/, /;

      if ($Cformat == 1) {
	s/\(IloCplex::IntParam\)/CPXsetintparam(env,/;
        s/\(IloCplex::BoolParam\)/CPXsetintparam(env,/;
	s/\(IloCplex::NumParam\)/CPXsetdoubleparam(env,/;
        print "$_);\n";

      } else {
        print "cplex->setParam($_);\n";
      }

    }

  }

}

exit(0);


sub usage {
  print "translateResultToCpp: a utility to convert the results from ParamILS into code\n";
  print "                      for insertion into C or C++ programs\n\n";
  print "Usage: translateResultToCpp [-C] <name of ParamILS result.txt file>\n";
  print "\t-C : Write the output in C format, rather than C++ format\n";
  print "\nAny bugs or issues, contact Andrew Coles (firstname.lastname\@cis.strath.ac.uk)\n";
  exit(1);
}
