Cbc-2.8.12/0000755000076600007660000000000012377555231010763 5ustar coincoinCbc-2.8.12/cbc.pc.in0000644000076600007660000000046111510112067012424 0ustar coincoinprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@/coin Name: CBC Description: COIN-OR Branch and Cut URL: https://projects.coin-or.org/Cbc Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lCbcSolver -lCbc @CBCLIB_PCLIBS@ Cflags: -I${includedir} Requires: @CBCLIB_PCREQUIRES@ Cbc-2.8.12/CbcSourceFilesTable2.csv0000644000076600007660000002061711305575712015367 0ustar coincoinFilename,,Group,Person,Inherits,Status,Age,CPP Lines,HPP Lines,Total Lines,libCbc,cbcSolve,cbcGeneric,Other Projects,First Object,Other Objects,Comment CbcBranchActual.cpp,,Branch,Edwin,,,8,5340,1823,7163,x,,,,Multiple,"CbcClique, CbcSos, CbcSimpleInteger, CbcIntegerBranchingObject, CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject, CbcSosBranchingObject, CbcBranchDefaultDecision, CbcFollowOn, CbcFixingBranchingObject, CbcNWay, CbcNWayBranchingObject, CbcFixVariable, CbcDummyBranchingObject, CbcGeneral, CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject, CbcSubProblem", ,CbcClique.cpp,Branch,Edwin,,,,,,,,,,,,, ,CbcSos.cpp,Branch,Edwin,,,,,,,,,,,,, ,CbcSimpleInteger,Branch,Edwin,,,,,,,,,,,,, ,CbcIntegerBranchingObject,Branch,Edwin,,,,,,,,,,,,, ,CbcSimpleIntegerPseudoCost,Branch,Edwin,,,,,,,,,,,,, ,CbcIntegerPseudoCostBranchingObject,Branch,Edwin,,,,,,,,,,,,, ,CbcCliqueBranchingObject,Branch,Edwin,,,,,,,,,,,,, ,CbcLongCliqueBranchingObject,Branch,Edwin,,,,,,,,,,,,, ,CbcSosBranchingObject,Branch,Edwin,,,,,,,,,,,,, ,CbcBranchDefaultDecision,Branch,Edwin,,,,,,,,,,,,, ,CbcFollowOn,Branch,Edwin,,,,,,,,,,,,, ,CbcFixingBranchingObject,Branch,Edwin,,,,,,,,,,,,, ,CbcNWay,Branch,Edwin,,,,,,,,,,,,, ,CbcNWayBranchingObject,Branch,Edwin,,,,,,,,,,,,, ,CbcFixVariable,Branch,Edwin,,,,,,,,,,,, ,CbcDummyBranchingObject,Branch,Edwin,,,,,,,,,,,, ,CbcGeneral,Branch,Edwin,,,,,,,,,,,, ,CbcGeneralDepth,Branch,Edwin,,,,,,,,,,,, ,CbcGeneralBranchingObject,Branch,Edwin,,,,,,,,,,,, ,CbcOneGeneralBranchingObject,Branch,Edwin,,,,,,,,,,,, ,CbcSubProblem,Branch,Edwin,,,,,,,,,,,, CbcBranchBase.cpp,,Branch,Edwin,,,10,352,707,1059,x,,,,CbcObject,"CbcBranchingObject, CbcBranchDecision, CbcConsequence, CbcObjectUpdateData" ,CbcBranchDecision,Branch,Edwin,,,,,,,,,,,, ,CbcBranchObject,Branch,Edwin,,,,,,,,,,,, ,CbcConsequence,Branch,Edwin,,,,,,,,,,,, ,CbcObject,Branch,Edwin,,,,,,,,,,,, ,CbcObjectUpdateData,Branch,Edwin,,,,,,,,,,,, CbcBranchCut.cpp,,Branch,Edwin,,,10,1023,315,1338,x,,,,CbcBranchCut,"CbcCutBranchingObject, CbcBranchToFixLots, CbcBranchAllDifferent" ,CbcBranchAllDifferent,Branch,Edwin,,,,,,,,,,,, ,CbcBranchToFixLots,Branch,Edwin,,,,,,,,,,,, ,CbcCutBranchingObject,Branch,Edwin,,,,,,,,,,,, CbcBranchDynamic.cpp,,Branch,Edwin,,,8,1911,557,2468,x,,,,CbcSimpleIntegerDynamicPseudoCost,"CbcDynamicPseudoCostBranchingObject, CbcBranchDynamicDecision" ,CbcDynamicPseudoCostBranching,Branch,Edwin,,,,,,,,,,,, ,CbcSimpleIntegerDynamicPseudoCost,Branch,Edwin,,,,,,,,,,,, CbcBranchLotsize.cpp,,Branch,Edwin,,,15,809,250,1059,x,,,,CbcLotsize,CbcLotsizeBranchingObject CbcCbcParam.cpp,,API,Bjarni,,,24,1,,1,x,,,,"#include ""CbcOrClpParam.cpp""", CbcCompareActual.cpp,,NodeStrat,Edwin,,,8,463,165,628,x,,,,CbcCompareDepth,"CbcCompareObjective, CbcCompareDefault, CbcCompareEstimate" ,CbcCompareDefault.cpp,NodeStrat,Edwin,,,,,,,,,,,, ,CbcCompareDepth.cpp,NodeStrat,Edwin,,,,,,,,,,,, ,CbcCompareEstimate.cpp,NodeStrat,Edwin,,,,,,,,,,,, ,CbcCompareObjective.cpp,NodeStrat,Edwin,,,,,,,,,,,, CbcCompareBase.hpp,,NodeStrat,Edwin,,,24,,170,170,x,,,,CbcCompareBase,"CbcCompare, CbcChooseVariable" ,CbcCompare,NodeStrat,Edwin,,,,,,,,,,,, ,CbcChooseVariable,NodeStrat,Edwin,,,,,,,,,,,, CbcConfig.h,,,,,,20,,102,102,x,,,,#defines, CbcCountRowCut.cpp,,Cuts,,,,10,126,115,241,x,,,,CbcCountRowCut, CbcCutGenerator.cpp,,Cuts,Edwin,,,2,1223,510,1733,x,,,,CbcCutGenerator,"CbcCutModifier, CbcCutSubsetModifier", ,CbcCutModifier.cp,Cuts,Edwin,,,,,,,,,,,,, ,CbcCutSubsetModifier.cpp,Cuts,Edwin,,,,,,,,,,,,, CbcEventHandler.cpp,,API,,,,36,101,221,322,x,,,,CbcEventHandler,, CbcFathom.cpp,,NodeStrat,Edwin,,,19,106,126,232,x,,,,CbcFathom,CbcOsiSolver, CbcFathomDynamicProgramming.cpp,,NodeStrat,Edwin,,,10,1051,166,1217,x,,,,CbcFathomDynamicProgramming,, CbcFeasibilityBase.hpp,,API?,,,,24,,53,53,x,,,,CbcFeasibilityBase,, CbcGenBaB.cpp,,Generic,Lou,,,14,886,,886,,,x,,namespace CbcGenParamUtils,namespace,The support functions for the main branch-and-cut action routine. CbcGenCbcParam.cpp,,Generic,Lou,,,24,155,189,344,,,x,,CbcCbcParam,,Constructors and destructors for CbcCbcParam CbcGenCbcParamUtils.cpp,,Generic,Lou,,,18,401,,401,,,x,,namespace CbcCbcParamUtils,,Implementation functions for CbcGenParam parameters. CbcGenCtlBlk.cpp,,Generic,Lou,,,24,681,948,1629,x,,x,,CbcGenCtlBlk,,Constructor for cbc-generic control block. CbcGeneric.cpp,,Generic,Lou,,,24,415,,415,,,x,,namespace CbcGenSolvers,namespace,Unnamed local namespace for cbc-generic support types and functions. CbcGenMessages.cpp,,Generic,Lou,,,24,192,,192,x,,,,CbcGenCtlBlk,,Message definitions. CbcGenOsiParam.cpp,,Generic,Lou,,,24,156,197,353,,,x,,CbcOsiParam,,Constructors and destructors for CbcOsiParam CbcGenOsiParamUtils.cpp,,Generic,Lou,,,18,528,,528,,,x,,namespace CbcOsiParamUtils,,Implementation functions for CbcOsiParam parameters CbcGenParam.cpp,,Generic,Lou,,,24,154,219,373,,,x,,CbcGenParam,,Constructors and destructors for CbcGenParam CbcGenParamUtils.cpp,,Generic,Lou,,,18,1497,,1497,,,x,,namespace CbcGenParamUtils,"namespace CbcGenSolvers, ",Implementation functions for CbcGenParam parameters CbcGenSolution.cpp,,Generic,Lou,,,22,584,,584,,,x,,CbcGenParamUtils,namespace,"Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise." CbcGenSolvers.cpp,,Generic,Lou,,,24,261,,261,,,x,,namespace CbcGenSolvers,namespace,This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers. CbcHeuristic.cpp,,Heuristic,,,,10,2901,650,3551,x,,,,CbcHeuristic,"CbcHeuristicNode, CbcHeuristicNodeList, CbcRounding, CbcHeuristicPartial, CbcSerendipity, CbcHeuristicJustOne", CbcHeuristicDive.cpp,,Heuristic,,,,10,1068,160,1228,x,,,,CbcHeuristicDive,, CbcHeuristicDiveCoefficient.cpp,,Heuristic,,,,12,128,49,177,x,,,,CbcHeuristicDiveCoefficient,, CbcHeuristicDiveFractional.cpp,,Heuristic,,,,18,112,49,161,x,,,,CbcHeuristicDiveFractional,, CbcHeuristicDiveGuided.cpp,,Heuristic,,,,18,123,52,175,x,,,,CbcHeuristicDiveGuided,, CbcHeuristicDiveLineSearch.cpp,,Heuristic,,,,18,120,49,169,x,,,,CbcHeuristicDiveLineSearch,, CbcHeuristicDivePseudoCost.cpp,,Heuristic,,,,18,227,57,284,x,,,,CbcHeuristicDivePseudoCost,, CbcHeuristicDiveVectorLength.cpp,,Heuristic,,,,10,123,49,172,x,,,,CbcHeuristicDiveVectorLength,, CbcHeuristicFPump.cpp,,Heuristic,,,,8,2764,319,3083,x,,,,CbcHeuristicFPump,CbcDisasterHandler, CbcHeuristicGreedy.cpp,,Heuristic,,,,17,861,189,1050,x,,,,CbcHeuristicGreedyCover,CbcHeuristicGreedyEquality, CbcHeuristicLocal.cpp,,Heuristic,,,,8,1104,208,1312,x,,,,CbcHeuristicLocal,CbcHeuristicNaive, CbcHeuristicPivotAndFix.cpp,,Heuristic,,,,14,537,55,592,x,,,,CbcHeuristicPivotAndFix,, CbcHeuristicRandRound.cpp,,Heuristic,,,,10,514,55,569,x,,,,CbcHeuristicRandRound,, CbcHeuristicRINS.cpp,,Heuristic,,,,10,1207,296,1503,x,,,,CbcHeuristicRINS,"CbcHeuristicRENS, CbcHeuristicDINS, CbcHeuristicVND" CbcLinked.cpp,,Nonlinear/Osi,,,,10,8302,1403,9705,x,,,,OsiSolverLink,"OsiLinkedBound, OsiHeuristicDynamic3, OsiOldLink, OsiBiLinear*, OsiSimpleFixedInteger, Multiple" CbcMain.cpp,,API,,,,14,1651,,1651,,,,x,main,"CbcCompareUser, namespace" CbcMessage.cpp,,API,,,,13,104,87,191,x,,,,CbcMessage, CbcModel.cpp,,Core,Edwin,,,0,16557,2622,19179,x,,,,CbcModel, CbcNode.cpp,,Core,Dan,,,0,5135,806,5941,x,,,,CbcNode,"CbcNodeInfo, CbcFullNodeInfo, CbcPartialNodeInfo, " ,CbcFullNodeInfo.cpp,Core,Dan,,,,,,,,,,,, ,CbcNodeInfo.cpp,Core,Dan,,,,,,,,,,,, ,CbcPartialNodeInfo.cpp,Core,Dan,,,,,,,,,,,, CbcParam.cpp,,API,Bjarni,,,24,502,237,739,x,,,,CbcParam, CbcSolver.cpp,,API,Bjarni,,,0,11365,,11365,,x,,,CbcSolver,CbcMain CbcStatistics.cpp,,API,,,,21,136,98,234,x,,,,CbcStatistics, CbcStrategy.cpp,,Core,Dan/Edwin,,,8,940,255,1195,x,,,,CbcStrategy,CbcStrategyDefault* CbcTree.cpp,,Core,Dan/Edwin,,,8,1178,419,1597,x,,,,CbcTree,CbcTreeArray CbcTreeLocal.cpp,,Heuristic,,,,10,1747,369,2116,x,,,,CbcTreeLocal, Cbc_ampl.cpp,,Ampl,,,,4,1504,65,1569,,,,x,global, Cbc_C_Interface.cpp,,Interface,Bjarni,,,4,2554,658,3212,,,,x,global, ClpAmplObjective.cpp,,Ampl,,,,14,750,110,860,,,,x,ClpAmplObjective, ClpAmplStuff.cpp,,Ampl,,,,3,1370,,1370,x,,,,CbcAmpl,"CbcAmpl*, Multiple" ClpConstraintAmpl.hpp,,Ampl,,,,24,,105,105,,,,,, CoinSolve.cpp,,API,Bjarni,,,8,342,,342,,x,,,MyMessageHandler2,main unitTest.cpp,,Test,,,,8,418,,418,,,,x,global, unitTestClp.cpp,,Test,,,,5,714,,714,,x,,,global, Cbc-2.8.12/config.sub0000755000076600007660000007772611405215312012751 0ustar coincoin#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, # Inc. timestamp='2007-04-29' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | mt \ | msp430 \ | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | score \ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16c) basic_machine=cr16c-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: Cbc-2.8.12/cbc-uninstalled.pc.in0000644000076600007660000000045611574143003014754 0ustar coincoinprefix=@prefix@ libdir=@ABSBUILDDIR@/src Name: CBC Description: COIN-OR Branch and Cut URL: https://projects.coin-or.org/Cbc Version: @PACKAGE_VERSION@ Libs: ${libdir}/libCbcSolver.la ${libdir}/libCbc.la @CBCLIB_PCLIBS@ Cflags: -I@abs_source_dir@/src -I@ABSBUILDDIR@/src Requires: @CBCLIB_PCREQUIRES@ Cbc-2.8.12/CbcSourceFilesTable3.csv0000644000076600007660000002266311307556223015371 0ustar coincoin"Filename",,"Group","Person","Inherits","Status","Age","CPP Lines","HPP Lines","Total Lines","libCbc","cbcSolve","cbcGeneric","Other Projects","First Object","Other Objects","Comment" "CbcBranchActual.cpp (broken up, no longer used)",,"Branch","Edwin",,,8,5340,1823,7163,"x",,,,"Multiple","CbcClique, CbcSos, CbcSimpleInteger, CbcIntegerBranchingObject, CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject, CbcSosBranchingObject, CbcBranchDefaultDecision, CbcFollowOn, CbcFixingBranchingObject, CbcNWay, CbcNWayBranchingObject, CbcFixVariable, CbcDummyBranchingObject, CbcGeneral, CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject, CbcSubProblem", ,"CbcClique.cpp (CbcClique, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject)","Branch","Edwin",,,,,,,,,,,,, ,"CbcSos.cpp (CbcSos, CbcSosBranchingObject)","Branch","Edwin",,,,,,,,,,,,, ,"CbcSimpleInteger.cpp (CbcSimpleInteger, CbcIntegerBranchingObject)","Branch","Edwin",,,,,,,,,,,,, ,"CbcSimpleIntegerPseudoCost.cpp (CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject)","Branch","Edwin",,,,,,,,,,,,, ,"CbcBranchDefaultDecision","Branch","Edwin",,,,,,,,,,,,, ,"CbcFollowOn.cpp (CbcFollowOn, CbcFixingBranchingObject)","Branch","Edwin",,,,,,,,,,,,, ,"CbcNWay.cpp (CbcNWay, CbcNWayBranchingObject)","Branch","Edwin",,,,,,,,,,,,, ,"CbcFixVariable","Branch","Edwin",,,,,,,,,,,,, ,"CbcDummyBranchingObject","Branch","Edwin",,,,,,,,,,,,, ,"CbcGeneral","Branch","Edwin",,,,,,,,,,,,, ,"CbcGeneralDepth.cpp (CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject)","Branch","Edwin",,,,,,,,,,,,, ,"CbcSubProblem","Branch","Edwin",,,,,,,,,,,,, "CbcBranchBase.cpp (broken up, no longer used)",,"Branch","Edwin",,,10,352,707,1059,"x",,,,"CbcObject","CbcBranchingObject, CbcBranchDecision, CbcConsequence, CbcObjectUpdateData", ,"CbcBranchDecision","Branch","Edwin",,,,,,,,,,,,, ,"CbcBranchObject","Branch","Edwin",,,,,,,,,,,,, ,"CbcConsequence","Branch","Edwin",,,,,,,,,,,,, ,"CbcObject","Branch","Edwin",,,,,,,,,,,,, ,"CbcObjectUpdateData","Branch","Edwin",,,,,,,,,,,,, "CbcBranchCut.cpp (CbcBranchCut, CbcCutBranchingObject)",,"Branch","Edwin",,,10,1023,315,1338,"x",,,,"CbcBranchCut","CbcCutBranchingObject, CbcBranchToFixLots, CbcBranchAllDifferent", ,"CbcBranchAllDifferent","Branch","Edwin",,,,,,,,,,,,, ,"CbcBranchToFixLots","Branch","Edwin",,,,,,,,,,,,, "CbcBranchDynamic.cpp (CbcBranchDynamic, CbcDynamicPseudoCostBranchingObject)",,"Branch","Edwin",,,8,1911,557,2468,"x",,,,"CbcSimpleIntegerDynamicPseudoCost","CbcDynamicPseudoCostBranchingObject, CbcBranchDynamicDecision", ,"CbcSimpleIntegerDynamicPseudoCost","Branch","Edwin",,,,,,,,,,,,, "CbcLotsize.cpp (CbcLotsize, CbcLotsizeBranchingObject)",,"Branch","Edwin",,,,,,,,,,,,, "CbcCbcParam.cpp",,"API","Bjarni",,,24,1,,1,"x",,,,"#include ""CbcOrClpParam.cpp""",, "CbcCompareActual.cpp",,"NodeStrat","Dan",,"Reviewed",8,463,165,628,"x",,,,"CbcCompareDepth","CbcCompareObjective, CbcCompareDefault, CbcCompareEstimate", ,"CbcCompareDefault.cpp","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, ,"CbcCompareDepth.cpp","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, ,"CbcCompareEstimate.cpp","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, ,"CbcCompareObjective.cpp","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, "CbcCompareBase.hpp",,"NodeStrat","Dan",,"Reviewed",24,,170,170,"x",,,,"CbcCompareBase","CbcCompare, CbcChooseVariable", ,"CbcCompare","NodeStrat","Dan",,"Reviewed",,,,,,,,,,, ,"CbcChooseVariable - class not used","NodeStrat","[Dan]",,"Reviewed",,,,,,,,,,, "CbcConfig.h",,,,,,20,,102,102,"x",,,,"#defines",, "CbcCountRowCut.cpp",,"Cuts",,,,10,126,115,241,"x",,,,"CbcCountRowCut",, "CbcCutGenerator.cpp",,"Cuts","Dan",,"Reviewed",2,1223,510,1733,"x",,,,"CbcCutGenerator","CbcCutModifier, CbcCutSubsetModifier", ,"CbcCutModifier.cpp","Cuts","Dan",,"Reviewed",,,,,,,,,,, ,"CbcCutSubsetModifier.cpp","Cuts","Dan",,"Reviewed",,,,,,,,,,, "CbcEventHandler.cpp",,"API",,,,36,101,221,322,"x",,,,"CbcEventHandler",, "CbcFathom.cpp - not used currently",,"NodeStrat","[Dan]",,"Reviewed",19,106,126,232,"x",,,,"CbcFathom","CbcOsiSolver", "CbcFathomDynamicProgramming.cpp - not used currently",,"NodeStrat","[Dan]",,"Reviewed",10,1051,166,1217,"x",,,,"CbcFathomDynamicProgramming",, "CbcFeasibilityBase.hpp",,"API?",,,,24,,53,53,"x",,,,"CbcFeasibilityBase",, "CbcGenBaB.cpp",,"Generic","Lou",,,14,886,,886,,,"x",,"namespace CbcGenParamUtils","namespace","The support functions for the main branch-and-cut action routine." "CbcGenCbcParam.cpp",,"Generic","Lou",,,24,155,189,344,,,"x",,"CbcCbcParam",,"Constructors and destructors for CbcCbcParam" "CbcGenCbcParamUtils.cpp",,"Generic","Lou",,,18,401,,401,,,"x",,"namespace CbcCbcParamUtils",,"Implementation functions for CbcGenParam parameters." "CbcGenCtlBlk.cpp",,"Generic","Lou",,,24,681,948,1629,"x-not used",,"x",,"CbcGenCtlBlk",,"Constructor for cbc-generic control block." "CbcGeneric.cpp",,"Generic","Lou",,,24,415,,415,,,"x",,"namespace CbcGenSolvers","namespace","Unnamed local namespace for cbc-generic support types and functions." "CbcGenMessages.cpp",,"Generic","Lou",,,24,192,,192,"x-not used",,,,"CbcGenCtlBlk",,"Message definitions." "CbcGenOsiParam.cpp",,"Generic","Lou",,,24,156,197,353,,,"x",,"CbcOsiParam",,"Constructors and destructors for CbcOsiParam" "CbcGenOsiParamUtils.cpp",,"Generic","Lou",,,18,528,,528,,,"x",,"namespace CbcOsiParamUtils",,"Implementation functions for CbcOsiParam parameters" "CbcGenParam.cpp",,"Generic","Lou",,,24,154,219,373,,,"x",,"CbcGenParam",,"Constructors and destructors for CbcGenParam" "CbcGenParamUtils.cpp",,"Generic","Lou",,,18,1497,,1497,,,"x",,"namespace CbcGenParamUtils","namespace CbcGenSolvers, ","Implementation functions for CbcGenParam parameters" "CbcGenSolution.cpp",,"Generic","Lou",,,22,584,,584,,,"x",,"CbcGenParamUtils","namespace","Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise." "CbcGenSolvers.cpp",,"Generic","Lou",,,24,261,,261,,,"x",,"namespace CbcGenSolvers","namespace","This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers." "CbcHeuristic.cpp",,"Heuristic",,,"Reviewed",10,2901,650,3551,"x",,,,"CbcHeuristic","CbcHeuristicNode, CbcHeuristicNodeList, CbcRounding, CbcHeuristicPartial, CbcSerendipity, CbcHeuristicJustOne", "CbcHeuristicDive.cpp",,"Heuristic",,,"Reviewed",10,1068,160,1228,"x",,,,"CbcHeuristicDive",, "CbcHeuristicDiveCoefficient.cpp",,"Heuristic",,,"Reviewed",12,128,49,177,"x",,,,"CbcHeuristicDiveCoefficient",, "CbcHeuristicDiveFractional.cpp",,"Heuristic",,,"Reviewed",18,112,49,161,"x",,,,"CbcHeuristicDiveFractional",, "CbcHeuristicDiveGuided.cpp",,"Heuristic",,,"Reviewed",18,123,52,175,"x",,,,"CbcHeuristicDiveGuided",, "CbcHeuristicDiveLineSearch.cpp",,"Heuristic",,,"Reviewed",18,120,49,169,"x",,,,"CbcHeuristicDiveLineSearch",, "CbcHeuristicDivePseudoCost.cpp",,"Heuristic",,,"Reviewed",18,227,57,284,"x",,,,"CbcHeuristicDivePseudoCost",, "CbcHeuristicDiveVectorLength.cpp",,"Heuristic",,,"Reviewed",10,123,49,172,"x",,,,"CbcHeuristicDiveVectorLength",, "CbcHeuristicFPump.cpp",,"Heuristic",,,"Reviewed",8,2764,319,3083,"x",,,,"CbcHeuristicFPump","CbcDisasterHandler", "CbcHeuristicGreedy.cpp",,"Heuristic",,,"Reviewed",17,861,189,1050,"x",,,,"CbcHeuristicGreedyCover","CbcHeuristicGreedyEquality", "CbcHeuristicLocal.cpp",,"Heuristic",,,"Reviewed",8,1104,208,1312,"x",,,,"CbcHeuristicLocal","CbcHeuristicNaive", "CbcHeuristicPivotAndFix.cpp",,"Heuristic",,,"Reviewed",14,537,55,592,"x",,,,"CbcHeuristicPivotAndFix",, "CbcHeuristicRandRound.cpp",,"Heuristic",,,"Reviewed",10,514,55,569,"x",,,,"CbcHeuristicRandRound",, "CbcHeuristicRINS.cpp",,"Heuristic",,,"Reviewed",10,1207,296,1503,"x",,,,"CbcHeuristicRINS","CbcHeuristicRENS, CbcHeuristicDINS, CbcHeuristicVND", "CbcLinked.cpp",,"Nonlinear/Osi",,,,10,8302,1403,9705,"x",,,,"OsiSolverLink","OsiLinkedBound, OsiHeuristicDynamic3, OsiOldLink, OsiBiLinear*, OsiSimpleFixedInteger, Multiple", "CbcMain.cpp",,"API",,,"Deleted",14,1651,,1651,,,,"x","main","CbcCompareUser, namespace", "CbcMessage.cpp",,"API",,,,13,104,87,191,"x",,,,"CbcMessage",, "CbcModel.cpp",,"Core","Edwin",,"Updated",0,16557,2622,19179,"x",,,,"CbcModel",, "CbcNode.cpp",,"Core","Dan",,"Reviewed",0,5135,806,5941,"x",,,,"CbcNode","CbcNodeInfo, CbcFullNodeInfo, CbcPartialNodeInfo, ", ,"CbcFullNodeInfo.cpp","Core","Dan",,"Reviewed",,,,,,,,,,, ,"CbcNodeInfo.cpp","Core","Dan",,"Reviewed",,,,,,,,,,, ,"CbcPartialNodeInfo.cpp","Core","Dan",,"Reviewed",,,,,,,,,,, "CbcParam.cpp",,"API","Bjarni",,,24,502,237,739,"x",,,,"CbcParam",, "CbcSolver.cpp",,"API","Bjarni",,,0,11365,,11365,,"x",,,"CbcSolver","CbcMain", "CbcStatistics.cpp",,"API",,,,21,136,98,234,"x",,,,"CbcStatistics",, "CbcStrategy.cpp",,"Core","Dan",,"Updated",8,940,255,1195,"x",,,,"CbcStrategy","CbcStrategyDefault*", "CbcTree.cpp",,"Core","Dan",,"Reviewed",8,1178,419,1597,"x",,,,"CbcTree","CbcTreeArray", "CbcTreeLocal.cpp",,"Heuristic",,,,10,1747,369,2116,"x",,,,"CbcTreeLocal",, "Cbc_ampl.cpp",,"Ampl",,,,4,1504,65,1569,,,,"x","global",, "Cbc_C_Interface.cpp",,"Interface","Bjarni",,,4,2554,658,3212,,,,"x","global",, "ClpAmplObjective.cpp",,"Ampl",,,,14,750,110,860,,,,"x","ClpAmplObjective",, "ClpAmplStuff.cpp",,"Ampl",,,,3,1370,,1370,"x",,,,"CbcAmpl","CbcAmpl*, Multiple", "ClpConstraintAmpl.hpp",,"Ampl",,,,24,,105,105,,,,,,, "CoinSolve.cpp",,"API",,,,8,342,,342,,"x",,,"MyMessageHandler2","main", "unitTest.cpp",,"Test",,,,8,418,,418,,,,"x","global",, "unitTestClp.cpp",,"Test",,,,5,714,,714,,"x",,,"global",, Cbc-2.8.12/AUTHORS0000644000076600007660000000010110755030022012003 0ustar coincoinForrest, John J. Hafer, Lou Goncalves, Joao P.: Diving heuristicsCbc-2.8.12/doxydoc/0000755000076600007660000000000012377555231012434 5ustar coincoinCbc-2.8.12/doxydoc/doxygen.conf.in0000644000076600007660000017377612244010257015375 0ustar coincoin# Doxyfile 1.6.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = @PACKAGE_NAME@ # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @PACKAGE_VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doxydoc # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = "@abs_top_srcdir@/" # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = @coin_doxy_logname@ #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @abs_top_srcdir@/src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.hpp \ *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */.svn* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 3 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = YES # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) # there is already a search function so this one should typically # be disabled. SEARCHENGINE = YES #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = YES # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = letter # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = @coin_doxy_tagfiles@ # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = @coin_doxy_tagname@ # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = YES # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = @coin_doxy_usedot@ # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES Cbc-2.8.12/INSTALL0000644000076600007660000000030612131315050011770 0ustar coincoinThis is a project directory. For information on how to install the package this project was downloaded with see the INSTALL file in the root of the package (the parent directory of this directory). Cbc-2.8.12/doc/0000755000076600007660000000000012377555231011530 5ustar coincoinCbc-2.8.12/doc/moresamples.xml0000644000076600007660000001016710235673241014577 0ustar coincoin More Samples
CBC's Samples Directory The CBC distribution includes a number of .cpp sample files. Users are encouraged to use them as starting points for their own CBC projects. The files can be found in the &cbcsamplesdir; directory. For the latest information on compiling and running these samples, please see the file &cbcsamplesdir;INSTALL. Most of them can be built by make DRIVER=name which produces an executable testit. Below is a list of some of the most useful sample files with a short description for each file. Basic Samples Source file        Description &minimumcpp; This is a CBC "Hello, world" program. It reads a problem in MPS file format, and solves the problem using simple branch-and-bound. &sample2cpp; This is designed to be a file that a user could modify to get a useful driver program for his or her project. In particular, it demonstrates the use of CGL's preprocess functionality. It uses CbcBranchUser.cpp, CbcCompareUser.cpp and CbcHeuristicUser.cpp with corresponding *.hpp files.
Advanced Samples Source file        Description &crewcpp; This sample shows the use of advanced branching and a use of priorities. It uses CbcCompareUser.cpp with corresponding *.hpp files. &longthincpp; This sample shows the advanced use of a solver. It also has coding for a greedy heuristic. The solver is given in CbcSolver2.hpp and CbcSolver2.cpp. The heuristic is given in CbcHeuristicGreedy.hpp and CbcHeuristicGreedy.cpp. It uses CbcBranchUser.cpp and CbcCompareUser.cpp with corresponding *.hpp files. &qmipcpp; This solves a quadratic MIP. It is to show advanced use of a solver. The solver is given in ClpQuadInterface.hpp and ClpQuadInterface.cpp. It uses CbcBranchUser.cpp and CbcCompareUser.cpp with corresponding *.hpp files. &soscpp; This artificially creates a Special Ordered Set problem. &lotsizecpp; This artificially creates a Lot Sizing problem.
Cbc-2.8.12/doc/doxygen.xml0000644000076600007660000000121410220363301013701 0ustar coincoin Doxygen There is Doxygen content for CBC available online at http://www.coin-or.org/Doxygen/Cbc/index.html. A local version of the Doxygen content can be generated from the CBC distribution. To do so, in the directory COIN/Cbc, enter make doc. The Doxygen content will be created in the directory COIN/Cbc/Doc/html. The same can be done for the COIN core, from the COIN/Coin directory. Cbc-2.8.12/doc/legal.xml0000644000076600007660000000164111507203260013322 0ustar coincoin 2005 IBM Coportation CBC and this documentation are provided under the terms of the Eclipse Public License (EPL). Any use, reproduction or distribution of the programs constitutes the recipient's acceptance of the license. The EPL is approved by the Open Source Initiative. The Eclipse Foundation, the steward of the EPL, has an EPL FAQ available which is based on the Eclipse Foundation's understanding of the EPL. Cbc-2.8.12/doc/cbcuserguide.xml0000644000076600007660000000352210235507566014717 0ustar coincoin sample2.cpp"> crew.cpp"> minimum.cpp"> qmip.cpp"> lotsize.cpp"> sos.cpp"> longthin.cpp"> ]> CBC User Guide &authors; &legal; &intro; &cbcmodelclass; &otherclasses; &moresamples; &messages; &faq; &doxygen; &revhist; Cbc-2.8.12/doc/osibuild.xml0000644000076600007660000000033710220363301014043 0ustar coincoin Building and Modifying a Model
CoinModel
Cbc-2.8.12/doc/otherclasses.xml0000644000076600007660000010637410235673241014755 0ustar coincoin Selecting the Next Node in the Search Tree
CbcCompare - Comparison Methods The order in which the nodes of the search tree are explored can strongly influence the performance of branch-and-cut algorithms. CBC give users complete control over the search order. The search order is controlled via the CbcCompare... class. CBC provides an abstract base class, CbcCompareBase, and several commonly used instances which are described in . Compare Classes Provided Class name Description CbcCompareDepth This will always choose the node deepest in tree. It gives minimum tree size but may take a long time to find the best solution. CbcCompareObjective This will always choose the node with the best objective value. This may give a very large tree. It is likely that the first solution found will be the best and the search should finish soon after the first solution is found. CbcCompareDefault This is designed to do a mostly depth-first search until a solution has been found. It then use estimates that are designed to give a slightly better solution. If a reasonable number of nodes have been explored (or a reasonable number of solutions found), then this class will adopt a breadth-first search (i.e., making a comparison based strictly on objective function values) unless the tree is very large when it will revert to depth-first search. A better description of CbcCompareUser is given below. CbcCompareEstimate When pseudo costs are invoked, they can be used to guess a solution. This class uses the guessed solution.
It is relatively simple for an experienced user to create new compare class instances. The code in describes how to build a new comparison class and the reasoning behind it. The complete source can be found in CbcCompareUser.hpp and CbcCompareUser.cpp, located in the CBC Samples directory. See . The key method in CbcCompare is bool test(CbcNode* x, CbcNode* y)) which returns true if node y is preferred over node x. In the test() method, information from CbcNode can easily be used. list some commonly used methods to access information at a node. Information Available from <classname>CbcNode</classname> double objectiveValue() const Value of objective at the node. int numberUnsatisfied() const Number of unsatisfied integers (assuming branching object is an integer - otherwise it might be number of unsatisfied sets). int depth() const Depth of the node in the search tree. double guessedObjectiveValue() const If user was setting this (e.g., if using pseudo costs). int way() const The way which branching would next occur from this node (for more advanced use). int variable() const The branching "variable" (associated with the CbcBranchingObject -- for more advanced use).
The node desired in the tree is often a function of the how the search is progressing. In the design of CBC, there is no information on the state of the tree. The CBC is designed so that the method newSolution() is called whenever a solution is found and the method every1000Nodes() is called every 1000 nodes. When these methods are called, the user has the opportunity to modify the behavior of test() by adjusting their common variables (e.g., weight_). Because CbcNode has a pointer to the model, the user can also influence the search through actions such as changing the maximum time CBC is allowed, once a solution has been found (e.g., CbcModel::setMaximumSeconds(double value)). In CbcCompareUser.cpp of the COIN/Cbc/Samples directory, four items of data are used. 1) The number of solutions found so far 2) The size of the tree (defined to be the number of active nodes) 3) A weight, weight_, which is initialized to -1.0 4) A saved value of weight, saveWeight_ (for when weight is set back to -1.0 for special reason) The full code for the CbcCompareUser::test() method is given in . <function>CbcCompareUser::test()</function> numberUnsatisfied() > y->numberUnsatisfied()) return true; else if (x->numberUnsatisfied() < y->numberUnsatisfied()) return false; else return x->depth() < y->depth(); } else { // after solution. // note: if weight_=0, comparison is based // solely on objective value double weight = CoinMax(weight_,0.0); return x->objectiveValue()+ weight*x->numberUnsatisfied() > y->objectiveValue() + weight*y->numberUnsatisfied(); } } ]]> Initially, weight_ is -1.0 and the search is biased towards depth first. In fact, test() prefers y if y has fewer unsatisfied variables. In the case of a tie, test() prefers the node with the greater depth in tree. Once a solution is found, newSolution() is called. The method newSolution() interacts with test() by means of the variable weight_. If the solution was achieved by branching, a calculation is made to determine the cost per unsatisfied integer variable to go from the continuous solution to an integer solution. The variable weight_ is then set to aim at a slightly better solution. From then on, test() returns true if it seems that y will lead to a better solution than x. This source for newSolution() in given in . <function>CbcCompareUser::newSolution()</function> getSolutionCount()==model->getNumberHeuristicSolutions()) return; // solution was found by rounding so ignore it. // set weight_ to get close to this solution double costPerInteger = (model->getObjValue()-objectiveAtContinuous)/ ((double) numberInfeasibilitiesAtContinuous); weight_ = 0.98*costPerInteger; saveWeight_=weight_; numberSolutions_++; if (numberSolutions_>5) weight_ =0.0; // comparison in test() will be // based strictly on objective value. } ]]> As the search progresses, the comparison can be modified. If many nodes (or many solutions) have been genereated, then weight_ is set to 0.0 leading to a breadth-first search. Breadth-first search can lead to an enormous tree. If the tree size is exceeds 10000, it may be desirable to return to a search biased towards depth first. Changing the behavior in this manner is done by the method every1000Nodes shown in . <function>CbcCompareUser::every1000Nodes()</function> 10000) weight_ =0.0; // compare nodes based on objective value else if (numberNodes==1000&&weight_==-2.0) weight_=-1.0; // Go to depth first // get size of tree treeSize_ = model->tree()->size(); if (treeSize_>10000) { // set weight to reduce size most of time if (treeSize_>20000) weight_=-1.0; else if ((numberNodes%4000)!=0) weight_=-1.0; else weight_=saveWeight_; } return numberNodes==11000; // resort if first time } ]]>
Getting Good Bounds in CBC
CbcHeuristic - Heuristic Methods In practice, it is very useful to get a good solution reasonably fast. Any MIP-feasible solution produces an upper bound, and a good bound will greatly reduce the run time. Good solutions can satisfy the user on very large problems where a complete search is impossible. Obviously, heuristics are problem dependent, although some do have more general use. At present there is only one heuristic in CBC itself, CbcRounding. Hopefully, the number will grow. Other heuristics are in the COIN/Cbc/Samples directory. A heuristic tries to obtain a solution to the original problem so it only needs to consider the original rows and does not have to use the current bounds. CBC provides an abstract base class CbcHeuristic and a rounding heuristic in CBC. This chapter describes how to build a greedy heuristic for a set covering problem, e.g., the miplib problem fast0507. A more general (and efficient) version of the heuristic is in CbcHeuristicGreedy.hpp and CbcHeuristicGreedy.cpp located in the COIN/Cbc/Samples directory, see . The greedy heuristic will leave all variables taking value one at this node of the tree at value one, and will initially set all other variable to value zero. All variables are then sorted in order of their cost divided by the number of entries in rows which are not yet covered. (We may randomize that value a bit so that ties will be broken in different ways on different runs of the heuristic.) The best one is choosen, and set to one. The process is repeated. Because this is a set covering problem (i.e., all constraints are ≥), the heuristic is guaranteed to find a solution (but not necessarily an improved solution). The speed of the heuristic could be improved by just redoing those affected, but for illustrative purposes we will keep it simple.(The speed could also be improved if all elements are 1.0). The key CbcHeuristic method is int solution(double & solutionValue, double * betterSolution). The solution() method returns 0 if no solution found, and returns 1 if a solution is found, in which case it fills in the objective value and primal solution. The code in CbcHeuristicGreedy.cpp is a little more complicated than this following example. For instance, the code here assumes all variables are integer. The important bit of data is a copy of the matrix (stored by column) before any cuts have been made. The data used are bounds, objective and the matrix plus two work arrays. Data solver(); // Get solver from CbcModel const double * columnLower = solver->getColLower(); // Column Bounds const double * columnUpper = solver->getColUpper(); const double * rowLower = solver->getRowLower(); // We know we only need lower bounds const double * solution = solver->getColSolution(); const double * objective = solver->getObjCoefficients(); // In code we also use min/max double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance,primalTolerance); int numberRows = originalNumberRows_; // This is number of rows when matrix was passed in // Column copy of matrix (before cuts) const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Get solution array for heuristic solution int numberColumns = solver->getNumCols(); double * newSolution = new double [numberColumns]; // And to sum row activities double * rowActivity = new double[numberRows]; ]]> The newSolution is then initialized to the rounded down solution. Initialize <varname>newSolution</varname> At this point some row activities may be below their lower bound. To correct this infeasibility, the variable which is cheapest in reducing the sum of infeasibilities is found and updated, and the process repeats. This is a finite process. (Theimplementation could be faster, but is kept simple for illustrative purposes.) Create Feasible <varname>newSolution</varname> from Initial <varname>newSolution</varname> 1.0e-7) { sum += CoinMin(element[j],gap); if (element[j]+rowActivity[iRow]0.0) { double ratio = (cost/sum)*(1.0+0.1*CoinDrand48()); if (ratio A solution value of newSolution is compared to the best solution value. If newSolution is an improvement, its feasibility is validated. Check Solution Quality of <varname>newSolution</varname>
Branching
Pseudo Cost Branching If the user declares variables as integer but does no more, then CBC will treat them as simple integer variables. In many cases the user would like to do some more fine tuning. This section shows how to create integer variables with pseudo costs. When pseudo costs are given then it is assumed that if a variable is at 1.3 then the cost of branching that variable down will be 0.3 times the down pseudo cost and the cost of branching up would be 0.7 times the up pseudo cost. Pseudo costs can be used both for branching and for choosing a node. The full code is in longthin.cpp located in the CBC Samples directory, see . The idea is simple for set covering problems. Branching up gets us much closer to an integer solution so we will encourage that direction by branch up if variable value > 0.333333. The expected cost of going up obviously depends on the cost of the variable. The pseudo costs are choosen to reflect that fact. <classname>CbcSimpleIntegerPseudoCosts</classname> getNumCols(); // do pseudo costs CbcObject ** objects = new CbcObject * [numberColumns]; // Point to objective const double * objective = model.getObjCoefficients(); int numberIntegers=0; for (iColumn=0;iColumnisInteger(iColumn)) { double cost = objective[iColumn]; CbcSimpleIntegerPseudoCost * newObject = new CbcSimpleIntegerPseudoCost(&model,numberIntegers,iColumn, 2.0*cost,cost); newObject->setMethod(3); objects[numberIntegers++]= newObject; } } // Now add in objects (they will replace simple integers) model.addObjects(numberIntegers,objects); for (iColumn=0;iColumn The code in also tries to give more importance to variables with more coefficients. Whether this sort of thing is worthwhile should be the subject of experimentation.
Follow-On Branching In crew scheduling, the problems are long and thin. A problem may have a few rows but many thousands of variables. Branching a variable to 1 is very powerful as it fixes many other variables to zero, but branching to zero is very weak as thousands of variables can increase from zero. In crew scheduling problems, each constraint is a flight leg, e.g., JFK airport to DFW airport. From DFW there may be several flights the crew could take next - suppose one flight is the 9:30 flight from DFW to LAX airport. A binary branch is that the crew arriving at DFW either take the 9:30 flight to LAX or they don't. This "follow-on" branching does not fix individual variables. Instead this branching divides all the variables with entries in the JFK-DFW constraint into two groups - those with entries in the DFW-LAX constraint and those without entries. The full sample code for follow-on brancing is in crew.cpp located in the CBC Samples directory, see ). In this case, the simple integer variables are left which may be necessary if other sorts of constraints exist. Follow-on branching rules are to be considered first, so the priorities are set to indicated the follow-on rules take precedence. Priority 1 is the highest priority. <classname>CbcFollowOn</classname> getNumCols(); /* We are going to add a single follow-on object but we want to give low priority to existing integers As the default priority is 1000 we don't actually need to give integer priorities but it is here to show how. */ // Normal integer priorities int * priority = new int [numberColumns]; int numberIntegers=0; for (iColumn=0;iColumnisInteger(iColumn)) { priority[numberIntegers++]= 100; // low priority } } /* Second parameter is set to true for objects, and false for integers. This indicates integers */ model.passInPriorities(priority,false); delete [] priority; /* Add in objects before we can give them a priority. In this case just one object - but it shows the general method */ CbcObject ** objects = new CbcObject * [1]; objects[0]=new CbcFollowOn(&model); model.addObjects(1,objects); delete objects[0]; delete [] objects; // High priority int followPriority=1; model.passInPriorities(&followPriority,true); ]]>
Advance Solver Uses
Creating a Solver via Inheritance CBC uses a generic OsiSolverInterface and its resolve capability. This does not give much flexibility so advanced users can inherit from their interface of choice. This section illustrates how to implement such a solver for a long thin problem, e.g., fast0507 again. As with the other examples in the Guide, the sample code is not guaranteed to be the fastest way to solve the problem. The main purpose of the example is to illustrate techniques. The full source is in CbcSolver2.hpp and CbcSolver2.cpp located in the CBC Samples directory, see . The method initialSolve is called a few times in CBC, and provides a convenient starting point. The modelPtr_ derives from OsiClpSolverInterface. <function>initialSolve()</function> setLogLevel(1); // switch on a bit of printout modelPtr_->scaling(0); // We don't want scaling for fast0507 setBasis(basis_,modelPtr_); // Put basis into ClpSimplex // Do long thin by sprint ClpSolve options; options.setSolveType(ClpSolve::usePrimalorSprint); options.setPresolveType(ClpSolve::presolveOff); options.setSpecialOption(1,3,15); // Do 15 sprint iterations modelPtr_->initialSolve(options); // solve problem basis_ = getBasis(modelPtr_); // save basis modelPtr_->setLogLevel(0); // switch off printout ]]> The resolve() method is more complicated than initialSolve(). The main pieces of data are a counter count_ which is incremented each solve and an integer array node_ which stores the last time a variable was active in a solution. For the first few times, the normal Dual Simplex is called and node_ array is updated. First Few Solves status()==0) { count_++; // feasible - save any nonzero or basic const double * solution = modelPtr_->primalColumnSolution(); for (int i=0;i1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } } else { printf("infeasible early on\n"); } } ]]> After the first few solves, only those variables which took part in a solution in the last so many solves are used. As fast0507 is a set covering problem, any rows which are already covered can be taken out. Create Small Problem columnLower(); const double * upper = modelPtr_->columnUpper(); setBasis(basis_,modelPtr_); // Set basis int nNewCol=0; // Number of columns in small model // Column copy of matrix const double * element = modelPtr_->matrix()->getElements(); const int * row = modelPtr_->matrix()->getIndices(); const CoinBigIndex * columnStart = modelPtr_->matrix()->getVectorStarts(); const int * columnLength = modelPtr_->matrix()->getVectorLengths(); int * rowActivity = new int[numberRows]; // Number of columns with entries in each row memset(rowActivity,0,numberRows*sizeof(int)); int * rowActivity2 = new int[numberRows]; // Lower bound on row activity for each row memset(rowActivity2,0,numberRows*sizeof(int)); char * mark = (char *) modelPtr_->dualColumnSolution(); // Get some space to mark columns memset(mark,0,numberColumns); for (i=0;icount_-memory_&&node_[i]>0); // Choose if used recently // Take if used recently or active in some sense if ((choose&&upper[i]) ||(modelPtr_->getStatus(i)!=ClpSimplex::atLowerBound&& modelPtr_->getStatus(i)!=ClpSimplex::isFixed) ||lower[i]>0.0) { mark[i]=1; // mark as used whichColumn[nNewCol++]=i; // add to list CoinBigIndex j; double value = upper[i]; if (value) { for (j=columnStart[i]; j0.0) { for (j=columnStart[i]; jsetRowStatus(i,ClpSimplex::basic); // make slack basic } if (nOKsetProblemStatus(1); delete [] whichRow; delete [] whichColumn; printf("infeasible by inspection\n"); return; } // Now make up a small model with the right rows and columns ClpSimplex * temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); ]]> If the variables cover the rows, then the problem is feasible (no cuts are being used). If the rows were equality constraints, then this might not be the case. More work would be needed. After the solution, the reduct costs are checked. If any reduced costs are negative, the code goes back to the full problem and cleans up with Primal Simplex. Check Optimal Solution setDualObjectiveLimit(1.0e50); // Switch off dual cutoff as problem is restricted temp->dual(); // solve double * solution = modelPtr_->primalColumnSolution(); // put back solution const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;isetStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;isetRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } // See if optimal double * dj = modelPtr_->dualColumnSolution(); // get reduced cost for large problem // this assumes minimization memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double)); modelPtr_->transposeTimes(-1.0,dual,dj); modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); int nBad=0; for (i=0;igetStatus(i)==ClpSimplex::atLowerBound &&upper[i]>lower[i]&&dj[i]<-1.0e-5) nBad++; } // If necessary clean up with primal (and save some statistics) if (nBad) { timesBad_++; modelPtr_->primal(1); iterationsBad_ += modelPtr_->numberIterations(); } ]]> The array node_ is updated, as for the first few solves. To give some idea of the effect of this tactic, the problem fast0507 has 63,009 variables but the small problem never has more than 4,000 variables. In only about ten percent of solves was it necessary to resolve, and then the average number of iterations on full problem was less than 20.
Quadratic MIP To give another example - again only for illustrative purposes -- it is possible to do quadratic MIP with CBC. In this case, we make resolve the same as initialSolve. The full code is in ClpQuadInterface.hpp and ClpQuadInterface.cpp located in the CBC Samples directory, see ). Solving a Quadratic MIP dualObjectiveLimit(); modelPtr_->setDualObjectiveLimit(1.0e50); modelPtr_->scaling(0); modelPtr_->setLogLevel(0); // solve with no objective to get feasible solution setBasis(basis_,modelPtr_); modelPtr_->dual(); basis_ = getBasis(modelPtr_); modelPtr_->setDualObjectiveLimit(cutoff); if (modelPtr_->problemStatus()) return; // problem was infeasible // Now pass in quadratic objective ClpObjective * saveObjective = modelPtr_->objectiveAsObject(); modelPtr_->setObjectivePointer(quadraticObjective_); modelPtr_->primal(); modelPtr_->setDualObjectiveLimit(cutoff); if (modelPtr_->objectiveValue()>cutoff) modelPtr_->setProblemStatus(1); modelPtr_->setObjectivePointer(saveObjective); ]]>
Cbc-2.8.12/doc/faqcontent.xml0000644000076600007660000000733511507203260014406 0ustar coincoin What is CBC? The COIN-OR Branch and Cut code is designed to be a high quality mixed integer code provided under the terms of the Eclipse Public License. CBC is written in C++, and is primarily intended to be used as a callable library (though a rudimentary stand-alone executable exists). The first documented release was .90.0 The current release is version .90.0. (JF 04/01/05) What are some of the features of CBC? CBC allows the use of any CGL cuts and the use of heuristics and specialized branching methods. (JF 04/01/05) How do I obtain and install CBC? Please see the COIN-OR FAQ for details on how to obtain and install COIN-OR modules. (JF 04/01/05) Is CBC reliable? CBC has been tested on many problems, but more testing and improvement is needed before it can get to version 1.0. (JF 04/01/05) Is there any documentation for CBC? If you can see this you have the best there is:-) Also available is a list of CBC class descriptions generated by Doxygen. (JF 04/01/05) Is CBC as fast as Cplex or Xpress? No. However its design is much more flexible so advanced users will be able to tailor CBC to their needs. (JF 04/01/05) When will version 1.0 of CBC be available? It is expected that version 1.0 will be released in time for the 2005 INFORMS annual meeting. (JF 04/01/05) What can the community do to help? People from all around the world are already helping. There are probably ten people who do not always post to the discussion mail list but are constantly "improving" the code by demanding performance or bug fixes or enhancements. And there are others posting questions to discussion groups. (JF 04/01/05) A good start is to join the coin-discuss mailing list where CBC is discussed. Some other possibilities include: Comment on the design Give feedback on the documentation and FAQs. Break the code, or better yet -- mend it. Tackle any of the "to-dos" listed in the Doxyen documentation and contribute back to COIN-OR. Cbc-2.8.12/doc/revhist.xml0000644000076600007660000000127610235507566013743 0ustar coincoin Revision History 0.2 May 2, 2005 RLH Book chapter for CBC Tutorial at INFORMS 2005 annual meeting. Reorganized the content. Added CBC Messages. Changed the font type to distinguish functions/variables/classnames/code from text. 0.1 April 1, 2005 JF First draft. The CBC documenation uses the DocBook CLP documentation created by David de la Nuez. Cbc-2.8.12/doc/cbcmodelclass.xml0000644000076600007660000006112010235673241015041 0ustar coincoin The CBC Model Class
Overview The main class in CBC is CbcModel. The CbcModel class is where most of the parameter setting is done. The absolute minimum number of actions taken with CbcModel is two, CbcModel(OsiSolverInterface & linearSolver) as constructor, and branchAndBound() for solving the problem.
Simple Branch-and-Bound Example The first sample program shows how to perform simple branch-and-bound with CBC. This program is short enough to present in full. Most of the remaining examples will take the form of small code fragments. The complete code for all the examples in this Guide can be found in the CBC Samples directory, COIN/Cbc/Samples. minimum.cpp getNumCols(); const double * solution = model.solver()->getColSolution(); for (int iColumn=0;iColumn1.0e-7&&model.solver()->isInteger(iColumn)) printf("%d has value %g\n",iColumn,value); } return 0; } ]]> The program in creates a OsiClpSolverInterface solver interface (i.e., solver1), and reads an MPS file. If there are no errors, the program passes the problem to CbcModel which solves the problem using the branch-and-bound algorithm. The part of the program which solves the problem is very small (one line!) but before that one line, the LP solver (i.e., solver1) had to be created and populated with the problem. After that one line, the results were printed out.
The Relationship Between OSI and CBC The program in illustrates the dependency of CBC on the OsiSolverInterface class. The constructor of CbcModel takes a pointer to an OsiSolverInterface (i.e., a solver). The CbcModel clones the solver, and uses its own instance of the solver. The CbcModel's solver and the original solver (e.g., solver1) are not in sync unless the user synchronizes them. The user can always access the CbcModel's solver through the model() method. To synchronize the two solvers, explicitly refreshing the original, e.g., solver1 = model.solver(); CbcModel's method solve() returns a pointer to CBC's cloned solver. For convenience, many of the OSI methods to access problem data have identical method names in CbcModel. (It's just more convenient to type model.getNumCols() rather than model.solver()->getNumCols()). The CbcModel refreshes its solver at certain logical points during the algorithm. At these points, the information from the CbcModel model will match the information from the model.solver(). Elsewhere, the information may vary. For instance, the OSI method getColSolution() will contain the best solution so far, while the CbcModel method may not. In this case, it is safer to use CbcModel::bestSolution(). While all the OSI methods used in minimum.cpp have equivalent methods in CbcModel, there are some OSI methods which do not. For example, if the program produced a lot of undesired output, one might add the line model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); to reduce the output. There is no setHintParam() method in CbcModel.
Getting Solution Information Optimality can be checked through a call to model.isProvenOptimal(). Also available are isProvenInfeasible(), isSolutionLimitReached(), isNodeLimitReached() or the feared isAbandoned(). There is also int status() which returns 0 if finished (which includes the case when the algorithm is finished because it has been proved infeasible), 1 if stopped by user, and 2 if difficulties arose. In addition to these CbcModel methods, solution values can be accessed via OSI methods. The OSI methods pick up the current solution in the CBCModel. The current solution will match the best solution found so far if called after branchAndBound() and a solution was found. Methods for Getting Solution Information from OSI Purpose Name Notes Primal column solution const double * getColSolution() The OSI method will return the best solution found thus far, unless none has been found. It is safer to use CbcModel version, CbcModel::bestSolution() Dual row solution const double * getRowPrice() Identical CbcModel version available, CbcModel::getRowPrice(). Primal row solution const double * getRowActivity() Identical CbcModel version available, CbcModel::getRowActivity(). Dual column solution const double * getReducedCost() Identical CbcModel version available, CbcModel::gtReducedCost(). Number of rows in model int getNumRows() Identical CbcModel version available, CbcModel::getNumRows(). Note: the number of rows can change due to cuts. Number of columns in model int getNumCols() Identical CbcModel version available, CbcModel::getNumCols().
Useful Set and Get Methods in <classname>CbcModel</classname> Most of the parameter setting in CBC is done through CbcModel methods. The most commonly used set and get methods are listed in . Useful Set and Get Methods in <classname>CbcModel</classname> Method(s) Description bool setMaximumNodes(int value) int getMaximumNodes() const bool setMaximumSeconds(double value) double getMaximumSeconds() bool setMaximumSolutions(double value) double getMaximumSolutions() const These set methods tell CBC to stop after a given number of nodes, seconds, or solutions is reached. The get methods return the corresponding values. bool setIntegerTolerance(double value) const double getIntegerTolerance() const An integer variable is deemed to be at an integral value if it is no further than this value (tolerance) away. bool setAllowableGap(double value) double getAllowableGap() const bool setAllowablePercentageGap(double value) double getAllowablePercentageGap() const bool setAllowableFractionGap(double value) double getAllowableFractionGap() const CbcModel returns if the gap between the best known solution and the best possible solution is less than this value, or as a percentage, or a fraction. void setNumberStrong(double value) int numberStrong() const These methods set or get the maximum number of candidates at a node to be evaluated for strong branching. void setPrintFrequency(int value) int printFrequency() const Controls the number of nodes evaluated between status prints. Print frequency has a very slight overhead, if value is small. int getNodeCount() const Returns number of nodes evaluated in the search. int numberRowsAtContinuous() const Returns number of rows at continuous int  numberIntegers() const const int * integerVariable() const Returns number of integer variables and an array specifying them. bool isBinary(int colIndex) const bool isContinuous(int colIndex) const bool isInteger(int colIndex) const Returns information on variable colIndex. OSI methods can be used to set these attributes (before handing the model to CbcModel). double getObjValue() const This method returns the best objective value so far. double getCurrentObjValue() const This method returns the current objective value. const double * getObjCoefficients() const This method return the objective coefficients. const double * getRowLower() const const double * getRowUpper() const const double * getColLower() const const double * getColUpper() const These methods return the lower and upper bounds on row and column activities. const CoinPackMatrix * getMatrixByRow() const This method returns a pointer to a row copy of matrix stored as a CoinPackedMatrix which can be further examined. const CoinPackMatrix * getMatrixByCol() const This method returns a pointer to a column copy of matrix stored as a CoinPackedMatrix which can be further examined. CoinBigIndex getNumElements() const CoinBigIndex is a typedef which in most cases is the same as int. Returns the number of nonzero elements in the problem matrix. void setObjSense(double value) double getObjSense() const These methods set and get the objective sense. The parameter value should be +1 to minimize and -1 to maximize.
Impacting the Solution Process CbcModel is extremely flexible and customizable. The class structure of CBC is designed to make the most commonly desired customizations of branch-and-cut possible. These include: selecting the next node to consider in the search tree, determining which variable to branch on, using heuristics to generate MIP-feasible solutions quickly, including cut generation when solving the LP-relaxations, and invoking customized subproblem solvers. To enable this flexibility, CbcModel uses other classes in CBC (some of which are virtual and may have multiple instances). Not all classes are created equal. The two tables below list in alphabetical order the classes used by CbcModel that are of most interest and of least interest. Classes Used by CbcModel - Most Useful Class name Description Notes CbcCompareBase Controls which node on the tree is selected. The default is CbcCompareDefault. Other comparison classes in CbcCompareActual.hpp include CbcCompareDepth and CbcCompareObjective. Experimenting with these classes and creating new compare classes is easy. CbcCutGenerator A wrapper for CglCutGenerator with additional data to control when the cut generator is invoked during the tree search. Other than knowing how to add a cut generator to CbcModel, there is not much the average user needs to know about this class. However, sophisticated users can implement their own cut generators. CbcHeuristic Heuristic that attempts to generate valid MIP-solutions leading to good upper bounds. Specialized heuristics can dramatically improve branch-and-cut performance. As many different heuristics as desired can be used in CBC. Advanced users should consider implementing custom heuristics when tackling difficult problems. CbcObject Defines what it means for a variable to be satisfied. Used in branching. Virtual class. CBC's concept of branching is based on the idea of an "object". An object has (i) a feasible region, (ii) can be evaluated for infeasibility, (iii) can be branched on, e.g., a method of generating a branching object, which defines an up branch and a down branch, and (iv) allows comparsion of the effect of branching. Instances of objects include CbcSimpleInteger, CbcSimpleIntegerPseudoCosts, CbcClique, CbcSOS (type 1 and 2), CbcFollowOn, and CbcLotsize. OsiSolverInterface Defines the LP solver being used and the LP model. Normally a pointer to the desired OsiSolverInteface is passed to CbcModel before branch and cut. Virtual class. The user instantiates the solver interface of their choice, e.g., OsiClpSolverInterface.
There is not much about the classes listed in that the average user needs to know about. Classes Used by CbcModel - Least Useful Class name Description Notes CbcBranchDecision Used in choosing which variable to branch on, however, most of the work is done by the definitions in CbcObject. Defaults to CbcBranchDefaultDecision. CbcCountRowCut Interface to OsiRowCut. It counts the usage so cuts can gracefully vanish. See OsiRowCut for more details. CbcNode Controls which variable/entity is selected to be branch on. Controlled via CbcModel parameters. Information from CbcNode can be useful in creating customized node selection rules. CbcNodeInfo Contains data on bounds, basis, etc. for one node of the search tree. Header is located in CbcNode.hpp. CbcTree Defines how the search tree is stored. This class can be changed but it is not likely to be modified. CoinMessageHandler Deals with message handling The user can inherit from CoinMessageHandler to specialize message handling. CoinWarmStartBasis Basis representation to be used by solver
Cbc-2.8.12/doc/faq.xml0000644000076600007660000000022410220363301012773 0ustar coincoin FAQ &faqcontent; Cbc-2.8.12/doc/cbcexe.xml0000644000076600007660000002067610220363301013472 0ustar coincoin The CLP Executable
Quick Start The result of make unitTest (executed in COIN/Clp) is an executable clp as well as the CLP and COIN libraries. The executable can be used to perform various unit tests, but can also be used as a standalone solver. As the executable has a very simple solution file format, the user may wish to modify COIN/Clp/Test/ClpMain.cpp, which contains the source of the executable (modifications could even be offered as a contribution to CLP). The clp executable operates in command line mode or prompted mode. Entering clp will invoke the prompted mode, while clp <filename> will import a problem in MPS format from filename, solve it using the dual simplex method and exit. The command clp <filename> -primalsimplex instructs the executable tp import a file and solve using the primal simplex method. An additional solitary dash ("-") starts the prompt mode once the execution of the initial command has been completed. The "-" is necessary as part of the command; invoking prompt mode as a separate command will result in the loss of problem information related to the initial command. So, the following sequences of commands are equivalent in the sense that both maximize a problem using the dual simplex method and write a solution to file: solfile:
$ clp filename -maximize -dualsimplex -solution solfile
$ clp filename -maximize - Clp:duals Clp:solution solfile Clp:quit
The executable is at a very early stage of development. Comments and suggestions would be appreciated.
Online Help and Basic Usage The executable has some command-completion functionality as well as some online help. Below is a table with some examples which summarize these capabilities. Command examples for the clp executable Command     Result ? Gives a list of all commands p? Gives a list of all commands which begin with <p>. p?? Gives a list of all commands which begin with <p>., with a short explanation for each. primals?? If is this is enough to uniquely determine a command (in this example, primalS, for primal simplex), a long explanation is given.
In addition, matching a name without a ? will either execute the command or give the value of the corresponding parameter as follows: primalw will give the current value of the primalWeight parameter while primalw 1.0e7 will change it to 1.0e7.
A Sample Session Below is a sample CLP executable prompt-mode session. A small problem is loaded and solved under various conditions with the primal and dual simplex methods. Note the use of the allslack command; it sets the basis to all slacks and resets the solution. $clp Coin LP version 0.99.9, build Sep 14 2004 Clp takes input from arguments ( - switches to stdin) Enter ? for list of commands or help Clp:import../Mps/Sample/p0033.mps At line 15 NAME P0033 At line 16 ROWS At line 34 COLUMNS At line 109 RHS At line 118 BOUNDS At line 152 ENDATA Problem P0033 has 16 rows, 33 columns and 98 elements Model was imported from ./../Mps/Sample/p0033.mps in 0 seconds Clp:primals Presolve 15 (-1) rows, 32 (-1) columns and 97 (-1) elements 0 Obj 0 Primal inf 27.2175 (10) Dual inf 6.42094e+11 (32) 32 Obj 2520.57 Optimal - objective value 2520.57 After Postsolve, objective 2520.57, infeasibilities - dual 0 (0), primal 0 (0) Optimal objective 2520.571739 - 32 iterations time 0.012, Presolve 0.01 Clp:max Clp:primals Presolve 11 (-5) rows, 25 (-8) columns and 84 (-14) elements 0 Obj 4807.92 Dual inf 1700.71 (15) End of values pass after 2 iterations 2 Obj 4921.7 Dual inf 580.637 (5) 9 Obj 5299.7 Optimal - objective value 5299.7 After Postsolve, objective 5299.7, infeasibilities - dual 643.608 (9), primal 27.0826 (10) Presolved model was optimal, full model needs cleaning up 0 Obj 5299.7 0 Obj 5299.7 Optimal - objective value 5299.7 Optimal objective 5299.698868 - 9 iterations time 0.022, Presolve 0.02 Clp:allslack Clp:duals Presolve 11 (-5) rows, 25 (-8) columns and 84 (-14) elements 0 Obj 2752 Primal inf 24.4867 (6) Dual inf 4280.55 (25) 8 Obj 5299.7 Optimal - objective value 5299.7 After Postsolve, objective 5299.7, infeasibilities - dual 704.58 (8), primal 27.0792 (10) Presolved model was optimal, full model needs cleaning up 0 Obj 5299.7 0 Obj 5299.7 Optimal - objective value 5299.7 Optimal objective 5299.698868 - 8 iterations time 0.032, Presolve 0.01 Clp:min Clp:duals Presolve 15 (-1) rows, 32 (-1) columns and 97 (-1) elements 0 Obj 5299.7 Dual inf 4632.26 (28) 16 Obj 2520.57 Optimal - objective value 2520.57 After Postsolve, objective 2520.57, infeasibilities - dual 2052.5 (13), primal 27.1143 (10) Presolved model was optimal, full model needs cleaning up 0 Obj 2520.57 0 Obj 2520.57 Optimal - objective value 2520.57 Optimal objective 2520.571739 - 16 iterations time 0.012, Presolve 0.01 Clp:allslack Clp:presolve off Clp:primals 0 Obj 0 Primal inf 27.2175 (10) Dual inf 6.39167e+11 (32) 32 Obj 2520.57 Optimal - objective value 2520.57 Optimal objective 2520.571739 - 32 iterations time 0.002 Clp:allslack Clp:maxIt 10 maxIterations was changed from 99999999 to 10 Clp:primals 0 Obj 0 Primal inf 27.2175 (10) Dual inf 6.39167e+11 (32) Stopped - objective value 4.24664e+10 Stopped objective 4.246637759e+10 - 10 iterations time 0.002 Clp:quit
Cbc-2.8.12/doc/intro.xml0000644000076600007660000002375310235673241013410 0ustar coincoin Introduction
Welcome to CBC The COIN The complete acronym is "COIN-OR" which stands for the Compuational Infrastructure for Operations Research. For simplicity (and in keeping with the directory and function names) we will simply use "COIN". Branch and Cut solver (CBC) is an open-source mixed-integer program (MIP) solver written in C++. CBC is intended to be used primarily as a callable library to create customized branch-and-cut solvers. A basic, stand-alone executable version is also available. CBC is an active open-source project led by John Forrest at www.coin-or.org.
Prerequisites The primary users of CBC are expected to be developers implementing customized branch-and-cut algorithms in C++ using CBC as a library. Consequently, this document assumes a working knowledge of C++, including basic object-oriented programming terminology, and familiarity with the fundamental concepts of linear programming and mixed integer programming. CBC relies other parts of the COIN repository. CBC needs an LP solver and relies the COIN Open Solver Inteface (OSI) to communicate with the user's choice of solver. Any LP solver with an OSI interface can be used with CBC. The LP solver expected to be used most commonly is COIN's native linear program solver, CLP. For cut generators, CBC relies on the COIN Cut Generation Library (CGL). Any cut generator written to CGL standards can be used with CBC. Some of the cut generators in CGL rely on other parts of COIN, e.g., CGL's Gomory cut generator rely on the factorization functionality of CoinFactorization. This document assumes basic familiarity with OSI and CGL. Technically speaking, CBC assesses the solver (and sometime the model and data it contains) through an OSISolverInterface. For the sake of simplicity, we will refer to the OsiSolverInterface as "the solver" in this document, rather than "the standard application programming interface to the solver." We hope any confusion caused by blurring this distinction will be mitigated by the shorter sentences. In summary, readers should have the following prerequisites: C++ knowledge, LP and MIP fundamentals, and OSI familiarity. Unless otherwise stated, we will assume the problem being optimized is a minimization problem. The terms "model" and "problem" are used synonymously.
Branch-and-Cut Overview Before examining CBC in more detail, we tersely describe the basic branch-and-cut algorithm by way of example, (which should really be called branch-and-cut-and-bound) and show the major C++ class(es) in CBC related to each step. The major CBC classes, labeled (A) through (F), are described in . Step 1. (Bound) Given a MIP model to minimize where some variables must take on integer values (e.g., 0, 1, or 2), relax the integrality requirements (e.g., consider each "integer" variable to be continuous with a lower bound of 0.0 and an upper bound of 2.0). Solve the resulting linear model with an LP solver to obtain a lower bound on the MIP's objective function value. If the optimal LP solution has integer values for the MIP's integer variables, we are finished. Any MIP-feasible solution provides an upper bound on the objective value. The upper bound equals the lower bound; the solution is optimal. Step 2. (Branch) Otherwise, there exists an "integer" variable with a non-integral value. Choose one non-integral variable (e.g., with value 1.3) (A)(B) and branch. Create two nodes, one with the branching variable having an upper bound of 1.0, and the other with the branching variable having a lower bound of 2.0. Add the two nodes to the search tree. While (search tree is not empty) { Step 3. (Choose Node) Pick a node off the tree (C)(D) Step 4. (Re-optimize LP) Create an LP relaxation and solve. Step 5. (Bound) Interrogate the optimal LP solution, and try to prune the node by one of the following. LP is infeasible, prune the node. Else, the optimal LP solution value of the node exceeds the current upper bound, prune the node. Else, the optimal LP solution of the node does not exceed the current upper bound and the solution is feasible to the MIP. Update the upper bound, and the best known MIP solution, and prune the node by optimality. Step 6. (Branch) If we were unable to prune the node, then branch. Choose one non-integral variable to branch on (A)(B). Create two nodes and add them to the search tree. } This is the outline of a "branch-and-bound" algorithm. If in optimizing the linear programs, we use cuts to tighten the LP relaxations (E)(F), then we have a "branch-and-cut" algorithm. (Note, if cuts are only used in Step 1, the method is called a "cut-and-branch" algorithm.) Associated Classes Note Class name Description (A) CbcBranch... These classes define the nature of MIP's discontinuity. The simplest discontinuity is a variable which must take an integral value. Other types of discontinuities exist, e.g., lot-sizing variables. (B) CbcNode This class decides which variable/entity to branch on next. Even advanced users will probably only interact with this class by setting CbcModel parameters ( e.g., priorities). (C) CbcTree All unsolved models can be thought of as being nodes on a tree where each node (model) can branch two or more times. The user should not need to be concerned with this class. (D) CbcCompare... These classes are used in determine which of the unexplored nodes in the tree to consider next. These classes are very small simple classes that can be tailored to suit the problem. (E) CglCutGenerators Any cut generator from CGL can be used in CBC. The cut generators are passed to CBC with parameters which modify when each generator will be tried. All cut generators should be tried to determine which are effective. Few users will write their own cut generators. (F) CbcHeuristics Heuristics are very important for obtaining valid solutions quickly. Some heuristics are available, but this is an area where it is useful and interesting to write specialized ones.
There are a number of resources available to help new CBC users get started. This document is designed to be used in conjunction with the files in the Samples subdirectory of the main CBC directory (COIN/Cbc/Samples). The Samples illustrate how to use CBC and may also serve as useful starting points for user projects. In the event that either this document or the available Doxygen content conflicts with the observed behavior of the source code, the comments in the header files, found in COIN/Cbc/include, are the ultimate reference.
Cbc-2.8.12/doc/messages.xml0000644000076600007660000003655510235446252014070 0ustar coincoin Messages Messages and codes passed by CBC are listed in the tables below. For a complete list, see COIN/Cbc/CbcMessages.cpp. The notation used is the same as for the printf in the C programming language. %s is a string %d is an integer %g or %f is a floating point value There are several log levels. Setting the log level to be i produces the log messages for level i and all levels less than i. Logging Level 0: Switches off all CBC messages, but one. Logging Level 1: The default. Logging Level 2: Substantial amount of information, e.g., message 15 is generated once per node. Can be useful when the evaluation at each node is slow. Logging Level 3: Tremendous amount of information, e.g., multiple messages per node. CBC Messages Passed At Logging Level 0 Code Text and notes 3007 No integer variables - nothing to do
CBC Messages Passed At or Above Logging Level 1 Code Text and notes 1 Search completed - best objective %g, took %d iterations and %d nodes 3 Exiting on maximum nodes 4 Integer solution of %g found after %d iterations and %d nodes 5 Partial search - best objective %g (best possible %g), took %d iterations and %d nodes 6 The LP relaxation is infeasible or too expensive 9 Objective coefficients multiple of %g 10 After %d nodes, %d on tree, %g best solution, best possible %g 11 Exiting as integer gap of %g less than %g or %g%% 12 Integer solution of %g found by heuristic after %d iterations and %d nodes 13 At root node, %d cuts changed objective from %g to %g in %d passes 14 Cut generator %d (%s) - %d row cuts (%d active), %d column cuts %? in %g seconds - new frequency is %d 16 Integer solution of %g found by strong branching after %d iterations and %d nodes 17 %d solved, %d variables fixed, %d tightened 18 After tightenVubs, %d variables fixed, %d tightened 19 Exiting on maximum solutions 20 Exiting on maximum time 23 Cutoff set to %g - equivalent to best solution of %g 24 Integer solution of %g found by subtree after %d iterations and %d nodes 26 Setting priorities for objects %d to %d inclusive (out of %d) 3008 Strong branching is fixing too many variables, too expensively!
CBC Messages Passed At or Above Logging Level 2 Code Text and notes 8 %d has value %g 15 Node %d Obj %g Unsat %d depth %d 21 On closer inspection node is infeasible 22 On closer inspection objective value of %g above cutoff of %g 23 Allowing solution, even though largest row infeasibility is %g
CBC Messages Passed At or Above Logging Level 3 Code Text and notes 7 Strong branching on %d (%d), down %g (%d) up %g (%d) value %g 25 %d cleanup iterations before strong branching
Cbc-2.8.12/doc/authors.xml0000644000076600007660000000107010235424220013715 0ustar coincoin John Forrest jjforre at us dot ibm dot com IBM Research Robin Lougee-Heimer robinlh at us dot ibm dot com IBM Research Cbc-2.8.12/install-sh0000755000076600007660000002202111405215312012744 0ustar coincoin#!/bin/sh # install - install a program, script, or datafile scriptversion=2005-05-14.22 # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" chmodcmd="$chmodprog 0755" chowncmd= chgrpcmd= stripcmd= rmcmd="$rmprog -f" mvcmd="$mvprog" src= dst= dir_arg= dstarg= no_target_directory= usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: -c (ignored) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. --help display this help and exit. --version display version info and exit. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test -n "$1"; do case $1 in -c) shift continue;; -d) dir_arg=true shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; --help) echo "$usage"; exit $?;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -s) stripcmd=$stripprog shift continue;; -t) dstarg=$2 shift shift continue;; -T) no_target_directory=true shift continue;; --version) echo "$0 $scriptversion"; exit $?;; *) # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. test -n "$dir_arg$dstarg" && break # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dstarg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dstarg" shift # fnord fi shift # arg dstarg=$arg done break;; esac done if test -z "$1"; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi for src do # Protect names starting with `-'. case $src in -*) src=./$src ;; esac if test -n "$dir_arg"; then dst=$src src= if test -d "$dst"; then mkdircmd=: chmodcmd= else mkdircmd=$mkdirprog fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dstarg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dstarg # Protect names starting with `-'. case $dst in -*) dst=./$dst ;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dstarg: Is a directory" >&2 exit 1 fi dst=$dst/`basename "$src"` fi fi # This sed command emulates the dirname command. dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` # Make sure that the destination directory exists. # Skip lots of stat calls in the usual case. if test ! -d "$dstdir"; then defaultIFS=' ' IFS="${IFS-$defaultIFS}" oIFS=$IFS # Some sh's can't handle IFS=/ for some reason. IFS='%' set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` shift IFS=$oIFS pathcomp= while test $# -ne 0 ; do pathcomp=$pathcomp$1 shift if test ! -d "$pathcomp"; then $mkdirprog "$pathcomp" # mkdir can fail with a `File exist' error in case several # install-sh are creating the directory concurrently. This # is OK. test -d "$pathcomp" || exit fi pathcomp=$pathcomp/ done fi if test -n "$dir_arg"; then $doit $mkdircmd "$dst" \ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } else dstfile=`basename "$dst"` # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 trap '(exit $?); exit' 1 2 13 15 # Copy the file name to the temp name. $doit $cpprog "$src" "$dsttmp" && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && # Now rename the file to the real destination. { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ || { # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { if test -f "$dstdir/$dstfile"; then $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ || { echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 (exit 1); exit 1 } else : fi } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" } } fi || { (exit 1); exit 1; } done # The final little trick to "correctly" pass the exit status to the exit trap. { (exit 0); exit 0 } # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: Cbc-2.8.12/CbcSourceFilesTable3.xls0000644000076600007660000006000011307556223015367 0ustar coincoinÐÏࡱá;þÿ -*þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿÿÿÿÿ  !"#$%&'()þÿÿÿþÿÿÿ,þÿÿÿ.þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿ » Ìá°Áâ\pCalc B°a=œ¯¼@=@ 8X"·Ú1&Èÿ Lohit Hindi1ÈÿArial1ÈÿArial1ÈÿArial1ÈÿArial1Èÿ¼Arial ¤GENERAL ¥GENERALà¤õÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ ठÀ à+õÿ ðÀ à)õÿ ðÀ à,õÿ ðÀ à*õÿ ðÀ à õÿ ðÀ ठÀ ॠÀ ठ@À “€ÿ“€ÿ“€ÿ“€ÿ“€ÿ“€ÿ`…¨Sheet1…¶KSheet2…3MSheet3Œëjðbð( 3 ð¿ À@@ñ  ÷ü„ÀÕFilenameGroupPersonInheritsStatusAge CPP Lines HPP Lines Total LineslibCbccbcSolve cbcGenericOther Projects First Object Other ObjectsComment/CbcBranchActual.cpp (broken up, no longer used)BranchEdwinxMultiple¾CbcClique, CbcSos, CbcSimpleInteger, CbcIntegerBranchingObject, CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject, CbcSosBranchingObject, CbcBranchDefaultDecision, CbcFollowOn, CbcFixingBranchingObject, CbcNWay, CbcNWayBranchingObject, CbcFixVariable, CbcDummyBranchingObject, CbcGeneral, CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject, CbcSubProblemQCbcClique.cpp (CbcClique, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject)*CbcSos.cpp (CbcSos, CbcSosBranchingObject)BCbcSimpleInteger.cpp (CbcSimpleInteger, CbcIntegerBranchingObject)`CbcSimpleIntegerPseudoCost.cpp (CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject)CbcBranchDefaultDecision7CbcFollowOn.cpp (CbcFollowOn, CbcFixingBranchingObject)-CbcNWay.cpp (CbcNWay, CbcNWayBranchingObject)CbcFixVariableCbcDummyBranchingObject CbcGeneral^CbcGeneralDepth.cpp (CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject) CbcSubProblem-CbcBranchBase.cpp (broken up, no longer used) CbcObjectJCbcBranchingObject, CbcBranchDecision, CbcConsequence, CbcObjectUpdateDataCbcBranchDecisionCbcBranchObjectCbcConsequenceCbcObjectUpdateData6CbcBranchCut.cpp (CbcBranchCut, CbcCutBranchingObject) CbcBranchCut@CbcCutBranchingObject, CbcBranchToFixLots, CbcBranchAllDifferentCbcBranchAllDifferentCbcBranchToFixLotsLCbcBranchDynamic.cpp (CbcBranchDynamic, CbcDynamicPseudoCostBranchingObject)!CbcSimpleIntegerDynamicPseudoCost=CbcDynamicPseudoCostBranchingObject, CbcBranchDynamicDecision6CbcLotsize.cpp (CbcLotsize, CbcLotsizeBranchingObject)CbcCbcParam.cppAPIBjarni#include "CbcOrClpParam.cpp"CbcCompareActual.cpp NodeStratDanReviewedCbcCompareDepth:CbcCompareObjective, CbcCompareDefault, CbcCompareEstimateCbcCompareDefault.cppCbcCompareDepth.cppCbcCompareEstimate.cppCbcCompareObjective.cppCbcCompareBase.hppCbcCompareBaseCbcCompare, CbcChooseVariable CbcCompare"CbcChooseVariable - class not used[Dan] CbcConfig.h#definesCbcCountRowCut.cppCutsCbcCountRowCutCbcCutGenerator.cppCbcCutGenerator$CbcCutModifier, CbcCutSubsetModifierCbcCutModifier.cppCbcCutSubsetModifier.cppCbcEventHandler.cppCbcEventHandler"CbcFathom.cpp - not used currently CbcFathom CbcOsiSolver4CbcFathomDynamicProgramming.cpp - not used currentlyCbcFathomDynamicProgrammingCbcFeasibilityBase.hppAPI?CbcFeasibilityBase CbcGenBaB.cppGenericLounamespace CbcGenParamUtils namespaceAThe support functions for the main branch-and-cut action routine.CbcGenCbcParam.cpp CbcCbcParam,Constructors and destructors for CbcCbcParamCbcGenCbcParamUtils.cppnamespace CbcCbcParamUtils4Implementation functions for CbcGenParam parameters.CbcGenCtlBlk.cpp x-not used CbcGenCtlBlk*Constructor for cbc-generic control block.CbcGeneric.cppnamespace CbcGenSolversDUnnamed local namespace for cbc-generic support types and functions.CbcGenMessages.cppMessage definitions.CbcGenOsiParam.cpp CbcOsiParam,Constructors and destructors for CbcOsiParamCbcGenOsiParamUtils.cppnamespace CbcOsiParamUtils3Implementation functions for CbcOsiParam parametersCbcGenParam.cpp CbcGenParam,Constructors and destructors for CbcGenParamCbcGenParamUtils.cppnamespace CbcGenSolvers, 3Implementation functions for CbcGenParam parametersCbcGenSolution.cppCbcGenParamUtils‚Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise.CbcGenSolvers.cpp¥This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers.CbcHeuristic.cpp Heuristic CbcHeuristicmCbcHeuristicNode, CbcHeuristicNodeList, CbcRounding, CbcHeuristicPartial, CbcSerendipity, CbcHeuristicJustOneCbcHeuristicDive.cppCbcHeuristicDiveCbcHeuristicDiveCoefficient.cppCbcHeuristicDiveCoefficientCbcHeuristicDiveFractional.cppCbcHeuristicDiveFractionalCbcHeuristicDiveGuided.cppCbcHeuristicDiveGuidedCbcHeuristicDiveLineSearch.cppCbcHeuristicDiveLineSearchCbcHeuristicDivePseudoCost.cppCbcHeuristicDivePseudoCost CbcHeuristicDiveVectorLength.cppCbcHeuristicDiveVectorLengthCbcHeuristicFPump.cppCbcHeuristicFPumpCbcDisasterHandlerCbcHeuristicGreedy.cppCbcHeuristicGreedyCoverCbcHeuristicGreedyEqualityCbcHeuristicLocal.cppCbcHeuristicLocalCbcHeuristicNaiveCbcHeuristicPivotAndFix.cppCbcHeuristicPivotAndFixCbcHeuristicRandRound.cppCbcHeuristicRandRoundCbcHeuristicRINS.cppCbcHeuristicRINS3CbcHeuristicRENS, CbcHeuristicDINS, CbcHeuristicVND CbcLinked.cpp Nonlinear/Osi OsiSolverLink_OsiLinkedBound, OsiHeuristicDynamic3, OsiOldLink, OsiBiLinear*, OsiSimpleFixedInteger, Multiple CbcMain.cppDeletedmainCbcCompareUser, namespaceCbcMessage.cpp CbcMessage CbcModel.cppCoreUpdatedCbcModel CbcNode.cppCbcNode2CbcNodeInfo, CbcFullNodeInfo, CbcPartialNodeInfo, CbcFullNodeInfo.cppCbcNodeInfo.cppCbcPartialNodeInfo.cpp CbcParam.cppCbcParam CbcSolver.cpp CbcSolverCbcMainCbcStatistics.cpp CbcStatisticsCbcStrategy.cpp CbcStrategyCbcStrategyDefault* CbcTree.cppCbcTree CbcTreeArrayCbcTreeLocal.cpp CbcTreeLocal Cbc_ampl.cppAmplglobalCbc_C_Interface.cpp InterfaceClpAmplObjective.cppClpAmplObjectiveClpAmplStuff.cppCbcAmplCbcAmpl*, MultipleClpConstraintAmpl.hpp CoinSolve.cppMyMessageHandler2 unitTest.cppTestunitTestClp.cppÿ Õ » Ì dü©ñÒMbP?_€%öÁ*+‚ƒ„&è?'è?(ð?)ð?¡"d,, ¶` ¶`à? ¶` ¶`à?U} ¤} œ(}  .} } '} \$} .\ö€öööööööö ö ö ö ö öööööööööööööööööööý ý ý ý ý ý ý ý ý ý  ý  ý  ý  ý  ý ý ý ý ý ½"rS~! û»@ DÀDÀý  ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý ý  ý ý ý !ý ý ý "ý ý ½*‚  Œ@  ¼[ : LþÀLÿÀý  ý #ý $ý %ý ý ý &ý ý ý 'ý ý ý #ý ý ý (ý ý ý )ý ý ½*þî è”@  ý  ý *ý +ý ,ý ý ý -ý ý ý .ý ý ½"Þ¶ H£@  ý  ý /ý 0ý /ý ý ý 1ý ý ý 2ý 3ý 4½b ð?  ý  ý 5ý 6ý 7ý 8ý 9½">–  ƒ@  ý  ý :ý ;ý <ý 7ý 8ý 9ý =ý 7ý 8ý 9ý >ý 7ý 8ý 9ý ?ý 7ý 8ý 9 ö!ö"ö#ö$ö%ö&ö'ö(ö)ö*ö+ö,ö-ö.ö/ö0ö1ö2ö3ö4ö5ö6ö7ö8ö9ö:ö;ö<ö=ö>ö?öý @ý 7ý 8ý 9~ b~ ª @e@  ý ý Aý Bý !Cý !7ý !8ý !9ý "Dý "7ý "Eý "9ý #F~ #R~ #š# €Y@  ý # ý #Gý $Hý $I½$*úÎ$  n@  ý $ ý $Jý %Ký %Iý %8ý %9½% ú% ›@  ý % ý %Lý %Mý &Ný &Iý &8ý &9ý 'Oý 'Iý '8ý '9ý (Pý (3½(’–v(  t@  ý ( ý (Qý )Rý )7ý )Eý )9½)Nªú) m@  ý ) ý )Sý )Tý *Uý *7ý *Eý *9½**nš* “@  ý * ý *Vý +Wý +X~ +b~ +Ö+ €J@  ý + ý +Yý ,Zý ,[ý ,\½,:Ú , °‹@  ý , ý ,]ý ,^ý ,_ý -`ý -[ý -\½-bnö- €u@  ý - ý -aý -bý .cý .[ý .\½.JF. y@  ý . ý .dý .eý /fý /[ý /\½/b¦ Ò/ t™@  ý / gý / ý /hý /iý 0jý 0[ý 0\½0b~0 ðy@  ý 0 ý 0ký 0^ý 0lý 1mý 1[ý 1\½1b1 h@  ý 1 gý 1hý 1ný 2oý 2[ý 2\½2br2 v@  ý 2 ý 2pý 2qý 3rý 3[ý 3\½3JB3 €€@  ý 3 ý 3sý 3tý 4uý 4[ý 4\½4bjn4 Pw@  ý 4 ý 4vý 4wý 5xý 5[ý 5\½5Jf5 d—@  ý 5 ý 5]ý 5yý 5zý 6{ý 6[ý 6\½6Z" 6 @‚@  ý 6 ý 6|ý 6^ý 6}ý 7~ý 7[ý 7\½7b7 Pp@  ý 7 ý 7ký 7^ý 7ý 8€ý 8ý 89½8*V-* 8 ¾«@  ý 8 ý 8‚ý 8ƒý 9„ý 9ý 99½9*²‚9 0“@  ý 9 ý 9…ý :†ý :ý :9½:2Æ:  f@  ý : ý :‡ý ;ˆý ;ý ;9½;JÂÆ;  d@  ý ; ý ;‰ý <Šý <ý <9½<JîÒ< àe@  ý < ý <‹ý =Œý =ý =9½=JâÆ=  e@  ý = ý =ý >Žý >ý >9½>JŽæ> Àq@  ý > ý >ý ?ý ?ý ?9½?*îÆ? €e@  ý ? ý ?‘@öAöBöCöDöEöFöGHöIöJöKöLöMöNöOöPöQöRöSöTöUöVöWöX öYöZö[öý @’ý @ý @9½@"2+þ@ ¨@  ý @ ý @“ý @”ý A•ý Aý A9½AFv öA h@  ý A ý A–ý A—ý B˜ý Bý B9½B"BBB €”@  ý B ý B™ý Bšý C›ý Cý C9½C:fÞC €‚@  ý C ý Cœý Dý Dý D9½D* ÞD È@  ý D ý Džý EŸý Eý E9½E*Þ¢E |—@  ý E ý E ý E¡ý F¢ý F£½F*ºîF €ôÂ@  ý F ý F¤ý F¥ý G¦ý G3ý G§½G:ÎG Ì™@  ý G ý G¨ý G©ý Hªý H3½H6¢^H àg@  ý H ý H«ý I¬ý I­ý Iý I®½I¶ú(I ÀºÒ@  ý I ý I¯ý J°ý J­ý J8ý J9½J>Pš J 5·@  ý J ý J±ý J²ý K³ý K­ý K8ý K9ý L´ý L­ý L8ý L9ý Mµý M­ý M8ý M9ý N¶ý N3ý N4½NbÚ¶N ‡@  ý N ý N·ý O¸ý O3ý O4½O–±O €2Æ@  ý O ý O¹ý Oºý P»ý P3½PV"ŠP @m@  ý P ý P¼ý Q½ý Q­ý Q8ý Q®½Q"²þQ ¬’@  ý Q ý Q¾ý Q¿ý RÀý R­ý R8ý R9½R"jŽR ô˜@  ý R ý RÁý RÂý SÃý S½S*NÆS ˆ @  ý S ý SÄý TÅý TƽT‚T „˜@  ý T ý TÇý UÈý UÉý U4½Uê'J U ©@  ý U ý UÇý VÊý VƽV:º ºV àŠ@  ý V ý VËý WÌý WƽWjW h•@  ý W ý WÍý WÎý XÏý XÆ~ Xb~ X¦X @Z@  ý YÐý Y3½Y"ZY `u@  ý Y ý YÑý Y¨ý ZÒý ZÓ½Z"ŠZ  z@  ý Z ý ZÇý [Ôý [Ó½[* [ P†@  ý [ ý [ÇìPðHðð0ð( ð ð>¶@• •dA äEGGGÿ » Ì dü©ñÒMbP?_€%öÁ*+‚ƒ„&è?'è?(ð?)ð?¡"d,, ¶` ¶`à? ¶` ¶`à?U} .ìPðH ðð0ð( ð ð>¶@GGÿ » Ì dü©ñÒMbP?_€%öÁ*+‚ƒ„&è?'è?(ð?)ð?¡"d,, ¶` ¶`à? ¶` ¶`à?U} .ìPðH0ð ð0ð( ð ð >¶@GGÿ þÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ ÿÿÿÿÀFMicrosoft Excel 97-TabelleBiff8þÿà…ŸòùOh«‘+'³Ù0ÄHPl ˆ ”   ¬ ¸éýBjarni KristjanssonMatthew Saltzman1@€Ü[$@@Sðü|NÊ@€‰!?[xÊþÿÕÍÕœ.“—+,ù®DÕÍÕœ.“—+,ù®\éýéýRoot EntryÿÿÿÿÿÿÿÿÀF+@Workbookÿÿÿÿ°NCompObjÿÿÿÿÿÿÿÿIOle ÿÿÿÿÿÿÿÿÿÿÿÿSummaryInformation(ÿÿÿÿÿÿÿÿôDocumentSummaryInformation8ÿÿÿÿÿÿÿÿÿÿÿÿtÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿCbc-2.8.12/examples/0000755000076600007660000000000012377555231012601 5ustar coincoinCbc-2.8.12/examples/quad2.mps0000644000076600007660000006322310142242520014322 0ustar coincoinNAME ROWS N obj E OBJBM E DIST1(1.2) E DIST1(1.3) E DIST1(1.4) E DIST1(1.5) E DIST1(2.3) E DIST1(2.4) E DIST1(2.5) E DIST1(3.4) E DIST1(3.5) E DIST1(4.5) E DIST2(1.2) E DIST2(1.3) E DIST2(1.4) E DIST2(1.5) E DIST2(2.3) E DIST2(2.4) E DIST2(2.5) E DIST2(3.4) E DIST2(3.5) E DIST2(4.5) E CONNEC(1.2) E CONNEC(1.3) E CONNEC(1.4) E CONNEC(1.5) E CONNEC(2.3) E CONNEC(2.4) E CONNEC(2.5) E CONNEC(3.4) E CONNEC(3.5) E CONNEC(4.5) L DISJ1(1.2) L DISJ1(1.3) L DISJ1(1.4) L DISJ1(1.5) L DISJ1(2.3) L DISJ1(2.4) L DISJ1(2.5) L DISJ1(3.4) L DISJ1(3.5) L DISJ1(4.5) L DISJ2(1.2) L DISJ2(1.3) L DISJ2(1.4) L DISJ2(1.5) L DISJ2(2.3) L DISJ2(2.4) L DISJ2(2.5) L DISJ2(3.4) L DISJ2(3.5) L DISJ2(4.5) L DISJ3(1.2) L DISJ3(1.3) L DISJ3(1.4) L DISJ3(1.5) L DISJ3(2.3) L DISJ3(2.4) L DISJ3(2.5) L DISJ3(3.4) L DISJ3(3.5) L DISJ3(4.5) L DISJ4(1.2) L DISJ4(1.3) L DISJ4(1.4) L DISJ4(1.5) L DISJ4(2.3) L DISJ4(2.4) L DISJ4(2.5) L DISJ4(3.4) L DISJ4(3.5) L DISJ4(4.5) L DISJ5_1(1) L DISJ5_1(2) L DISJ5_1(3) L DISJ5_1(4) L DISJ5_1(5) G DISJ5_2(1) G DISJ5_2(2) G DISJ5_2(3) G DISJ5_2(4) G DISJ5_2(5) L DISJ5_3(1) L DISJ5_3(2) L DISJ5_3(3) L DISJ5_3(4) L DISJ5_3(5) G DISJ5_4(1) G DISJ5_4(2) G DISJ5_4(3) G DISJ5_4(4) G DISJ5_4(5) L DISJ6_1(1) L DISJ6_1(2) L DISJ6_1(3) L DISJ6_1(4) L DISJ6_1(5) G DISJ6_2(1) G DISJ6_2(2) G DISJ6_2(3) G DISJ6_2(4) G DISJ6_2(5) L DISJ6_3(1) L DISJ6_3(2) L DISJ6_3(3) L DISJ6_3(4) L DISJ6_3(5) G DISJ6_4(1) G DISJ6_4(2) G DISJ6_4(3) G DISJ6_4(4) G DISJ6_4(5) E BIN1(1.2) E BIN1(1.3) E BIN1(1.4) E BIN1(1.5) E BIN1(2.3) E BIN1(2.4) E BIN1(2.5) E BIN1(3.4) E BIN1(3.5) E BIN1(4.5) E BIN2(1) E BIN2(2) E BIN2(3) E BIN2(4) E BIN2(5) L BNDX(1) L BNDX(2) L BNDX(3) L BNDX(4) L BNDX(5) G BNDY(1) G BNDY(2) G BNDY(3) G BNDY(4) G BNDY(5) G BOUNDD(1.1) G BOUNDD(1.2) G BOUNDD(1.3) G BOUNDD(1.4) G BOUNDD(1.5) G BOUNDD(2.1) G BOUNDD(2.2) G BOUNDD(2.3) G BOUNDD(2.4) G BOUNDD(2.5) G BOUNDD(3.1) G BOUNDD(3.2) G BOUNDD(3.3) G BOUNDD(3.4) G BOUNDD(3.5) G BOUNDD(4.1) G BOUNDD(4.2) G BOUNDD(4.3) G BOUNDD(4.4) G BOUNDD(4.5) G BOUNDD(5.1) G BOUNDD(5.2) G BOUNDD(5.3) G BOUNDD(5.4) G BOUNDD(5.5) COLUMNS X(1) obj -1200 DIST1(1.2) -1 X(1) DIST1(1.3) -1 DIST1(1.4) -1 X(1) DIST1(1.5) -1 DISJ1(1.2) 1 X(1) DISJ1(1.3) 1 DISJ1(1.4) 1 X(1) DISJ1(1.5) 1 DISJ2(1.2) -1 X(1) DISJ2(1.3) -1 DISJ2(1.4) -1 X(1) DISJ2(1.5) -1 BNDX(1) 1 X(2) obj -3800 DIST1(1.2) 1 X(2) DIST1(2.3) -1 DIST1(2.4) -1 X(2) DIST1(2.5) -1 DISJ1(1.2) -1 X(2) DISJ1(2.3) 1 DISJ1(2.4) 1 X(2) DISJ1(2.5) 1 DISJ2(1.2) 1 X(2) DISJ2(2.3) -1 DISJ2(2.4) -1 X(2) DISJ2(2.5) -1 BNDX(2) 1 X(3) obj -1960 DIST1(1.3) 1 X(3) DIST1(2.3) 1 DIST1(3.4) -1 X(3) DIST1(3.5) -1 DISJ1(1.3) -1 X(3) DISJ1(2.3) -1 DISJ1(3.4) 1 X(3) DISJ1(3.5) 1 DISJ2(1.3) 1 X(3) DISJ2(2.3) 1 DISJ2(3.4) -1 X(3) DISJ2(3.5) -1 BNDX(3) 1 X(4) obj -1020 DIST1(1.4) 1 X(4) DIST1(2.4) 1 DIST1(3.4) 1 X(4) DIST1(4.5) -1 DISJ1(1.4) -1 X(4) DISJ1(2.4) -1 DISJ1(3.4) -1 X(4) DISJ1(4.5) 1 DISJ2(1.4) 1 X(4) DISJ2(2.4) 1 DISJ2(3.4) 1 X(4) DISJ2(4.5) -1 BNDX(4) 1 X(5) obj -240 DIST1(1.5) 1 X(5) DIST1(2.5) 1 DIST1(3.5) 1 X(5) DIST1(4.5) 1 DISJ1(1.5) -1 X(5) DISJ1(2.5) -1 DISJ1(3.5) -1 X(5) DISJ1(4.5) -1 DISJ2(1.5) 1 X(5) DISJ2(2.5) 1 DISJ2(3.5) 1 X(5) DISJ2(4.5) 1 BNDX(5) 1 Y(1) obj -3000 DIST2(1.2) -1 Y(1) DIST2(1.3) -1 DIST2(1.4) -1 Y(1) DIST2(1.5) -1 DISJ3(1.2) -1 Y(1) DISJ3(1.3) -1 DISJ3(1.4) -1 Y(1) DISJ3(1.5) -1 DISJ4(1.2) 1 Y(1) DISJ4(1.3) 1 DISJ4(1.4) 1 Y(1) DISJ4(1.5) 1 BNDY(1) 1 Y(2) obj -5700 DIST2(1.2) 1 Y(2) DIST2(2.3) -1 DIST2(2.4) -1 Y(2) DIST2(2.5) -1 DISJ3(1.2) 1 Y(2) DISJ3(2.3) -1 DISJ3(2.4) -1 Y(2) DISJ3(2.5) -1 DISJ4(1.2) -1 Y(2) DISJ4(2.3) 1 DISJ4(2.4) 1 Y(2) DISJ4(2.5) 1 BNDY(2) 1 Y(3) obj -2520 DIST2(1.3) 1 Y(3) DIST2(2.3) 1 DIST2(3.4) -1 Y(3) DIST2(3.5) -1 DISJ3(1.3) 1 Y(3) DISJ3(2.3) 1 DISJ3(3.4) -1 Y(3) DISJ3(3.5) -1 DISJ4(1.3) -1 Y(3) DISJ4(2.3) -1 DISJ4(3.4) 1 Y(3) DISJ4(3.5) 1 BNDY(3) 1 Y(4) obj -1020 DIST2(1.4) 1 Y(4) DIST2(2.4) 1 DIST2(3.4) 1 Y(4) DIST2(4.5) -1 DISJ3(1.4) 1 Y(4) DISJ3(2.4) 1 DISJ3(3.4) 1 Y(4) DISJ3(4.5) -1 DISJ4(1.4) -1 Y(4) DISJ4(2.4) -1 DISJ4(3.4) -1 Y(4) DISJ4(4.5) 1 BNDY(4) 1 Y(5) obj -1200 DIST2(1.5) 1 Y(5) DIST2(2.5) 1 DIST2(3.5) 1 Y(5) DIST2(4.5) 1 DISJ3(1.5) 1 Y(5) DISJ3(2.5) 1 DISJ3(3.5) 1 Y(5) DISJ3(4.5) 1 DISJ4(1.5) -1 Y(5) DISJ4(2.5) -1 DISJ4(3.5) -1 Y(5) DISJ4(4.5) -1 BNDY(5) 1 MARK0000 'MARKER' 'INTORG' Z(1.1.2) DISJ1(1.2) 53 BIN1(1.2) 1 Z(1.1.3) DISJ1(1.3) 53 BIN1(1.3) 1 Z(1.1.4) DISJ1(1.4) 53 BIN1(1.4) 1 Z(1.1.5) DISJ1(1.5) 53 BIN1(1.5) 1 Z(1.2.3) DISJ1(2.3) 53 BIN1(2.3) 1 Z(1.2.4) DISJ1(2.4) 53 BIN1(2.4) 1 Z(1.2.5) DISJ1(2.5) 53 BIN1(2.5) 1 Z(1.3.4) DISJ1(3.4) 53 BIN1(3.4) 1 Z(1.3.5) DISJ1(3.5) 53 BIN1(3.5) 1 Z(1.4.5) DISJ1(4.5) 53 BIN1(4.5) 1 Z(2.1.2) DISJ2(1.2) 53 BIN1(1.2) 1 Z(2.1.3) DISJ2(1.3) 53 BIN1(1.3) 1 Z(2.1.4) DISJ2(1.4) 53 BIN1(1.4) 1 Z(2.1.5) DISJ2(1.5) 53 BIN1(1.5) 1 Z(2.2.3) DISJ2(2.3) 53 BIN1(2.3) 1 Z(2.2.4) DISJ2(2.4) 53 BIN1(2.4) 1 Z(2.2.5) DISJ2(2.5) 53 BIN1(2.5) 1 Z(2.3.4) DISJ2(3.4) 53 BIN1(3.4) 1 Z(2.3.5) DISJ2(3.5) 53 BIN1(3.5) 1 Z(2.4.5) DISJ2(4.5) 53 BIN1(4.5) 1 Z(3.1.2) DISJ3(1.2) 53 BIN1(1.2) 1 Z(3.1.3) DISJ3(1.3) 53 BIN1(1.3) 1 Z(3.1.4) DISJ3(1.4) 53 BIN1(1.4) 1 Z(3.1.5) DISJ3(1.5) 53 BIN1(1.5) 1 Z(3.2.3) DISJ3(2.3) 53 BIN1(2.3) 1 Z(3.2.4) DISJ3(2.4) 53 BIN1(2.4) 1 Z(3.2.5) DISJ3(2.5) 53 BIN1(2.5) 1 Z(3.3.4) DISJ3(3.4) 53 BIN1(3.4) 1 Z(3.3.5) DISJ3(3.5) 53 BIN1(3.5) 1 Z(3.4.5) DISJ3(4.5) 53 BIN1(4.5) 1 Z(4.1.2) DISJ4(1.2) 53 BIN1(1.2) 1 Z(4.1.3) DISJ4(1.3) 53 BIN1(1.3) 1 Z(4.1.4) DISJ4(1.4) 53 BIN1(1.4) 1 Z(4.1.5) DISJ4(1.5) 53 BIN1(1.5) 1 Z(4.2.3) DISJ4(2.3) 53 BIN1(2.3) 1 Z(4.2.4) DISJ4(2.4) 53 BIN1(2.4) 1 Z(4.2.5) DISJ4(2.5) 53 BIN1(2.5) 1 Z(4.3.4) DISJ4(3.4) 53 BIN1(3.4) 1 Z(4.3.5) DISJ4(3.5) 53 BIN1(3.5) 1 Z(4.4.5) DISJ4(4.5) 53 BIN1(4.5) 1 W(1.1) DISJ5_2(1) -3 DISJ5_3(1) 3 W(1.1) BIN2(1) 1 W(1.2) DISJ5_1(2) 6 DISJ5_4(2) -6 W(1.2) BIN2(2) 1 W(1.3) DISJ5_1(3) 3 DISJ5_4(3) -3 W(1.3) BIN2(3) 1 W(1.4) DISJ5_1(4) 1 DISJ5_4(4) -1 W(1.4) BIN2(4) 1 W(1.5) DISJ5_1(5) 1 DISJ5_4(5) -1 W(1.5) BIN2(5) 1 W(2.1) DISJ6_1(1) 3 DISJ6_4(1) -3 W(2.1) BIN2(1) 1 W(2.2) DISJ6_2(2) -6 DISJ6_3(2) 6 W(2.2) BIN2(2) 1 W(2.3) DISJ6_2(3) -3 DISJ6_3(3) 3 W(2.3) BIN2(3) 1 W(2.4) DISJ6_2(4) -1 DISJ6_3(4) 1 W(2.4) BIN2(4) 1 W(2.5) DISJ6_2(5) -1 DISJ6_3(5) 1 W(2.5) BIN2(5) 1 MARK0001 'MARKER' 'INTEND' L(1) DISJ1(1.2) 1 DISJ1(1.3) 1 L(1) DISJ1(1.4) 1 DISJ1(1.5) 1 L(1) DISJ5_3(1) 1 DISJ5_4(1) 1 L(1) DISJ6_3(1) 1 DISJ6_4(1) 1 L(1) BNDX(1) 1 L(2) DISJ1(2.3) 1 DISJ1(2.4) 1 L(2) DISJ1(2.5) 1 DISJ2(1.2) 1 L(2) DISJ5_3(2) 1 DISJ5_4(2) 1 L(2) DISJ6_3(2) 1 DISJ6_4(2) 1 L(2) BNDX(2) 1 L(3) DISJ1(3.4) 1 DISJ1(3.5) 1 L(3) DISJ2(1.3) 1 DISJ2(2.3) 1 L(3) DISJ5_3(3) 1 DISJ5_4(3) 1 L(3) DISJ6_3(3) 1 DISJ6_4(3) 1 L(3) BNDX(3) 1 L(4) DISJ1(4.5) 1 DISJ2(1.4) 1 L(4) DISJ2(2.4) 1 DISJ2(3.4) 1 L(4) DISJ5_3(4) 1 DISJ5_4(4) 1 L(4) DISJ6_3(4) 1 DISJ6_4(4) 1 L(4) BNDX(4) 1 L(5) DISJ2(1.5) 1 DISJ2(2.5) 1 L(5) DISJ2(3.5) 1 DISJ2(4.5) 1 L(5) DISJ5_3(5) 1 DISJ5_4(5) 1 L(5) DISJ6_3(5) 1 DISJ6_4(5) 1 L(5) BNDX(5) 1 H(1) DISJ3(1.2) 1 DISJ3(1.3) 1 H(1) DISJ3(1.4) 1 DISJ3(1.5) 1 H(1) DISJ5_1(1) 1 DISJ5_2(1) 1 H(1) DISJ6_1(1) 1 DISJ6_2(1) 1 H(1) BNDY(1) -1 H(2) DISJ3(2.3) 1 DISJ3(2.4) 1 H(2) DISJ3(2.5) 1 DISJ4(1.2) 1 H(2) DISJ5_1(2) 1 DISJ5_2(2) 1 H(2) DISJ6_1(2) 1 DISJ6_2(2) 1 H(2) BNDY(2) -1 H(3) DISJ3(3.4) 1 DISJ3(3.5) 1 H(3) DISJ4(1.3) 1 DISJ4(2.3) 1 H(3) DISJ5_1(3) 1 DISJ5_2(3) 1 H(3) DISJ6_1(3) 1 DISJ6_2(3) 1 H(3) BNDY(3) -1 H(4) DISJ3(4.5) 1 DISJ4(1.4) 1 H(4) DISJ4(2.4) 1 DISJ4(3.4) 1 H(4) DISJ5_1(4) 1 DISJ5_2(4) 1 H(4) DISJ6_1(4) 1 DISJ6_2(4) 1 H(4) BNDY(4) -1 H(5) DISJ4(1.5) 1 DISJ4(2.5) 1 H(5) DISJ4(3.5) 1 DISJ4(4.5) 1 H(5) DISJ5_1(5) 1 DISJ5_2(5) 1 H(5) DISJ6_1(5) 1 DISJ6_2(5) 1 H(5) BNDY(5) -1 D(1.1) BOUNDD(1.1) 1 D(1.2) obj 300 CONNEC(1.2) 1 D(1.2) BOUNDD(1.2) 1 D(1.3) obj 400 CONNEC(1.3) 1 D(1.3) BOUNDD(1.3) 1 D(1.4) CONNEC(1.4) 1 BOUNDD(1.4) 1 D(1.5) CONNEC(1.5) 1 BOUNDD(1.5) 1 D(2.1) BOUNDD(2.1) 1 D(2.2) BOUNDD(2.2) 1 D(2.3) obj 85 CONNEC(2.3) 1 D(2.3) BOUNDD(2.3) 1 D(2.4) CONNEC(2.4) 1 BOUNDD(2.4) 1 D(2.5) CONNEC(2.5) 1 BOUNDD(2.5) 1 D(3.1) BOUNDD(3.1) 1 D(3.2) BOUNDD(3.2) 1 D(3.3) BOUNDD(3.3) 1 D(3.4) obj 75 CONNEC(3.4) 1 D(3.4) BOUNDD(3.4) 1 D(3.5) obj 60 CONNEC(3.5) 1 D(3.5) BOUNDD(3.5) 1 D(4.1) BOUNDD(4.1) 1 D(4.2) BOUNDD(4.2) 1 D(4.3) BOUNDD(4.3) 1 D(4.4) BOUNDD(4.4) 1 D(4.5) obj 100 CONNEC(4.5) 1 D(4.5) BOUNDD(4.5) 1 D(5.1) BOUNDD(5.1) 1 D(5.2) BOUNDD(5.2) 1 D(5.3) BOUNDD(5.3) 1 D(5.4) BOUNDD(5.4) 1 D(5.5) BOUNDD(5.5) 1 DELX1(1.2) DIST1(1.2) 1 CONNEC(1.2) -1 DELX1(1.3) DIST1(1.3) 1 CONNEC(1.3) -1 DELX1(1.4) DIST1(1.4) 1 CONNEC(1.4) -1 DELX1(1.5) DIST1(1.5) 1 CONNEC(1.5) -1 DELX1(2.3) DIST1(2.3) 1 CONNEC(2.3) -1 DELX1(2.4) DIST1(2.4) 1 CONNEC(2.4) -1 DELX1(2.5) DIST1(2.5) 1 CONNEC(2.5) -1 DELX1(3.4) DIST1(3.4) 1 CONNEC(3.4) -1 DELX1(3.5) DIST1(3.5) 1 CONNEC(3.5) -1 DELX1(4.5) DIST1(4.5) 1 CONNEC(4.5) -1 DELX2(1.2) DIST1(1.2) -1 CONNEC(1.2) -1 DELX2(1.3) DIST1(1.3) -1 CONNEC(1.3) -1 DELX2(1.4) DIST1(1.4) -1 CONNEC(1.4) -1 DELX2(1.5) DIST1(1.5) -1 CONNEC(1.5) -1 DELX2(2.3) DIST1(2.3) -1 CONNEC(2.3) -1 DELX2(2.4) DIST1(2.4) -1 CONNEC(2.4) -1 DELX2(2.5) DIST1(2.5) -1 CONNEC(2.5) -1 DELX2(3.4) DIST1(3.4) -1 CONNEC(3.4) -1 DELX2(3.5) DIST1(3.5) -1 CONNEC(3.5) -1 DELX2(4.5) DIST1(4.5) -1 CONNEC(4.5) -1 DELY1(1.2) DIST2(1.2) 1 CONNEC(1.2) -1 DELY1(1.3) DIST2(1.3) 1 CONNEC(1.3) -1 DELY1(1.4) DIST2(1.4) 1 CONNEC(1.4) -1 DELY1(1.5) DIST2(1.5) 1 CONNEC(1.5) -1 DELY1(2.3) DIST2(2.3) 1 CONNEC(2.3) -1 DELY1(2.4) DIST2(2.4) 1 CONNEC(2.4) -1 DELY1(2.5) DIST2(2.5) 1 CONNEC(2.5) -1 DELY1(3.4) DIST2(3.4) 1 CONNEC(3.4) -1 DELY1(3.5) DIST2(3.5) 1 CONNEC(3.5) -1 DELY1(4.5) DIST2(4.5) 1 CONNEC(4.5) -1 DELY2(1.2) DIST2(1.2) -1 CONNEC(1.2) -1 DELY2(1.3) DIST2(1.3) -1 CONNEC(1.3) -1 DELY2(1.4) DIST2(1.4) -1 CONNEC(1.4) -1 DELY2(1.5) DIST2(1.5) -1 CONNEC(1.5) -1 DELY2(2.3) DIST2(2.3) -1 CONNEC(2.3) -1 DELY2(2.4) DIST2(2.4) -1 CONNEC(2.4) -1 DELY2(2.5) DIST2(2.5) -1 CONNEC(2.5) -1 DELY2(3.4) DIST2(3.4) -1 CONNEC(3.4) -1 DELY2(3.5) DIST2(3.5) -1 CONNEC(3.5) -1 DELY2(4.5) DIST2(4.5) -1 CONNEC(4.5) -1 OBJ obj 1 OBJBM 1 RHS rhs OBJBM 103530 DISJ1(1.2) 53 rhs DISJ1(1.3) 53 DISJ1(1.4) 53 rhs DISJ1(1.5) 53 DISJ1(2.3) 53 rhs DISJ1(2.4) 53 DISJ1(2.5) 53 rhs DISJ1(3.4) 53 DISJ1(3.5) 53 rhs DISJ1(4.5) 53 DISJ2(1.2) 53 rhs DISJ2(1.3) 53 DISJ2(1.4) 53 rhs DISJ2(1.5) 53 DISJ2(2.3) 53 rhs DISJ2(2.4) 53 DISJ2(2.5) 53 rhs DISJ2(3.4) 53 DISJ2(3.5) 53 rhs DISJ2(4.5) 53 DISJ3(1.2) 53 rhs DISJ3(1.3) 53 DISJ3(1.4) 53 rhs DISJ3(1.5) 53 DISJ3(2.3) 53 rhs DISJ3(2.4) 53 DISJ3(2.5) 53 rhs DISJ3(3.4) 53 DISJ3(3.5) 53 rhs DISJ3(4.5) 53 DISJ4(1.2) 53 rhs DISJ4(1.3) 53 DISJ4(1.4) 53 rhs DISJ4(1.5) 53 DISJ4(2.3) 53 rhs DISJ4(2.4) 53 DISJ4(2.5) 53 rhs DISJ4(3.4) 53 DISJ4(3.5) 53 rhs DISJ4(4.5) 53 DISJ5_1(1) 8 rhs DISJ5_1(2) 11 DISJ5_1(3) 7 rhs DISJ5_1(4) 8 DISJ5_1(5) 3 rhs DISJ5_2(1) 5 DISJ5_2(2) 5 rhs DISJ5_2(3) 4 DISJ5_2(4) 7 rhs DISJ5_2(5) 2 DISJ5_3(1) 8 rhs DISJ5_3(2) 11 DISJ5_3(3) 7 rhs DISJ5_3(4) 8 DISJ5_3(5) 3 rhs DISJ5_4(1) 5 DISJ5_4(2) 5 rhs DISJ5_4(3) 4 DISJ5_4(4) 7 rhs DISJ5_4(5) 2 DISJ6_1(1) 8 rhs DISJ6_1(2) 11 DISJ6_1(3) 7 rhs DISJ6_1(4) 8 DISJ6_1(5) 3 rhs DISJ6_2(1) 5 DISJ6_2(2) 5 rhs DISJ6_2(3) 4 DISJ6_2(4) 7 rhs DISJ6_2(5) 2 DISJ6_3(1) 8 rhs DISJ6_3(2) 11 DISJ6_3(3) 7 rhs DISJ6_3(4) 8 DISJ6_3(5) 3 rhs DISJ6_4(1) 5 DISJ6_4(2) 5 rhs DISJ6_4(3) 4 DISJ6_4(4) 7 rhs DISJ6_4(5) 2 BIN1(1.2) 1 rhs BIN1(1.3) 1 BIN1(1.4) 1 rhs BIN1(1.5) 1 BIN1(2.3) 1 rhs BIN1(2.4) 1 BIN1(2.5) 1 rhs BIN1(3.4) 1 BIN1(3.5) 1 rhs BIN1(4.5) 1 BIN2(1) 1 rhs BIN2(2) 1 BIN2(3) 1 rhs BIN2(4) 1 BIN2(5) 1 rhs BNDX(1) 53 BNDX(2) 53 rhs BNDX(3) 53 BNDX(4) 53 rhs BNDX(5) 53 BOUNDD(1.2) 5 rhs BOUNDD(1.3) 4 BOUNDD(1.4) 5 rhs BOUNDD(1.5) 2 BOUNDD(2.3) 4 rhs BOUNDD(2.4) 5 BOUNDD(2.5) 2 rhs BOUNDD(3.4) 4 BOUNDD(3.5) 2 rhs BOUNDD(4.5) 2 BOUNDS UP bnd Y(1) 53 UP bnd Y(2) 53 UP bnd Y(3) 53 UP bnd Y(4) 53 UP bnd Y(5) 53 UP bnd Z(1.1.2) 1 UP bnd Z(1.1.3) 1 UP bnd Z(1.1.4) 1 UP bnd Z(1.1.5) 1 UP bnd Z(1.2.3) 1 UP bnd Z(1.2.4) 1 UP bnd Z(1.2.5) 1 UP bnd Z(1.3.4) 1 UP bnd Z(1.3.5) 1 UP bnd Z(1.4.5) 1 UP bnd Z(2.1.2) 1 UP bnd Z(2.1.3) 1 UP bnd Z(2.1.4) 1 UP bnd Z(2.1.5) 1 UP bnd Z(2.2.3) 1 UP bnd Z(2.2.4) 1 UP bnd Z(2.2.5) 1 UP bnd Z(2.3.4) 1 UP bnd Z(2.3.5) 1 UP bnd Z(2.4.5) 1 UP bnd Z(3.1.2) 1 UP bnd Z(3.1.3) 1 UP bnd Z(3.1.4) 1 UP bnd Z(3.1.5) 1 UP bnd Z(3.2.3) 1 UP bnd Z(3.2.4) 1 UP bnd Z(3.2.5) 1 UP bnd Z(3.3.4) 1 UP bnd Z(3.3.5) 1 UP bnd Z(3.4.5) 1 UP bnd Z(4.1.2) 1 UP bnd Z(4.1.3) 1 UP bnd Z(4.1.4) 1 UP bnd Z(4.1.5) 1 UP bnd Z(4.2.3) 1 UP bnd Z(4.2.4) 1 UP bnd Z(4.2.5) 1 UP bnd Z(4.3.4) 1 UP bnd Z(4.3.5) 1 UP bnd Z(4.4.5) 1 UP bnd W(1.1) 1 UP bnd W(1.2) 1 UP bnd W(1.3) 1 UP bnd W(1.4) 1 UP bnd W(1.5) 1 UP bnd W(2.1) 1 UP bnd W(2.2) 1 UP bnd W(2.3) 1 UP bnd W(2.4) 1 UP bnd W(2.5) 1 FR bnd OBJ QUADOBJ X(1) X(1) 300 X(2) X(2) 380 X(3) X(3) 280 X(4) X(4) 340 X(5) X(5) 240 Y(1) Y(1) 300 Y(2) Y(2) 380 Y(3) Y(3) 280 Y(4) Y(4) 340 Y(5) Y(5) 240 ENDATA Cbc-2.8.12/examples/link.cpp0000644000076600007660000001501212131315050014216 0ustar coincoin// $Id: link.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CoinModel.hpp" // For Linked Ordered Sets #include "CbcBranchLink.hpp" #include "OsiClpSolverInterface.hpp" #include "CoinTime.hpp" /************************************************************************ This shows how we can define a new branching method to solve problems with nonlinearities and discontinuities. We are going to solve the problem minimize 10.0*x + y + z - w where x, y are continuous between 1 and 10, z can take the values 0, 0.1, 0.2 up to 1.0 and w can take the values 0 or 1. There is one constraint w <= x*z**2 + y*sqrt(z) One could try to use logarithms to make the problem separable but that is a very weak formulation as we want to branch on z directly. The answer is the concept of linked special ordered sets. The generalization with column generation can be even more powerful but here we are limiting z to discrete values to avoid column generation. The idea is simple: A linear variable is a convex combination of its lower bound and upper bound! If x must lie between 2 and 10 then we can substitute for x as x == 2.0*xl + 10.0*xu where xl + xu == 1.0. At first this looks cumbersome but if we have xl0, xl1, ... xl10 and corresponding xu and yl and yu then we can write: x == sum 2.0*xl[i] + 10.0* xu[i] where sum xl[i] + xu[i] == 1.0 and x*z**2 == 0.02*xl1 + 0.1*xu1 + 0.08*xl2 + 0.4*xu2 .... + 2.0*xl10 + 10.0*xu10 with similar substitutions for y and y*sqrt(z) And now the problem is satisfied if w is 0 or 1 and xl[i], xu[i], yl[i] and yu[i] are only nonzero for one i. So this is just like a special ordered set of type 1 but on four sets simultaneously. Also note that convexity requirements for any non-linear functions are not needed. So we need a new branching method to do that - see CbcBranchLink.?pp We are going to need a CbcBranchLink method to see whether we are satisfied etc and also to create another branching object which knows how to fix variables. We might be able to use an existing method for the latter but let us create two methods CbcLink and CbcLinkBranchingObject. For CbcLink we will need the following methods: Constructot/Destructor infeasibility - returns 0.0 if feasible otherwise some measure of infeasibility feasibleRegion - sets bounds to contain current solution createBranch - creates a CbcLinkBranchingObject For CbcLinkBranchingObject we need: Constructor/Destructor branch - does actual fixing print - optional for debug purposes. The easiest way to do this is to cut and paste from CbcBranchActual to get current SOS stuff and then modify that. ************************************************************************/ int main (int argc, const char *argv[]) { OsiClpSolverInterface solver1; // Create model CoinModel build; // Keep x,y and z for reporting purposes in rows 0,1,2 // Do these double value=1.0; int row=-1; // x row=0; build.addColumn(1,&row,&value,1.0,10.0,10.0); // y row=1; build.addColumn(1,&row,&value,1.0,10.0,1.0); // z row=2; build.addColumn(1,&row,&value,0.0,1.0,1.0); // w row=3; build.addColumn(1,&row,&value,0.0,1.0,-1.0); build.setInteger(3); // Do columns so we know where each is int i; for (i=4;i<4+44;i++) build.setColumnBounds(i,0.0,1.0); // Now do rows // x build.setRowBounds(0,0.0,0.0); for (i=0;i<11;i++) { // xl build.setElement(0,4+4*i,-1.0); // xu build.setElement(0,4+4*i+1,-10.0); } // y build.setRowBounds(1,0.0,0.0); for (i=0;i<11;i++) { // yl build.setElement(1,4+4*i+2,-1.0); // yu build.setElement(1,4+4*i+3,-10.0); } // z - just use x part build.setRowBounds(2,0.0,0.0); for (i=0;i<11;i++) { // xl build.setElement(2,4+4*i,-0.1*i); // xu build.setElement(2,4+4*i+1,-0.1*i); } // w <= x*z**2 + y* sqrt(z) build.setRowBounds(3,-COIN_DBL_MAX,0.0); for (i=0;i<11;i++) { double value = 0.1*i; // xl * z**2 build.setElement(3,4+4*i,-1.0*value*value); // xu * z**2 build.setElement(3,4+4*i+1,-10.0*value*value); // yl * sqrt(z) build.setElement(3,4+4*i+2,-1.0*sqrt(value)); // yu * sqrt(z) build.setElement(3,4+4*i+3,-10.0*sqrt(value)); } // and convexity for x and y // x build.setRowBounds(4,1.0,1.0); for (i=0;i<11;i++) { // xl build.setElement(4,4+4*i,1.0); // xu build.setElement(4,4+4*i+1,1.0); } // y build.setRowBounds(5,1.0,1.0); for (i=0;i<11;i++) { // yl build.setElement(5,4+4*i+2,1.0); // yu build.setElement(5,4+4*i+3,1.0); } solver1.loadFromCoinModel(build); // To make CbcBranchLink simpler assume that all variables with same i are consecutive double time1 = CoinCpuTime(); solver1.initialSolve(); solver1.writeMps("bad"); CbcModel model(solver1); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Although just one set - code as if more CbcObject ** objects = new CbcObject * [1]; /* Format is number in sets, number in each link, first variable in matrix) and then a weight for each in set to say where to branch. Finally a set number as ID. */ double where[]={0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0}; objects[0]=new CbcLink(&model,11,4,4,where,0); model.addObjects(1,objects); delete objects[0]; delete [] objects; // Do complete search model.branchAndBound(); std::cout<<"took "<1.0e-7) { if (which==-1) which=i; else assert (which==i); } } } double x=solution[0]; double y=solution[1]; double z=solution[2]; double w=solution[3]; // check z assert (fabs(z-0.1*((double) which))<1.0e-7); printf("Optimal solution when x is %g, y %g, z %g and w %g\n", x,y,z,w); printf("solution should be %g\n",10.0*x+y+z-w); } return 0; } Cbc-2.8.12/examples/barrier.cpp0000644000076600007660000000450012131315050014707 0ustar coincoin// $Id: barrier.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include "CoinPragma.hpp" #include "OsiClpSolverInterface.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program reads in a model from an mps file. It then tells the OsiClpSolver to use barrier for initialSolve The cryptic code was generated by playing around with "clp" and using -cpp option. So clp input.mps -cpp 1 -barrier created a user_driver.cpp from which the lines between ===== were taken ************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Taken from a user_driver.cpp // ======================= ClpSolve::SolveType method = ClpSolve::useBarrier; ClpSolve::PresolveType presolveType = ClpSolve::presolveOn; int numberPasses = 5; #ifndef UFL_BARRIER int options[] = {0,0,0,0,0,0}; #else // we can use UFL code int options[] = {0,0,0,0,4,0}; #endif int extraInfo[] = {-1,-1,-1,-1,-1,-1}; int independentOptions[] = {0,0,3}; ClpSolve clpSolve(method,presolveType,numberPasses, options,extraInfo,independentOptions); // ======================= // now pass options in solver1.setSolveOptions(clpSolve); // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); solver1.initialSolve(); std::cout< #include #include //#define CBC_DEBUG #include "CoinPragma.hpp" #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchLink.hpp" #include "CoinError.hpp" #include "CoinPackedMatrix.hpp" // Default Constructor CbcLink::CbcLink () : CbcObject(), weights_(NULL), numberMembers_(0), numberLinks_(0), which_(NULL), sosType_(1) { } // Useful constructor (which are indices) CbcLink::CbcLink (CbcModel * model, int numberMembers, int numberLinks, int first , const double * weights, int identifier) : CbcObject(model), numberMembers_(numberMembers), numberLinks_(numberLinks), which_(NULL), sosType_(1) { id_=identifier; if (numberMembers_) { weights_ = new double[numberMembers_]; which_ = new int[numberMembers_*numberLinks_]; if (weights) { memcpy(weights_,weights,numberMembers_*sizeof(double)); } else { for (int i=0;iweights_[i-1]+1.0e-12); for (i=0;iweights_[i-1]+1.0e-12); for (i=0;isolver(); const double * solution = model_->testSolution(); //const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double weight = 0.0; double sum =0.0; // check bounds etc double lastWeight=-1.0e100; int base=0; for (j=0;j=weights_[j]-1.0e-7) throw CoinError("Weights too close together in CBCLink","infeasibility","CbcLink"); double value = CoinMax(0.0,solution[iColumn]); sum += value; if (value>integerTolerance&&upper[iColumn]) { // Possibly due to scaling a fixed variable might slip through if (value>upper[iColumn]+1.0e-8) { // Could change to #ifdef CBC_DEBUG #ifndef NDEBUG if (model_->messageHandler()->logLevel()>1) printf("** Variable %d (%d) has value %g and upper bound of %g\n", iColumn,j,value,upper[iColumn]); #endif } value = CoinMin(value,upper[iColumn]); weight += weights_[j]*value; if (firstNonZero<0) firstNonZero=j; lastNonZero=j; } } base += numberLinks_; } double valueInfeasibility; preferredWay=1; if (lastNonZero-firstNonZero>=sosType_) { // find where to branch assert (sum>0.0); weight /= sum; valueInfeasibility = lastNonZero-firstNonZero+1; valueInfeasibility *= 0.5/((double) numberMembers_); //#define DISTANCE #ifdef DISTANCE assert (sosType_==1); // code up /* may still be satisfied. For LOS type 2 we might wish to move coding around and keep initial info in model_ for speed */ int iWhere; bool possible=false; for (iWhere=firstNonZero;iWhere<=lastNonZero;iWhere++) { if (fabs(weight-weights_[iWhere])<1.0e-8) { possible=true; break; } } if (possible) { // One could move some of this (+ arrays) into model_ const CoinPackedMatrix * matrix = solver->getMatrixByCol(); const double * element = matrix->getMutableElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * rowSolution = solver->getRowActivity(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = matrix->getNumRows(); double * array = new double [numberRows]; CoinZeroN(array,numberRows); int * which = new int [numberRows]; int n=0; int base=numberLinks_*firstNonZero; for (j=firstNonZero;j<=lastNonZero;j++) { for (int k=0;kintegerTolerance&&upper[iColumn]) { value = CoinMin(value,upper[iColumn]); for (int j=columnStart[iColumn];j1.0e-8) { if (distance+rowSolution[iRow]>rowUpper[iRow]+1.0e-8) { possible=false; break; } } else if (distance<-1.0e-8) { if (distance+rowSolution[iRow]solver(); const double * solution = model_->testSolution(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double weight = 0.0; double sum =0.0; int base=0; for (j=0;jintegerTolerance&&upper[iColumn]) { weight += weights_[j]*value; if (firstNonZero<0) firstNonZero=j; lastNonZero=j; } } base += numberLinks_; } #ifdef DISTANCE if (lastNonZero-firstNonZero>sosType_-1) { /* may still be satisfied. For LOS type 2 we might wish to move coding around and keep initial info in model_ for speed */ int iWhere; bool possible=false; for (iWhere=firstNonZero;iWhere<=lastNonZero;iWhere++) { if (fabs(weight-weights_[iWhere])<1.0e-8) { possible=true; break; } } if (possible) { // One could move some of this (+ arrays) into model_ const CoinPackedMatrix * matrix = solver->getMatrixByCol(); const double * element = matrix->getMutableElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * rowSolution = solver->getRowActivity(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = matrix->getNumRows(); double * array = new double [numberRows]; CoinZeroN(array,numberRows); int * which = new int [numberRows]; int n=0; int base=numberLinks_*firstNonZero; for (j=firstNonZero;j<=lastNonZero;j++) { for (int k=0;kintegerTolerance&&upper[iColumn]) { value = CoinMin(value,upper[iColumn]); for (int j=columnStart[iColumn];j1.0e-8) { if (distance+rowSolution[iRow]>rowUpper[iRow]+1.0e-8) { possible=false; break; } } else if (distance<-1.0e-8) { if (distance+rowSolution[iRow]setColUpper(iColumn,0.0); } base += numberLinks_; } // skip base += numberLinks_; for (j=lastNonZero+1;jsetColUpper(iColumn,0.0); } base += numberLinks_; } } // Creates a branching object CbcBranchingObject * CbcLink::createCbcBranch(OsiSolverInterface * /*solver*/, const OsiBranchingInformation * /*info*/, int way) { int j; const double * solution = model_->testSolution(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); OsiSolverInterface * solver = model_->solver(); const double * upper = solver->getColUpper(); int firstNonFixed=-1; int lastNonFixed=-1; int firstNonZero=-1; int lastNonZero = -1; double weight = 0.0; double sum =0.0; int base=0; for (j=0;jintegerTolerance) { weight += weights_[j]*value; if (firstNonZero<0) firstNonZero=j; lastNonZero=j; } } } base += numberLinks_; } assert (lastNonZero-firstNonZero>=sosType_) ; // find where to branch assert (sum>0.0); weight /= sum; int iWhere; double separator=0.0; for (iWhere=firstNonZero;iWhereid(),way,0.5) { set_ = set; separator_ = separator; } // Copy constructor CbcLinkBranchingObject::CbcLinkBranchingObject ( const CbcLinkBranchingObject & rhs) :CbcBranchingObject(rhs) { set_=rhs.set_; separator_ = rhs.separator_; } // Assignment operator CbcLinkBranchingObject & CbcLinkBranchingObject::operator=( const CbcLinkBranchingObject& rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); set_=rhs.set_; separator_ = rhs.separator_; } return *this; } CbcBranchingObject * CbcLinkBranchingObject::clone() const { return (new CbcLinkBranchingObject(*this)); } // Destructor CbcLinkBranchingObject::~CbcLinkBranchingObject () { } double CbcLinkBranchingObject::branch() { decrementNumberBranchesLeft(); int numberMembers = set_->numberMembers(); int numberLinks = set_->numberLinks(); const double * weights = set_->weights(); const int * which = set_->which(); OsiSolverInterface * solver = model_->solver(); //const double * lower = solver->getColLower(); //const double * upper = solver->getColUpper(); // *** for way - up means fix all those in down section if (way_<0) { int i; for ( i=0;i separator_) break; } assert (isetColUpper(iColumn,0.0); } base += numberLinks; } way_=1; // Swap direction } else { int i; int base=0; for ( i=0;i= separator_) { break; } else { for (int k=0;ksetColUpper(iColumn,0.0); } base += numberLinks; } } assert (inumberMembers(); int numberLinks = set_->numberLinks(); const double * weights = set_->weights(); const int * which = set_->which(); OsiSolverInterface * solver = model_->solver(); const double * upper = solver->getColUpper(); int first=numberMembers; int last=-1; int numberFixed=0; int numberOther=0; int i; int base=0; for ( i=0;i separator_) break; for (int k=0;k= separator_) break; for (int k=0;k %d (%g), %d would be fixed, %d other way\n", separator_,first,weights[first],last,weights[last],numberFixed/numberLinks, numberOther/numberLinks); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcLinkBranchingObject::compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap) { throw("must implement"); } Cbc-2.8.12/examples/CbcBranchLink.hpp0000644000076600007660000001035312131315050015714 0ustar coincoin// $Id: CbcBranchLink.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcBranchLink_H #define CbcBranchLink_H #include "CbcBranchBase.hpp" /** Define Special Linked Ordered Sets. */ class CbcLink : public CbcObject { public: // Default Constructor CbcLink (); /** Useful constructor - A valid solution is if all variables are zero apart from k*numberLink to (k+1)*numberLink-1 where k is 0 through numberInSet-1. The length of weights array is numberInSet. For this constructor the variables in matrix are the numberInSet*numberLink starting at first. If weights null then 0,1,2.. */ CbcLink (CbcModel * model, int numberMembers, int numberLinks, int first, const double * weights, int setNumber); /** Useful constructor - A valid solution is if all variables are zero apart from k*numberLink to (k+1)*numberLink-1 where k is 0 through numberInSet-1. The length of weights array is numberInSet. For this constructor the variables are given by list - grouped. If weights null then 0,1,2.. */ CbcLink (CbcModel * model, int numberMembers, int numberLinks, int typeSOS, const int * which, const double * weights, int setNumber); // Copy constructor CbcLink ( const CbcLink &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcLink & operator=( const CbcLink& rhs); // Destructor ~CbcLink (); /// Infeasibility - large is 0.5 virtual double infeasibility(int & preferredWay) const; /// This looks at solution and sets bounds to contain solution virtual void feasibleRegion(); /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Number of members inline int numberMembers() const {return numberMembers_;} /// Number of links for each member inline int numberLinks() const {return numberLinks_;} /// Which variables inline const int * which() const {return which_;} /** Array of weights */ inline const double * weights() const { return weights_;} private: /// data /// Weights double * weights_; /// Number of members int numberMembers_; /// Number of links int numberLinks_; /// Members int * which_; /// Type 1 or 2 int sosType_; }; /** Branching object for Special ordered sets Variable_ is the set id number (redundant, as the object also holds a pointer to the set. */ class CbcLinkBranchingObject : public CbcBranchingObject { public: // Default Constructor CbcLinkBranchingObject (); // Useful constructor CbcLinkBranchingObject (CbcModel * model, const CbcLink * set, int way, double separator); // Copy constructor CbcLinkBranchingObject ( const CbcLinkBranchingObject &); // Assignment operator CbcLinkBranchingObject & operator=( const CbcLinkBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; // Destructor virtual ~CbcLinkBranchingObject (); /// Does next branch and updates state virtual double branch(); /** \brief Print something about branch - only if log level high */ virtual void print(); /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return CbcBranchObjType(0);} /*FIXME what type() should be returned here? */ /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); private: /// data const CbcLink * set_; /// separator double separator_; }; #endif Cbc-2.8.12/examples/CbcBranchFollow2.hpp0000644000076600007660000000457211510742723016364 0ustar coincoin// $Id: CbcBranchFollow2.hpp 1574 2011-01-05 01:13:55Z lou $ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcBranchFollowOn2_H #define CbcBranchFollowOn2_H #include "CbcBranchActual.hpp" #include "CoinPackedMatrix.hpp" /** Define a follow on class. The idea of this is that in air-crew scheduling problems crew may fly in on flight A and out on flight B or on some other flight. A useful branch is one which on one side fixes all which go out on flight B to 0, while the other branch fixes all those that do NOT go out on flight B to 0. This tries to generalize so that cuts are produced with sum aij xj <= bi on each side. It should be intelligent enough to fix if things can be fixed. We also need to make sure branch cuts work properly (i.e. persistence). This branching rule should be in addition to normal rules and have a high priority. */ class CbcFollowOn2 : public CbcObject { public: // Default Constructor CbcFollowOn2 (); /** Useful constructor */ CbcFollowOn2 (CbcModel * model); // Copy constructor CbcFollowOn2 ( const CbcFollowOn2 &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcFollowOn2 & operator=( const CbcFollowOn2& rhs); // Destructor ~CbcFollowOn2 (); /// Infeasibility - large is 0.5 virtual double infeasibility(int & preferredWay) const; /// This looks at solution and sets bounds to contain solution virtual void feasibleRegion(); /// Creates a branching object virtual CbcBranchingObject * createBranch(int way) ; /** As some computation is needed in more than one place - returns row. Also returns other row and effective rhs (so we can know if cut) */ virtual int gutsOfFollowOn2(int & otherRow, int & preferredWay, int & effectiveRhs) const; /// get and set for maximum rhws (affects cuts as branch) inline int maximumRhs() const { return maximumRhs_;} inline void setMaximumRhs(int value) { maximumRhs_=value;} protected: /// data /// Matrix CoinPackedMatrix matrix_; /// Matrix by row CoinPackedMatrix matrixByRow_; /// Possible rhs (if 0 then not possible) int * rhs_; /// If >1 then allow cuts if effective rhs <= this int maximumRhs_; }; #endif Cbc-2.8.12/examples/ClpQuadInterface.cpp0000644000076600007660000001062611510742723016454 0ustar coincoin// $Id: ClpQuadInterface.cpp 1574 2011-01-05 01:13:55Z lou $ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include "CoinHelperFunctions.hpp" //#include "CoinIndexedVector.hpp" #include "ClpQuadraticObjective.hpp" #include "ClpLinearObjective.hpp" #include "ClpObjective.hpp" //#include "ClpSimplex.hpp" #include "ClpQuadInterface.hpp" //############################################################################# // Solve methods //############################################################################# void ClpQuadInterface::initialSolve() { // save cutoff double cutoff = modelPtr_->dualObjectiveLimit(); modelPtr_->setDualObjectiveLimit(1.0e50); modelPtr_->scaling(0); modelPtr_->setLogLevel(0); // solve with no objective to get feasible solution setBasis(basis_,modelPtr_); modelPtr_->dual(); basis_ = getBasis(modelPtr_); modelPtr_->setDualObjectiveLimit(cutoff); if (modelPtr_->problemStatus()) { assert (modelPtr_->problemStatus()==1); return; } ClpObjective * saveObjective = modelPtr_->objectiveAsObject(); modelPtr_->setObjectivePointer(quadraticObjective_); //modelPtr_->setLogLevel(1); // Could load up any data into a solver modelPtr_->primal(); modelPtr_->setDualObjectiveLimit(cutoff); if (modelPtr_->objectiveValue()>cutoff) modelPtr_->setProblemStatus(1); // zero reduced costs // Should not have to as convex //CoinZeroN(modelPtr_->dualRowSolution(),modelPtr_->numberRows()); //CoinZeroN(modelPtr_->dualColumnSolution(),modelPtr_->numberColumns()); modelPtr_->setObjectivePointer(saveObjective); } //----------------------------------------------------------------------------- void ClpQuadInterface::resolve() { initialSolve(); } //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpQuadInterface::ClpQuadInterface () : OsiClpSolverInterface() { quadraticObjective_=NULL; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * ClpQuadInterface::clone(bool CopyData) const { if (CopyData) { return new ClpQuadInterface(*this); } else { printf("warning ClpQuadInterface clone with copyData false\n"); return new ClpQuadInterface(); } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpQuadInterface::ClpQuadInterface ( const ClpQuadInterface & rhs) : OsiClpSolverInterface(rhs) { if (rhs.quadraticObjective_) quadraticObjective_=rhs.quadraticObjective_->clone(); else quadraticObjective_=NULL; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpQuadInterface::~ClpQuadInterface () { delete quadraticObjective_; } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpQuadInterface & ClpQuadInterface::operator=(const ClpQuadInterface& rhs) { if (this != &rhs) { OsiClpSolverInterface::operator=(rhs); if (rhs.quadraticObjective_) quadraticObjective_=rhs.quadraticObjective_->clone(); else quadraticObjective_=NULL; } return *this; } //------------------------------------------------------------------- // Real initializer //------------------------------------------------------------------- void ClpQuadInterface::initialize () { // Save true objective and create a fake one delete quadraticObjective_; quadraticObjective_ = modelPtr_->objectiveAsObject(); ClpLinearObjective * linearObjective = new ClpLinearObjective(NULL,modelPtr_->numberColumns()); modelPtr_->setObjectivePointer(linearObjective); } // Get objective function value (can't use default) double ClpQuadInterface::getObjValue() const { // first try easy way return modelPtr_->objectiveValue(); } Cbc-2.8.12/examples/CbcSolver2.cpp0000644000076600007660000003307511510742723015251 0ustar coincoin// $Id: CbcSolver2.cpp 1574 2011-01-05 01:13:55Z lou $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include "CoinTime.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "ClpFactorization.hpp" #include "ClpObjective.hpp" #include "ClpSimplex.hpp" #include "ClpSolve.hpp" #include "CbcSolver2.hpp" #include "CbcModel.hpp" #include "CoinModel.hpp" static int timesBad_=0; static int iterationsBad_=0; //############################################################################# // Solve methods //############################################################################# void CbcSolver2::initialSolve() { modelPtr_->scaling(0); setBasis(basis_,modelPtr_); // Do long thin by sprint ClpSolve options; options.setSolveType(ClpSolve::usePrimalorSprint); options.setPresolveType(ClpSolve::presolveOff); options.setSpecialOption(1,3,30); modelPtr_->initialSolve(options); basis_ = getBasis(modelPtr_); modelPtr_->setLogLevel(0); } //----------------------------------------------------------------------------- void CbcSolver2::resolve() { int numberColumns = modelPtr_->numberColumns(); if ((count_<10&&algorithm_==2)||!algorithm_) { OsiClpSolverInterface::resolve(); if (modelPtr_->status()==0) { count_++; double * solution = modelPtr_->primalColumnSolution(); int i; for (i=0;i1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } } else { if (!algorithm_==2) printf("infeasible early on\n"); } } else { // use counts int numberRows=modelPtr_->numberRows(); int * whichRow = new int[numberRows]; int * whichColumn = new int [numberColumns]; int i; const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); const double * rowUpper = modelPtr_->rowUpper(); bool equality=false; for (i=0;imatrix()->getElements(); const int * row = modelPtr_->matrix()->getIndices(); const CoinBigIndex * columnStart = modelPtr_->matrix()->getVectorStarts(); const int * columnLength = modelPtr_->matrix()->getVectorLengths(); int * rowActivity = new int[numberRows]; memset(rowActivity,0,numberRows*sizeof(int)); int * rowActivity2 = new int[numberRows]; memset(rowActivity2,0,numberRows*sizeof(int)); char * mark = new char[numberColumns]; memset(mark,0,numberColumns); // Get rows which are satisfied for (i=0;i0.0) { CoinBigIndex j; for (j=columnStart[i]; j1) { feasible=false; break; } } if (!feasible) { delete [] rowActivity; delete [] rowActivity2; modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; delete [] mark; printf("infeasible by inspection (over)\n"); return; } } int nNoGood=0; for (i=0;icount_-memory_&&node_[i]>0); bool any; if (equality) { // See if forced to be zero CoinBigIndex j; any=true; for (j=columnStart[i]; jgetColumnStatus(i)==ClpSimplex::basic) choose=true; if (choose||lower[i]>0.0) { mark[i]=1; whichColumn[nNewCol++]=i; CoinBigIndex j; double value = upper[i]; if (value) { for (j=columnStart[i]; jsetRowStatus(i,ClpSimplex::basic); // make slack basic } if (nOKsetProblemStatus(1); delete [] whichRow; delete [] whichColumn; delete [] mark; printf("infeasible by inspection\n"); return; } bool allIn=false; if (nNewCol+nNoGood+numberRows>numberColumns) { // add in all allIn=true; for (i=0;iaddColumns(build); temp->setLogLevel(1); printf("small has %d rows and %d columns (%d impossible to help) %s\n", nNewRow,nNewCol,nNoGood,allIn ? "all in" : ""); temp->setSpecialOptions(128+512); temp->setDualObjectiveLimit(1.0e50); temp->dual(); assert (!temp->status()); double * solution = modelPtr_->primalColumnSolution(); const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;isetStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;isetRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } // See if optimal double * dj = modelPtr_->dualColumnSolution(); // get reduced cost for large problem // this assumes minimization memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double)); modelPtr_->transposeTimes(-1.0,dual,dj); modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); int nBad=0; for (i=0;igetStatus(i)==ClpSimplex::atLowerBound &&upper[i]>lower[i]&&dj[i]<-1.0e-5) nBad++; } //modelPtr_->writeMps("bada.mps"); //temp->writeMps("badb.mps"); delete temp; if (nBad&&!allIn) { assert (algorithm_==2); //printf("%d bad\n",nBad); timesBad_++; // just non mark==2 int nAdded=0; for (i=0;iaddColumns(build); temp->setLogLevel(2); temp->setSpecialOptions(128+512); temp->setDualObjectiveLimit(1.0e50); temp->primal(1); assert (!temp->status()); double * solution = modelPtr_->primalColumnSolution(); const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;isetStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;isetRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); iterationsBad_ += temp->numberIterations(); printf("clean %d\n",temp->numberIterations()); delete temp; } } delete [] mark; delete [] whichRow; delete [] whichColumn; basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); count_++; if ((count_%100)==0&&algorithm_==2) printf("count %d, bad %d - iterations %d\n",count_,timesBad_,iterationsBad_); for (i=0;i1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } if (modelPtr_->objectiveValue()>=modelPtr_->dualObjectiveLimit()) modelPtr_->setProblemStatus(1); } } //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CbcSolver2::CbcSolver2 () : OsiClpSolverInterface() { node_=NULL; howMany_=NULL; count_=0; model_ = NULL; memory_=300; algorithm_=0; strategy_=0; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * CbcSolver2::clone(bool CopyData) const { if (CopyData) { return new CbcSolver2(*this); } else { printf("warning CbcSolveUser clone with copyData false\n"); return new CbcSolver2(); } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CbcSolver2::CbcSolver2 ( const CbcSolver2 & rhs) : OsiClpSolverInterface(rhs) { model_ = rhs.model_; int numberColumns = modelPtr_->numberColumns(); node_=CoinCopyOfArray(rhs.node_,numberColumns); howMany_=CoinCopyOfArray(rhs.howMany_,numberColumns); count_=rhs.count_; memory_=rhs.memory_; algorithm_=rhs.algorithm_; strategy_=rhs.strategy_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CbcSolver2::~CbcSolver2 () { delete [] node_; delete [] howMany_; } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcSolver2 & CbcSolver2::operator=(const CbcSolver2& rhs) { if (this != &rhs) { OsiClpSolverInterface::operator=(rhs); delete [] node_; delete [] howMany_; model_ = rhs.model_; int numberColumns = modelPtr_->numberColumns(); node_=CoinCopyOfArray(rhs.node_,numberColumns); howMany_=CoinCopyOfArray(rhs.howMany_,numberColumns); count_=rhs.count_; memory_=rhs.memory_; algorithm_=rhs.algorithm_; strategy_=rhs.strategy_; } return *this; } //------------------------------------------------------------------- // Real initializer //------------------------------------------------------------------- void CbcSolver2::initialize (CbcModel * model, const char * keep) { model_=model; int numberColumns = modelPtr_->numberColumns(); if (numberColumns) { node_ = new int[numberColumns]; howMany_ = new int[numberColumns]; for (int i=0;i #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcStrategy.hpp" #include "CbcBranchUser.hpp" #include "CbcCompareUser.hpp" #include "CbcCutGenerator.hpp" #include "CbcHeuristicLocal.hpp" #include "OsiClpSolverInterface.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglRedSplit.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding2.hpp" // Preprocessing #include "CglPreProcess.hpp" // Heuristics #include "CbcHeuristic.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program reads in an integer model from an mps file. It then sets up some Cgl cut generators and calls branch and cut. This is designed to show two things :- 1) Use of CbcStrategy to do preprocessing - this should be cleaner than old way 2) Looping round modifying solver and redoing branch and cut. This uses resetToReferenceCopy which resets stuff like the cutoff and any memory of previous branch and cut. ************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); /* Options are: preprocess to do preprocessing time in minutes if 2 parameters and numeric taken as time */ bool preProcess=false; double minutes=-1.0; int nGoodParam=0; for (int iParam=2; iParam=0.0) { nGoodParam+=2; iParam++; // skip time } } } } if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) { // If time is given then stop after that number of minutes minutes = atof(argv[2]); if (minutes>=0.0) nGoodParam=1; } if (nGoodParam!=argc-2&&argc>=2) { printf("Usage [preprocess] [time ] or \n"); exit(1); } //solver1.getModelPtr()->setLogLevel(0); solver1.messageHandler()->setLogLevel(0); solver1.initialSolve(); // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); CbcModel model(solver1); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(1); generator1.setMaxPassRoot(5); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); generator1.setMaxProbeRoot(1000); // How far to follow the consequences generator1.setMaxLook(50); generator1.setMaxLookRoot(500); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglRedSplit generator4; // try larger limit generator4.setLimit(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding2 mixedGen; CglFlowCover flowGen; // Add in generators // Experiment with -1 and -99 etc model.addCutGenerator(&generator1,-1,"Probing"); model.addCutGenerator(&generator2,-1,"Gomory"); model.addCutGenerator(&generator3,-1,"Knapsack"); // model.addCutGenerator(&generator4,-1,"RedSplit"); model.addCutGenerator(&generator5,-1,"Clique"); model.addCutGenerator(&flowGen,-1,"FlowCover"); model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver()); // go faster stripes if (osiclp) { // Turn this off if you get problems // Used to be automatically set osiclp->setSpecialOptions(128); if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) { //osiclp->setupForRepeatedUse(2,1); osiclp->setupForRepeatedUse(0,1); } } // Uncommenting this should switch off most CBC messages //model.messagesPointer()->setDetailMessages(10,5,5000); // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // And local search when new solution found CbcHeuristicLocal heuristic2(model); model.addHeuristic(&heuristic2); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); // Do initial solve to continuous model.initialSolve(); // Could tune more double objValue = model.solver()->getObjSense()*model.solver()->getObjValue(); double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4); double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4; printf("min drop %g (A %g)\n",minimumDrop,minimumDropA); model.setMinimumDrop(minimumDrop); if (model.getNumCols()<500) model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (model.getNumCols()<5000) model.setMaximumCutPassesAtRoot(100); // use minimum drop else model.setMaximumCutPassesAtRoot(20); model.setMaximumCutPasses(10); //model.setMaximumCutPasses(2); // Switch off strong branching if wanted // model.setNumberStrong(0); // Do more strong branching if small if (model.getNumCols()<5000) model.setNumberStrong(10); model.setNumberStrong(20); //model.setNumberStrong(5); model.setNumberBeforeTrust(5); //model.setSizeMiniTree(2); model.solver()->setIntParam(OsiMaxNumIterationHotStart,100); // If time is given then stop after that number of minutes if (minutes>=0.0) { std::cout<<"Stopping after "<setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } // Default strategy will leave cut generators as they exist already // so cutsOnlyAtRoot (1) ignored // numberStrong (2) is 5 (default) // numberBeforeTrust (3) is 5 (default is 0) // printLevel (4) defaults (0) CbcStrategyDefault strategy(true,5,5); // Set up pre-processing to find sos if wanted if (preProcess) strategy.setupPreProcessing(2); model.setStrategy(strategy); // Go round adding cuts to cutoff last solution // Stop after finding 20 best solutions for (int iPass=0;iPass<20;iPass++) { time1 = CoinCpuTime(); // Do complete search model.branchAndBound(); std::cout<getNumCols(); const double * solution = model.bestSolution(); //const double * lower = solver->getColLower(); //const double * upper = solver->getColUpper(); // Get names from solver1 (as OsiSolverInterface may lose) std::vector columnNames = *solver1.getModelPtr()->columnNames(); int iColumn; std::cout<1.0e-7&&solver->isInteger(iColumn)) std::cout<getColLower(); const double * originalUpper = refSolver->getColUpper(); #endif CoinPackedVector cut; double rhs = 1.0; for (iColumn=0;iColumnisInteger(iColumn)) { // only works for 0-1 variables assert (originalLower[iColumn]==0.0&& originalUpper[iColumn]==1.0); // double check integer assert (fabs(floor(value+0.5)-value)<1.0e-5); if (value>0.5) { // at 1.0 cut.insert(iColumn,-1.0); rhs -= 1.0; } else { // at 0.0 cut.insert(iColumn,1.0); } } } // now add cut refSolver->addRow(cut,rhs,COIN_DBL_MAX); model.resetToReferenceSolver(); } return 0; } Cbc-2.8.12/examples/longthin.cpp0000644000076600007660000001456412131315050015116 0ustar coincoin// $Id: longthin.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchUser.hpp" #include "CbcCompareUser.hpp" #include "CbcCutGenerator.hpp" #include "CbcHeuristicGreedy.hpp" #include "CbcSolver2.hpp" #include "CoinModel.hpp" // Cuts #include "CglProbing.hpp" #include "CoinTime.hpp" /************************************************************************ This main program reads in an integer model from an mps file. It expects it to be unit coefficients and unit rhs and long and thin Branching is simple binary branching on integer variables. */ int main (int argc, const char *argv[]) { // Define a Solver for long thin problems CbcSolver2 solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); solver1.initialSolve(); // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); OsiSolverInterface * solver2=&solver1; CbcModel model(*solver2); // Point to solver OsiSolverInterface * solver3 = model.solver(); CbcSolver2 * osiclp = dynamic_cast< CbcSolver2*> (solver3); assert (osiclp); osiclp->initialize(&model,NULL); osiclp->setAlgorithm(2); osiclp->setMemory(1000); // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); // How far to follow the consequences generator1.setMaxLook(50); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); generator1.setRowCuts(3); // Add in generators // Experiment with -1 and -99 etc model.addCutGenerator(&generator1,-99,"Probing"); // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // And Greedy heuristic CbcHeuristicGreedyCover heuristic2(model); // Use original upper and perturb more heuristic2.setAlgorithm(11); model.addHeuristic(&heuristic2); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); int iColumn; int numberColumns = solver3->getNumCols(); // do pseudo costs CbcObject ** objects = new CbcObject * [numberColumns]; const CoinPackedMatrix * matrix = solver3->getMatrixByCol(); // Column copy const int * columnLength = matrix->getVectorLengths(); const double * objective = model.getObjCoefficients(); int numberIntegers=0; for (iColumn=0;iColumnisInteger(iColumn)) { /* Branching up gets us much closer to an integer solution so we want to encourage up - so we will branch up if variable value > 0.333333. The expected cost of going up obviously depends on the cost of the variable so we just choose pseudo costs to reflect that. We could also decide to try and use the pseudo costs to make it more likely to branch on a variable with many coefficients. This leads to the computation below. */ double cost = objective[iColumn]*(1.0 + 0.2*((double) columnLength[iColumn])); CbcSimpleIntegerPseudoCost * newObject = new CbcSimpleIntegerPseudoCost(&model,iColumn, 2.0*cost,cost); newObject->setMethod(3); objects[numberIntegers++]= newObject; } } model.addObjects(numberIntegers,objects); for (iColumn=0;iColumnsetSpecialOptions(16); // We had better allow a lot model.solver()->setIntParam(OsiMaxNumIterationHotStart,10000); // So use strategy to keep rows osiclp->setStrategy(1); // Switch off most output if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } //model.setPrintFrequency(50); // Do complete search try { model.branchAndBound(); } catch (CoinError e) { e.print(); if (e.lineNumber()>=0) std::cout<<"This was from a CoinAssert"<getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7&&model.solver()->isInteger(iColumn)) std::cout< #include // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchUser.hpp" #include "CbcBranchActual.hpp" #include "CbcCompareUser.hpp" #include "CoinTime.hpp" #include "OsiClpSolverInterface.hpp" //############################################################################# /************************************************************************ This main program reads in an SOS model (rgn) from an mps file. It then solves it three ways :- a) As normal b) SOS 1 c) SOS 2 (so answer will be different) ************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; //solver1.messageHandler()->setLogLevel(0); CbcModel model(solver1); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Read in rgn.mps std::string mpsFileName; #if defined(MIPLIB3DIR) mpsFileName = MIPLIB3DIR "/rgn"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find miplib3 MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = model.solver()->readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } // Definition of node choice CbcCompareUser compare; compare.setWeight(0.0); model.setNodeComparison(compare); // Reduce output model.messageHandler()->setLogLevel(1); // Get branching messages model.messageHandler()->setLogLevel(3); // Do initial solve to continuous model.initialSolve(); // Save model CbcModel model2 = model; int numberColumns=model.getNumCols(); int numberIntegers = 0; int * integerVariable = new int[numberColumns]; int i; for ( i=0;igetColSolution(); std::cout<1.0e-7) std::cout<addCols(4,start,row,element,NULL,up,NULL); // Now use SOS1 int numberSets=4; int which[104]; double weights[104]; int starts[5]; // load int n=0; starts[0]=0; for (int iSet=0;iSet<4;iSet++) { for (int i=0;i<25;i++) { weights[n]=i+1.0; which[n]=iSet*25+i; n++; } // slack - make sure first branch is on slack weights[n]=1000.0; which[n]=180+iSet; n++; starts[iSet+1]=n; } for (i=0;isetContinuous(iColumn); } // save model in this state CbcModel modelSOS = model; CbcObject ** objects = new CbcObject * [numberSets]; for (i=0;igetColSolution(); std::cout<1.0e-7) std::cout<getColSolution(); std::cout<1.0e-7) std::cout< #include #include "CoinPragma.hpp" #include "CbcModel.hpp" #include "OsiClpSolverInterface.hpp" #include "CbcSolver.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program shows how to take advantage of the standalone cbc in your program, while still making major modifications. First it reads in an integer model from an mps file Then it initializes the integer model with cbc defaults Then it calls CbcMain1 passing all parameters apart from first but with callBack to modify stuff Finally it prints solution ************************************************************************/ /* Meaning of whereFrom: 1 after initial solve by dualsimplex etc 2 after preprocessing 3 just before branchAndBound (so user can override) 4 just after branchAndBound (before postprocessing) 5 after postprocessing */ /* Meaning of model status is as normal status -1 before branchAndBound 0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found (or check value of best solution) 1 stopped - on maxnodes, maxsols, maxtime 2 difficulties so run was abandoned (5 event user programmed event occurred) cbc secondary status of problem -1 unset (status_ will also be -1) 0 search completed with solution 1 linear relaxation not feasible (or worse than cutoff) 2 stopped on gap 3 stopped on nodes 4 stopped on time 5 stopped on user event 6 stopped on solutions 7 linear relaxation unbounded but initially check if status is 0 and secondary status is 1 -> infeasible or you can check solver status. */ /* Return non-zero to return quickly */ static int callBack(CbcModel * model, int whereFrom) { int returnCode=0; switch (whereFrom) { case 1: case 2: if (!model->status()&&model->secondaryStatus()) returnCode=1; break; case 3: { //CbcCompareUser compare; //model->setNodeComparison(compare); } break; case 4: // If not good enough could skip postprocessing break; case 5: break; default: abort(); } return returnCode; } #include "CbcEventHandler.hpp" /** This is so user can trap events and do useful stuff. CbcModel model_ is available as well as anything else you care to pass in */ class MyEventHandler3 : public CbcEventHandler { public: /**@name Overrides */ //@{ virtual CbcAction event(CbcEvent whichEvent); //@} /**@name Constructors, destructor etc*/ //@{ /** Default constructor. */ MyEventHandler3(); /// Constructor with pointer to model (redundant as setEventHandler does) MyEventHandler3(CbcModel * model); /** Destructor */ virtual ~MyEventHandler3(); /** The copy constructor. */ MyEventHandler3(const MyEventHandler3 & rhs); /// Assignment MyEventHandler3& operator=(const MyEventHandler3 & rhs); /// Clone virtual CbcEventHandler * clone() const ; //@} protected: // data goes here }; //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- MyEventHandler3::MyEventHandler3 () : CbcEventHandler() { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- MyEventHandler3::MyEventHandler3 (const MyEventHandler3 & rhs) : CbcEventHandler(rhs) { } // Constructor with pointer to model MyEventHandler3::MyEventHandler3(CbcModel * model) : CbcEventHandler(model) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- MyEventHandler3::~MyEventHandler3 () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- MyEventHandler3 & MyEventHandler3::operator=(const MyEventHandler3& rhs) { if (this != &rhs) { CbcEventHandler::operator=(rhs); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- CbcEventHandler * MyEventHandler3::clone() const { return new MyEventHandler3(*this); } CbcEventHandler::CbcAction MyEventHandler3::event(CbcEvent whichEvent) { // If in sub tree carry on if (!model_->parentModel()) { if (whichEvent==solution||whichEvent==heuristicSolution) { #ifdef STOP_EARLY return stop; // say finished #else // If preprocessing was done solution will be to processed model int numberColumns = model_->getNumCols(); const double * bestSolution = model_->bestSolution(); assert (bestSolution); printf("value of solution is %g\n",model_->getObjValue()); for (int i=0;i1.0e-8) printf("%d %g\n",i,bestSolution[i]); } return noAction; // carry on #endif } else { return noAction; // carry on } } else { return noAction; // carry on } } int main (int argc, const char *argv[]) { OsiClpSolverInterface solver1; //#define USE_OSI_NAMES #ifdef USE_OSI_NAMES // Say we are keeping names (a bit slower this way) solver1.setIntParam(OsiNameDiscipline,1); #endif // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } // Tell solver to return fast if presolve or initial solve infeasible solver1.getModelPtr()->setMoreSpecialOptions(3); /* Two ways of doing this depending on whether NEW_STYLE_SOLVER defined. So we need pointer to model. Old way could use modelA. rather than model-> */ // Messy code below copied from CbcSolver.cpp #ifdef CLP_FAST_CODE // force new style solver #ifndef NEW_STYLE_SOLVER #define NEW_STYLE_SOLVER 1 #endif #else // Not new style solver #ifndef NEW_STYLE_SOLVER #define NEW_STYLE_SOLVER 0 #endif #endif #if NEW_STYLE_SOLVER==0 // Pass to Cbc initialize defaults CbcModel modelA(solver1); CbcModel * model = &modelA; CbcMain0(modelA); // Event handler MyEventHandler3 eventHandler; model->passInEventHandler(&eventHandler); /* Now go into code for standalone solver Could copy arguments and add -quit at end to be safe but this will do */ if (argc>2) { CbcMain1(argc-1,argv+1,modelA,callBack); } else { const char * argv2[]={"driver4","-solve","-quit"}; CbcMain1(3,argv2,modelA,callBack); } #else CbcSolver control(solver1); // initialize control.fillValuesInSolver(); // Event handler MyEventHandler3 eventHandler; CbcModel * model = control.model(); model->passInEventHandler(&eventHandler); control.solve (argc-1, argv+1, 1); #endif // Solver was cloned so get current copy OsiSolverInterface * solver = model->solver(); // Print solution if finished (could get from model->bestSolution() as well if (model->bestSolution()) { const double * solution = solver->getColSolution(); int iColumn; int numberColumns = solver->getNumCols(); std::cout<1.0e-7&&solver->isInteger(iColumn)) std::cout<getColName(iColumn) <1.0e-7&&solver->isInteger(iColumn)) std::cout<columnName(iColumn) < #include // For Branch and bound //#include "CbcStrategy.hpp" #include "CoinPragma.hpp" #include "OsiCbcSolverInterface.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program reads in an integer model from an mps file. It then uses default strategy - just cuts at root node ************************************************************************/ int main (int argc, const char *argv[]) { // This would just do cuts at root // OsiCbcSolverInterface solver1; // This does cuts in tree and uses Clp CbcStrategyDefault strategy(false); OsiCbcSolverInterface solver1(NULL,&strategy); // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); // Do complete search solver1.branchAndBound(); std::cout<1.0e-7&&solver1.isInteger(iColumn)) std::cout< #include // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchUser.hpp" #include "CbcCompareUser.hpp" #include "CbcTreeLocal.hpp" #include "CbcCutGenerator.hpp" #include "CbcHeuristicLocal.hpp" #include "OsiClpSolverInterface.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglOddHole.hpp" #include "CglClique.hpp" // Heuristics #include "CbcHeuristic.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program reads in an integer model from an mps file. It then sets up some Cgl cut generators and calls branch and cut. Branching is simple binary branching on integer variables. Node selection is depth first until first solution is found and then based on objective and number of unsatisfied integer variables. In this example the functionality is the same as default but it is a user comparison function. Variable branching selection is on maximum minimum-of-up-down change after strong branching on 5 variables closest to 0.5. A simple rounding heuristic is used. ************************************************************************/ // See if option there and return integer value - or -123456 bool option(int argc, const char *argv[],const char * check, int & value) { value=-123456; for (int i=1;igetNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7&&model.solver()->isInteger(iColumn)) std::cout<0.5&&model.solver()->isInteger(i)) { if (comma) printf(","); if (newLine) printf("\n"); printf("%d ",i); comma=true; newLine=false; n++; if (n==10) { n=0; newLine=true; } } } printf("};\n"); n=0; comma=false; newLine=false; printf("\tdouble intSolnV[]={\n"); for ( i=0;i0.5&&model.solver()->isInteger(i)) { if (comma) printf(","); if (newLine) printf("\n"); int value = (int) (solution[i]+0.5); printf("%d. ",value); comma=true; newLine=false; n++; if (n==10) { n=0; newLine=true; } } } printf("};\n"); } return 0; } Cbc-2.8.12/examples/qmip.cpp0000644000076600007660000001510512131315050014232 0ustar coincoin// $Id: qmip.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchUser.hpp" #include "CbcCompareUser.hpp" #include "CbcCutGenerator.hpp" #include "CbcHeuristicLocal.hpp" #include "ClpQuadInterface.hpp" // Cuts - some may work but be very very careful #include "CglProbing.hpp" // Heuristics would need adapting #include "CbcHeuristic.hpp" // Time #include "CoinTime.hpp" /************************************************************************ This main program reads in a quadratic integer model from an mps file. It then sets up some Cgl cut generators and calls branch and cut. Branching is simple binary branching on integer variables. Node selection is depth first until first solution is found and then based on objective and number of unsatisfied integer variables. In this example the functionality is the same as default but it is a user comparison function. Variable branching selection is on maximum minimum-of-up-down change after strong branching on 5 variables closest to 0.5. A simple rounding heuristic could be used.but is switched off as needs work for quadratic This is NOT meant to be a serious MIQP code; it is to show how you can use ClpQuadInterface.hpp to solve a QP at each node. You could pick up data in that interface and use any QP solver (e.g. one that works) ************************************************************************/ int main (int argc, const char *argv[]) { // Define a Solver which inherits from OsiClpsolverInterface -> OsiSolverInterface ClpQuadInterface solver1; // Read in model using argv[1] if (argc <= 1) { printf("using %s \n", argv[0]); return 1; } // must use clp to get a quadratic model ClpSimplex * clp = solver1.getModelPtr(); int numMpsReadErrors = clp->readMps(argv[1]); // and assert that it is a clean model if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } // This clones solver CbcModel model(solver1); // But now model doesn't know about integers! const char * integerInfo = clp->integerInformation(); int numberColumns = clp->numberColumns(); // and point to solver OsiSolverInterface * solver2 = model.solver(); for (int iColumn=0;iColumnsetInteger(iColumn); } // Okay - now we have a good MIQP solver // Within branch and cut it is better (at present) to switch off all objectives ClpQuadInterface * osiclp = dynamic_cast< ClpQuadInterface*> (solver2); assert (osiclp); // Set fake objective so Cbc not confused osiclp->initialize(); solver2->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); // Add in generators // Only some generators work (and even then try without first) model.addCutGenerator(&generator1,1,"Probing"); // Allow rounding heuristic CbcRounding heuristic1(model); // do not add yet as don't know how to deal with quadratic objective //model.addHeuristic(&heuristic1); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; // breadth first //compare.setWeight(0.0); model.setNodeComparison(compare); // Do initial solve to continuous model.initialSolve(); // Could tune more model.setMinimumDrop(CoinMin(1.0, fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4)); model.setMaximumCutPassesAtRoot(0); model.setMaximumCutPasses(0); // Switch off strong branching if wanted //model.setNumberStrong(5); model.solver()->setIntParam(OsiMaxNumIterationHotStart,10000); // If time is given then stop after that number of minutes if (argc>2) { int minutes = atoi(argv[2]); std::cout<<"Stopping after "<=0); model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes); } // Switch off most output if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } model.setPrintFrequency(50); double time1 = CoinCpuTime(); // Do complete search model.branchAndBound(); std::cout<cutGeneratorName()<<" was tried " <numberTimesEntered()<<" times and created " <numberCutsInTotal()<<" cuts of which " <numberCutsActive()<<" were active after adding rounds of cuts" <getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7&&model.solver()->isInteger(iColumn)) std::cout< #include #include #include "CoinPragma.hpp" #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchUser.hpp" #include "CoinSort.hpp" // Default Constructor // Default Constructor CbcBranchUserDecision::CbcBranchUserDecision() :CbcBranchDecision() { } // Copy constructor CbcBranchUserDecision::CbcBranchUserDecision ( const CbcBranchUserDecision & rhs) :CbcBranchDecision(rhs) { } CbcBranchUserDecision::~CbcBranchUserDecision() { } // Clone CbcBranchDecision * CbcBranchUserDecision::clone() const { return new CbcBranchUserDecision(*this); } // Initialize i.e. before start of choosing at a node void CbcBranchUserDecision::initialize(CbcModel * model) { } /* Returns nonzero if branching on first object is "better" than on second (if second NULL first wins). User can play with decision object. This is only used after strong branching. The initial selection is done by infeasibility() for each CbcObject return code +1 for up branch preferred, -1 for down */ int CbcBranchUserDecision::betterBranch(CbcBranchingObject * thisOne, CbcBranchingObject * bestSoFar, double changeUp, int numberInfeasibilitiesUp, double changeDown, int numberInfeasibilitiesDown) { printf("Now obsolete CbcBranchUserDecision::betterBranch\n"); abort(); return 0; } /* Compare N branching objects. Return index of best and sets way of branching in chosen object. This routine is used only after strong branching. This is reccommended version as it can be more sophisticated */ int CbcBranchUserDecision::bestBranch (CbcBranchingObject ** objects, int numberObjects, int numberUnsatisfied, double * changeUp, int * numberInfeasibilitiesUp, double * changeDown, int * numberInfeasibilitiesDown, double objectiveValue) { int bestWay=0; int whichObject = -1; if (numberObjects) { CbcModel * model = objects[0]->model(); // at continuous //double continuousObjective = model->getContinuousObjective(); //int continuousInfeasibilities = model->getContinuousInfeasibilities(); // average cost to get rid of infeasibility //double averageCostPerInfeasibility = //(objectiveValue-continuousObjective)/ //(double) (abs(continuousInfeasibilities-numberUnsatisfied)+1); /* beforeSolution is : 0 - before any solution n - n heuristic solutions but no branched one -1 - branched solution found */ int numberSolutions = model->getSolutionCount(); double cutoff = model->getCutoff(); int method=0; int i; if (numberSolutions) { int numberHeuristic = model->getNumberHeuristicSolutions(); if (numberHeuristicnumberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesDown[i]bestCriterion) betterWay=1; } else { if (changeDown[i]>bestCriterion) betterWay=-1; } if (betterWay) { bestCriterion = CoinMin(changeUp[i],changeDown[i]); whichObject = i; bestWay = betterWay; } } break; case 2: for ( i = 0 ; i < numberObjects ; i++) { double change = CoinMin(changeUp[i],changeDown[i]); double sum = changeUp[i] + changeDown[i]; bool take=false; if (change>1.1*bestCriterion) take=true; else if (change>0.9*bestCriterion&&sum+change>bestCriterion+alternativeCriterion) take=true; if (take) { if (changeUp[i]<=changeDown[i]) { if (changeUp[i]>bestCriterion) bestWay=1; } else { if (changeDown[i]>bestCriterion) bestWay=-1; } bestCriterion = change; alternativeCriterion = sum; whichObject = i; } } break; case 3: for ( i = 0 ; i < numberObjects ; i++) { int numberNext = numberInfeasibilitiesUp[i]; if (numberNextnumberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesDown[i]=0) objects[whichObject]->way(bestWay); } return whichObject; } /** Default Constructor Equivalent to an unspecified binary variable. */ CbcSimpleIntegerFixed::CbcSimpleIntegerFixed () : CbcSimpleInteger() { } /** Useful constructor Loads actual upper & lower bounds for the specified variable. */ CbcSimpleIntegerFixed::CbcSimpleIntegerFixed (CbcModel * model, int iColumn, double breakEven) : CbcSimpleInteger(model,iColumn,breakEven) { } // Constructor from simple CbcSimpleIntegerFixed::CbcSimpleIntegerFixed (const CbcSimpleInteger & rhs) : CbcSimpleInteger(rhs) { } // Copy constructor CbcSimpleIntegerFixed::CbcSimpleIntegerFixed ( const CbcSimpleIntegerFixed & rhs) :CbcSimpleInteger(rhs) { } // Clone CbcObject * CbcSimpleIntegerFixed::clone() const { return new CbcSimpleIntegerFixed(*this); } // Assignment operator CbcSimpleIntegerFixed & CbcSimpleIntegerFixed::operator=( const CbcSimpleIntegerFixed& rhs) { if (this!=&rhs) { CbcSimpleInteger::operator=(rhs); } return *this; } // Destructor CbcSimpleIntegerFixed::~CbcSimpleIntegerFixed () { } // Infeasibility - large is 0.5 double CbcSimpleIntegerFixed::infeasibility(int & preferredWay) const { OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); /*printf("%d %g %g %g %g\n",columnNumber_,value,lower[columnNumber_], solution[columnNumber_],upper[columnNumber_]);*/ double nearest = floor(value+(1.0-breakEven_)); assert (breakEven_>0.0&&breakEven_<1.0); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); if (nearest>value) preferredWay=1; else preferredWay=-1; if (preferredWay_) preferredWay=preferredWay_; double weight = fabs(value-nearest); // normalize so weight is 0.5 at break even if (nearesttestSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); assert (upper[columnNumber_]>lower[columnNumber_]); if (!model_->hotstartSolution()) { double nearest = floor(value+0.5); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); if (fabs(value-nearest)hotstartSolution(); double targetValue = hotstartSolution[columnNumber_]; if (way>0) value = targetValue-0.1; else value = targetValue+0.1; } CbcBranchingObject * branch = new CbcIntegerBranchingObject(model_,columnNumber_,way, value); branch->setOriginalObject(this); return branch; } Cbc-2.8.12/examples/minimum.cpp0000644000076600007660000000266412131315050014745 0ustar coincoin// $Id: minimum.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CbcModel.hpp" // Using as solver #include "OsiClpSolverInterface.hpp" int main (int argc, const char *argv[]) { OsiClpSolverInterface solver1; // Read in example model // and assert that it is a clean model #if defined(SAMPLEDIR) int numMpsReadErrors = solver1.readMps(SAMPLEDIR "/p0033.mps",""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif // Pass data and solver to CbcModel CbcModel model(solver1); // uncomment to reduce printout //model.setLogLevel(1); //model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Do complete search model.branchAndBound(); /* Print solution. CbcModel clones solver so we need to get current copy */ int numberColumns = model.solver()->getNumCols(); const double * solution = model.solver()->getColSolution(); for (int iColumn=0;iColumn1.0e-7&&model.solver()->isInteger(iColumn)) printf("%d has value %g\n",iColumn,value); } return 0; } Cbc-2.8.12/examples/modify.cpp0000644000076600007660000000676312101340057014567 0ustar coincoin// $Id: modify.cpp 1854 2013-01-28 00:02:55Z stefan $ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* This example shows the creation of a model from arrays, solution and then changes to objective and adding a row */ #include "CbcModel.hpp" // Using as solver #include "OsiClpSolverInterface.hpp" int main (int argc, const char *argv[]) { // model is as exmip1.mps from Data/samples int numberRows=5; int numberColumns=8; int numberElements=14; // matrix data - column ordered CoinBigIndex start[9]={0,2,4,6,8,10,11,12,14}; int length[8]={2,2,2,2,2,1,1,2}; int rows[14]={0,4,0,1,1,2,0,3,0,4,2,3,0,4}; double elements[14]={3,5.6,1,2,1.1,1,-2,2.8,-1,1,1,-1.2,-1,1.9}; CoinPackedMatrix matrix(true,numberRows,numberColumns,numberElements,elements,rows,start,length); // rim data double objective[8]={1,0,0,0,2,0,0,-1}; double rowLower[5]={2.5,-COIN_DBL_MAX,4,1.8,3}; double rowUpper[5]={COIN_DBL_MAX,2.1,4,5,15}; double colLower[8]={2.5,0,0,0,0.5,0,0,0}; double colUpper[8]={COIN_DBL_MAX,4.1,1,1,4,COIN_DBL_MAX,COIN_DBL_MAX,4.3}; OsiClpSolverInterface solver1; // load problem solver1.loadProblem(matrix,colLower,colUpper,objective, rowLower,rowUpper); // mark integer solver1.setInteger(2); solver1.setInteger(3); // Solve solver1.initialSolve(); // Pass data and solver to CbcModel CbcModel model(solver1); // reduce printout model.setLogLevel(1); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Do complete search model.branchAndBound(); /* Print solution. CbcModel clones solver so we need to get current copy */ const double * solution = model.solver()->getColSolution(); int i; for (i=0;i1.0e-7&&model.solver()->isInteger(i)) printf("i %d has value %g\n",i,value); else if (fabs(value)>1.0e-7) printf("c %d has value %g\n",i,value); } // Change objective solver1.setObjCoeff(0,-100.0); // Now model has too much information e.g. best solution // simplest is to start again // Pass data and solver to CbcModel model = CbcModel(solver1); // reduce printout model.setLogLevel(1); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Do complete search model.branchAndBound(); solution = model.solver()->getColSolution(); for (i=0;i1.0e-7&&model.solver()->isInteger(i)) printf("i %d has value %g\n",i,value); else if (fabs(value)>1.0e-7) printf("c %d has value %g\n",i,value); } // Add constraint int column[8]={0,1,2,3,4,5,6,7}; double element2[8] ={1,1,1,1,1,1,1,1}; solver1.addRow(8,column,element2,7.8,COIN_DBL_MAX); // Now model has too much information e.g. best solution // simplest is to start again // Pass data and solver to CbcModel model = CbcModel(solver1); // reduce printout model.setLogLevel(1); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Do complete search model.branchAndBound(); solution = model.solver()->getColSolution(); for (i=0;i1.0e-7&&model.solver()->isInteger(i)) printf("i %d has value %g\n",i,value); else if (fabs(value)>1.0e-7) printf("c %d has value %g\n",i,value); } return 0; } Cbc-2.8.12/examples/sos.cpp0000644000076600007660000001476212131315050014100 0ustar coincoin// $Id: sos.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include "CoinPragma.hpp" // For Branch and bound #include "CbcModel.hpp" #include "CbcBranchActual.hpp" #include "OsiClpSolverInterface.hpp" // Time #include "CoinTime.hpp" /************************************************************************ This main program reads in an integer model from an mps file. It then tries to find SOS structure *************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(MIPLIB3DIR) mpsFileName = MIPLIB3DIR "/10teams"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find miplib3 MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } int iRow, iColumn; int numberColumns = solver1.getNumCols(); int numberRows = solver1.getNumRows(); // get row copy const CoinPackedMatrix * matrix = solver1.getMatrixByRow(); const double * element = matrix->getElements(); const int * column = matrix->getIndices(); const CoinBigIndex * rowStart = matrix->getVectorStarts(); const int * rowLength = matrix->getVectorLengths(); const double * rowLower = solver1.getRowLower(); const double * rowUpper = solver1.getRowUpper(); const double * columnLower = solver1.getColLower(); // Look for possible SOS int numberSOS=0; int * mark = new int[numberColumns]; CoinFillN(mark,numberColumns,-1); for (iRow=0;iRow=0||columnLower[iColumn]) { goodRow=false; break; } } if (goodRow) { // mark all for (int j=rowStart[iRow];j2) { int minutes = atoi(argv[2]); std::cout<<"Stopping after "<=0); model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes); } // Switch off most output model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } model.messageHandler()->setLogLevel(1); double time1 = CoinCpuTime(); // Do complete search model.branchAndBound(); std::cout<getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7&&model.solver()->isInteger(iColumn)) std::cout<1.0e-7) std::cout< #include #include "CoinPragma.hpp" // For Branch and bound #include "CbcModel.hpp" #include "CbcBranchActual.hpp" #include "OsiClpSolverInterface.hpp" // Time #include "CoinTime.hpp" /************************************************************************ This main program reads in an integer model from an mps file. It then tries to find SOS structure and solves using N-way variables *************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(MIPLIB3DIR) mpsFileName = MIPLIB3DIR "/10teams"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find miplib3 MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } int iRow, iColumn; int numberColumns = solver1.getNumCols(); int numberRows = solver1.getNumRows(); // get row copy const CoinPackedMatrix * matrix = solver1.getMatrixByRow(); const double * element = matrix->getElements(); const int * column = matrix->getIndices(); const CoinBigIndex * rowStart = matrix->getVectorStarts(); const int * rowLength = matrix->getVectorLengths(); const double * rowLower = solver1.getRowLower(); const double * rowUpper = solver1.getRowUpper(); const double * columnLower = solver1.getColLower(); // Look for possible SOS int numberSOS=0; int * mark = new int[numberColumns]; CoinFillN(mark,numberColumns,-1); for (iRow=0;iRow=0||columnLower[iColumn]) { goodRow=false; break; } } if (goodRow) { // mark all for (int j=rowStart[iRow];j2) { int minutes = atoi(argv[2]); std::cout<<"Stopping after "<=0); model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes); } // Switch off most output model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); //model.solver()->messageHandler()->setLogLevel(1); } //model.messageHandler()->setLogLevel(1); double time1 = CoinCpuTime(); // Do complete search model.branchAndBound(); std::cout<getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7&&model.solver()->isInteger(iColumn)) std::cout< #include // For Branch and bound #include "CoinPragma.hpp" #include "CbcModel.hpp" #include "CbcStrategy.hpp" #include "OsiClpSolverInterface.hpp" // Preprocessing #include "CglPreProcess.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program reads in an integer model from an mps file. It then uses default strategy - just cuts at root node ************************************************************************/ int main (int argc, const char *argv[]) { OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); /* Options are: preprocess to do preprocessing time in minutes if 2 parameters and numeric taken as time */ bool preProcess=false; double minutes=-1.0; int nGoodParam=0; for (int iParam=2; iParam=0.0) { nGoodParam+=2; iParam++; // skip time } } } } if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) { // If time is given then stop after that number of minutes minutes = atof(argv[2]); if (minutes>=0.0) nGoodParam=1; } if (nGoodParam!=argc-2&&argc>=2) { printf("Usage [preprocess] [time ] or \n"); exit(1); } // See if we want preprocessing OsiSolverInterface * solver2=&solver1; CglPreProcess process; if (preProcess) { /* Do not try and produce equality cliques and do up to 5 passes */ solver2 = process.preProcess(solver1,false,5); if (!solver2) { printf("Pre-processing says infeasible\n"); exit(2); } solver2->resolve(); } CbcModel model(*solver2); // If time is given then stop after that number of minutes if (minutes>=0.0) { std::cout<<"Stopping after "<getNumCols(); const double * solution = solver->getColSolution(); int iColumn; std::cout<1.0e-7&&solver->isInteger(iColumn)) std::cout< #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CoinModel.hpp" // For Linked Ordered Sets #include "CbcBranchLink.hpp" #include "OsiClpSolverInterface.hpp" #include "CoinTime.hpp" /************************************************************************ This shows how we can define a new branching method to solve problems with nonlinearities and discontinuities. We are going to solve the problem minimize abs ( 1.0/6.931 - x1*x4/x2*x3) where the variables are integral between 12 and 60. See E.Sangren, "Nonlinear Integer and Discrete Programming in Mechanical Design Optimization". Trans. ASME, J. Mech Design 112, 223-229, 1990 One could try to use logarithms to make the problem separable but that leads to a weak formulation. Instaed we are going to use linked special ordered sets. The generalization with column generation can be even more powerful but is not yet in CBC. The idea is simple: A linear variable is a convex combination of its lower bound and upper bound! If x must lie between 12 and 60 then we can substitute for x as x == 12.0*xl + 60.0*xu where xl + xu == 1.0. At first this looks cumbersome but if we have xl12, xl13, ... xl60 and corresponding xu and yl and yu then we can write: x == sum 12.0*xl[i] + 60.0* xu[i] where sum xl[i] + xu[i] == 1.0 and x*y == 12.0*12.0*xl12 + 12.0*60.0*xu12 + 13.0*12.0*xl13 + 13.0*60.0*x13 .... + 12.0*60*.0xl60 + 60.0*60.0*xu60 And now x*y is correct if x is integer and xl[i], xu[i] are only nonzero for one i. Note that this would have worked just as easily for y**2 or any clean function of y. So this is just like a special ordered set of type 1 but on two sets simultaneously. The idea is even more powerful if we want other functions on y as we can branch on all sets simultaneously. Also note that convexity requirements for any non-linear functions are not needed. So we need a new branching method to do that - see CbcBranchLink.?pp We are going to need a CbcBranchLink method to see whether we are satisfied etc and also to create another branching object which knows how to fix variables. We might be able to use an existing method for the latter but let us create two methods CbcLink and CbcLinkBranchingObject. For CbcLink we will need the following methods: Constructot/Destructor infeasibility - returns 0.0 if feasible otherwise some measure of infeasibility feasibleRegion - sets bounds to contain current solution createBranch - creates a CbcLinkBranchingObject For CbcLinkBranchingObject we need: Constructor/Destructor branch - does actual fixing print - optional for debug purposes. The easiest way to do this is to cut and paste from CbcBranchActual to get current SOS stuff and then modify that. ************************************************************************/ int main (int argc, const char *argv[]) { OsiClpSolverInterface solver1; /* We are going to treat x1 and x2 as integer and x3 and x4 as a set. We define two new variables y1 == x1*x4 and y2 == x2*x3. We define a variable z == x1*x4/x2*x3 so y2*z == y1 (we will treat y2 as a set) Then we have objective - minimize w1 + w2 where w1 - w2 = 1.0/6.931 - z The model would be a lot smaller if we had column generation. */ // Create model CoinModel build; // Keep values of all variables for reporting purposes even if not necessary /* z is first, then x then y1,y2 then w1,w2 then y1 stuff, y2 stuff and finally y2 -> z stuff. For rows same but 2 per y then rest of z stuff */ int loInt=12; int hiInt=60; int ybaseA=5, ybaseB=9, ylen=hiInt-loInt+1; int base = ybaseB+2*2*ylen; int yylen = hiInt*hiInt-loInt*loInt+1; int zbase = 10; int i; // Do single variables double value[] ={1.0,1.0}; int row[2]; /* z - obviously we can't choose bounds too tight but we need bounds so choose 20% off as obviously feasible. fastest way to solve would be too run for a few seconds to get tighter bounds then re-formulate and solve. */ double loose=0.2; double loZ = (1-loose)*(1.0/6.931), hiZ = (1+loose)*(1.0/6.931); row[0]=0; // for reporting row[1]=zbase+1; // for real use build.addColumn(2,row,value,loZ, hiZ, 0.0); // x for (i=0;i<4;i++) { row[0]=i+1; build.addColumn(1,row,value,loInt, hiInt,0.0); // we don't need to say x2, x3 integer but won't hurt build.setInteger(i+1); } // y for (i=0;i<2;i++) { // y from x*x, and convexity row[0]=ybaseA+2*i; if (i==0) row[1]=zbase+2; // yb*z == ya else row[1]=zbase-1; // to feed into z build.addColumn(2,row,value,loInt*loInt, hiInt*hiInt,0.0); // we don't need to say integer but won't hurt build.setInteger(ybaseA+i); } // skip z convexity put w in final equation row[0]=zbase+1; build.addColumn(1,row,value,0.0,1.0,1.0); value[0]=-1.0; build.addColumn(1,row,value,0.0,1.0,1.0); // Do columns so we know where each is for (i=ybaseB;isetHintParam(OsiDoReducePrint,true,OsiHintTry); model.solver()->setHintParam(OsiDoScale,false,OsiHintTry); CbcObject ** objects = new CbcObject * [3]; /* Format is number in sets, number in each link, first variable in matrix) and then a weight for each in set to say where to branch. In this case use NULL to say 0,1,2 ... Finally a set number as ID. */ objects[0]=new CbcLink(&model,ylen,2,ybaseB,NULL,0); objects[0]->setPriority(10); objects[1]=new CbcLink(&model,ylen,2,ybaseB+2*ylen,NULL,0); objects[1]->setPriority(20); objects[2]=new CbcLink(&model,yylen,2,base,NULL,0); objects[2]->setPriority(1); model.addObjects(3,objects); for (i=0;i<3;i++) delete objects[i]; delete [] objects; model.messageHandler()->setLogLevel(1); // Do complete search model.setDblParam(CbcModel::CbcMaximumSeconds,1200.0); model.setDblParam(CbcModel::CbcCutoffIncrement,1.0e-8); model.branchAndBound(); std::cout<<"took "<getNumCols(); double x1=solution[1]; double x2=solution[2]; double x3=solution[3]; double x4=solution[4]; printf("Optimal solution %g %g %g %g\n",x1,x2,x3,x4); for (int iColumn=0;iColumn1.0e-7) std::cout< #include #include "CoinPragma.hpp" #include "CbcModel.hpp" #include "OsiClpSolverInterface.hpp" #include "CbcSolver.hpp" #include "CoinTime.hpp" //############################################################################# // AS parallel.cpp but just one char * and dummy callBack /************************************************************************ This main program shows how to take advantage of the standalone cbc in your program, while still making major modifications. This is like driver4 but executes in parallel First it reads in a model from an mps file Then it initializes three integer models with cbc defaults Then it calls CbcMain0/1 using threads passing parameters Finally it prints solution (just for first model) All models have same parameters unless "-switch" is found so -- miplib/p0033 -solve -switch -heuristic off -solve would solve first model with heuristics and subsequent ones without This could be used to try different ideas OR on different models NOTE - The minimum has been done to make thread safe so no interrupts -quit is added to make sure just reads from argv */ /*************************************************************************/ #define USE_PTHREAD #ifdef USE_PTHREAD #include #endif // For threads typedef struct { CbcModel * model; char * args; } threadStuff; static void * doThread(void * voidInfo) { threadStuff * stuff = reinterpret_cast(voidInfo); CbcModel * model = stuff->model; callCbc(stuff->args,*model); return NULL; } int main (int argc, const char *argv[]) { // Number of models to do at once int numberModels=3; // Stuff for each model CbcModel * allModels = new CbcModel[numberModels]; OsiClpSolverInterface * allSolvers = new OsiClpSolverInterface[numberModels]; threadStuff * allData = new threadStuff[numberModels]; // First populate first model /* in a real application models would be different */ OsiClpSolverInterface & solver1 = allSolvers[0]; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } // Tell solver to return fast if presolve or initial solve infeasible solver1.getModelPtr()->setMoreSpecialOptions(3); // create models for (int iModel=1;iModel0) lastArgc=thisArgc; else thisArgc=lastArgc; // allow extra for -quit char * args = new char[256]; allData[iModel].args=args; for (int iArgc=lastArgPosition;iArgcsolver(); // Print solution if finished (could get from model->bestSolution() as well if (model->bestSolution()) { const double * solution = solver->getColSolution(); int iColumn; int numberColumns = solver->getNumCols(); std::cout<1.0e-7&&solver->isInteger(iColumn)) std::cout<getColName(iColumn) <1.0e-7&&solver->isInteger(iColumn)) std::cout<columnName(iColumn) < #include #include "CoinPragma.hpp" // For Branch and bound #include "CbcModel.hpp" #include "CbcBranchLotsize.hpp" #include "OsiClpSolverInterface.hpp" // Time #include "CoinTime.hpp" /************************************************************************ This main program reads in an integer model from an mps file. It then replaces all 0-1 variables by lotsizing variables which can take values 0.0,0.45-0.55 or 1.0 *************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(MIPLIB3DIR) mpsFileName = MIPLIB3DIR "/10teams"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find miplib3 MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } int iColumn; int numberColumns = solver1.getNumCols(); int numberLot=0; char * mark = new char[numberColumns]; // take off integers but find where they are for (iColumn=0;iColumn2) { int minutes = atoi(argv[2]); std::cout<<"Stopping after "<=0); model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes); } // Switch off most output model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } model.messageHandler()->setLogLevel(1); double time1 = CoinCpuTime(); // Do complete search model.branchAndBound(); std::cout<getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7) std::cout< #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchUser.hpp" #include "CbcCompareUser.hpp" #include "CbcCutGenerator.hpp" #include "CbcStrategy.hpp" #include "CbcHeuristicLocal.hpp" #include "OsiClpSolverInterface.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglRedSplit.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding2.hpp" // Preprocessing #include "CglPreProcess.hpp" // Heuristics #include "CbcHeuristic.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program reads in an integer model from an mps file. It then sets up some Cgl cut generators and calls branch and cut. Branching is simple binary branching on integer variables. Node selection is depth first until first solution is found and then based on objective and number of unsatisfied integer variables. In this example the functionality is the same as default but it is a user comparison function. Variable branching selection is on maximum minimum-of-up-down change after strong branching on 5 variables closest to 0.5. A simple rounding heuristic is used. Preprocessing may be selected in two ways - the second is preferred now ************************************************************************/ #define PREPROCESS 2 int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string dirsep(1,CoinFindDirSeparator()); std::string mpsFileName; # if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR ; mpsFileName += dirsep+"p0033.mps"; # else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } # endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); /* Options are: preprocess to do preprocessing time in minutes if 2 parameters and numeric taken as time */ bool preProcess=false; double minutes=-1.0; int nGoodParam=0; for (int iParam=2; iParam=0.0) { nGoodParam+=2; iParam++; // skip time } } } } if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) { // If time is given then stop after that number of minutes minutes = atof(argv[2]); if (minutes>=0.0) nGoodParam=1; } if (nGoodParam!=argc-2&&argc>=2) { printf("Usage [preprocess] [time ] or \n"); exit(1); } solver1.initialSolve(); // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); // See if we want preprocessing OsiSolverInterface * solver2=&solver1; #if PREPROCESS==1 CglPreProcess process; if (preProcess) { /* Do not try and produce equality cliques and do up to 5 passes */ solver2 = process.preProcess(solver1,false,5); if (!solver2) { printf("Pre-processing says infeasible\n"); exit(2); } solver2->resolve(); } #endif CbcModel model(*solver2); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(1); generator1.setMaxPassRoot(5); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); generator1.setMaxProbeRoot(1000); // How far to follow the consequences generator1.setMaxLook(50); generator1.setMaxLookRoot(500); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglRedSplit generator4; // try larger limit generator4.setLimit(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding2 mixedGen; CglFlowCover flowGen; // Add in generators // Experiment with -1 and -99 etc model.addCutGenerator(&generator1,-1,"Probing"); model.addCutGenerator(&generator2,-1,"Gomory"); model.addCutGenerator(&generator3,-1,"Knapsack"); // model.addCutGenerator(&generator4,-1,"RedSplit"); model.addCutGenerator(&generator5,-1,"Clique"); model.addCutGenerator(&flowGen,-1,"FlowCover"); model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); // Say we want timings int numberGenerators = model.numberCutGenerators(); int iGenerator; for (iGenerator=0;iGeneratorsetTiming(true); } OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver()); // go faster stripes if (osiclp) { // Turn this off if you get problems // Used to be automatically set osiclp->setSpecialOptions(128); if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) { //osiclp->setupForRepeatedUse(2,0); osiclp->setupForRepeatedUse(0,0); } } // Uncommenting this should switch off all CBC messages // model.messagesPointer()->setDetailMessages(10,10000,NULL); // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // And local search when new solution found CbcHeuristicLocal heuristic2(model); model.addHeuristic(&heuristic2); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); // Do initial solve to continuous model.initialSolve(); // Could tune more double objValue = model.solver()->getObjSense()*model.solver()->getObjValue(); double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4); double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4; printf("min drop %g (A %g)\n",minimumDrop,minimumDropA); model.setMinimumDrop(minimumDrop); if (model.getNumCols()<500) model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (model.getNumCols()<5000) model.setMaximumCutPassesAtRoot(100); // use minimum drop else model.setMaximumCutPassesAtRoot(20); model.setMaximumCutPasses(10); //model.setMaximumCutPasses(2); // Switch off strong branching if wanted // model.setNumberStrong(0); // Do more strong branching if small if (model.getNumCols()<5000) model.setNumberStrong(10); model.setNumberStrong(20); //model.setNumberStrong(5); model.setNumberBeforeTrust(5); model.solver()->setIntParam(OsiMaxNumIterationHotStart,100); // If time is given then stop after that number of minutes if (minutes>=0.0) { std::cout<<"Stopping after "<setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } //model.messageHandler()->setLogLevel(2); //model.solver()->messageHandler()->setLogLevel(2); //model.setPrintFrequency(50); //#define DEBUG_CUTS #ifdef DEBUG_CUTS // Set up debugger by name (only if no preprocesing) if (!preProcess) { std::string problemName ; model.solver()->getStrParam(OsiProbName,problemName) ; model.solver()->activateRowCutDebugger(problemName.c_str()) ; } #endif #if PREPROCESS==2 // Default strategy will leave cut generators as they exist already // so cutsOnlyAtRoot (1) ignored // numberStrong (2) is 5 (default) // numberBeforeTrust (3) is 5 (default is 0) // printLevel (4) defaults (0) CbcStrategyDefault strategy(true,5,5); // Set up pre-processing to find sos if wanted if (preProcess) strategy.setupPreProcessing(2); model.setStrategy(strategy); #endif // Do complete search model.branchAndBound(); std::cout<cutGeneratorName()<<" was tried " <numberTimesEntered()<<" times and created " <numberCutsInTotal()<<" cuts of which " <numberCutsActive()<<" were active after adding rounds of cuts"; if (generator->timing()) std::cout<<" ( "<timeInCutGenerator()<<" seconds)"<getNumCols(); const double * solution = solver->getColSolution(); // Get names from solver1 (as OsiSolverInterface may lose) std::vector columnNames = *solver1.getModelPtr()->columnNames(); int iColumn; std::cout<1.0e-7&&solver->isInteger(iColumn)) std::cout< #include "CbcConfig.h" #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "OsiClpSolverInterface.hpp" #include "ClpPresolve.hpp" #include "CbcCompareUser.hpp" #include "CglProbing.hpp" //############################################################################# #ifdef NDEBUG #undef NDEBUG #endif // Time #include #if !defined(_MSC_VER) #include #include #include #endif static double cpuTime() { double cpu_temp; #if defined(_MSC_VER) unsigned int ticksnow; /* clock_t is same as int */ ticksnow = (unsigned int)clock(); cpu_temp = (double)((double)ticksnow/CLOCKS_PER_SEC); #else struct rusage usage; getrusage(RUSAGE_SELF,&usage); cpu_temp = (double)usage.ru_utime.tv_sec; cpu_temp += 1.0e-6*((double) usage.ru_utime.tv_usec); #endif return cpu_temp; } /************************************************************************ This main program reads in an integer model from an mps file. It then sets up some Cgl cut generators and calls branch and cut. Branching is simple binary branching on integer variables. Node selection is depth first until first solution is found and then based on objective and number of unsatisfied integer variables. Variable branching selection is on maximum minimum-of-up-down change after strong branching on 5 variables closest to 0.5. A simple rounding heuristic is used. Any cut generators based on Cgl can be added in same way You may also wish to look at CbcModel.hpp ************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver ClpSimplex simplex; double time0 = cpuTime(); double time1 = time0; double time2; // Read in model using argv[1] // and assert that it is a clean model if (argc <= 1) { printf("using %s \n", argv[0]); return 1; } int numMpsReadErrors = simplex.readMps(argv[1],""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } time2 = cpuTime(); std::cout<<"Input took "<setLogLevel(0); CbcModel model(solver1); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); // Maybe probing due to very large coefficients CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); generator1.setMaxProbe(100); generator1.setMaxLook(50); generator1.setRowCuts(3); // Add in generators // model.addCutGenerator(&generator1,-1,"Probing"); // Switch off strong branching if wanted model.setNumberStrong(0); model.solver()->setIntParam(OsiMaxNumIterationHotStart,100); //model.solver()->setHintParam(OsiDoScale,false,OsiHintTry); // Switch off most output if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } // Do complete search model.branchAndBound(); time2 = cpuTime(); std::cout<<"Search took "< (model.solver()); assert (clpSolver); ClpSimplex * clp = clpSolver->getModelPtr(); *simplex2 = *clp; pinfo.postsolve(true); time1 = time2; // Fix all integers const int * original = pinfo.originalColumns(); double * lower2 = simplex2->columnLower(); double * upper2 = simplex2->columnUpper(); const char * info2 = simplex2->integerInformation(); double * lower = simplex.columnLower(); double * upper = simplex.columnUpper(); int i; for (i=0;inumberColumns();i++) { if (info2[i]) { int iSeq = original[i]; upper[iSeq]=upper2[i]; lower[iSeq]=lower2[i]; } } simplex.primal(); time2 = cpuTime(); std::cout<<"Cleanup took "< #include #include #include /* prototypes */ void printSolution(Cbc_Model *cbc_model); Cbc_Model * getDefaultModel(int argc, const char *argv[]); /* Call back function - just says whenever it gets Clp0005 or Coin0002 */ /* TODO: It seems that Cbc gives callbacks but not Coin */ static void callBack(Cbc_Model * model, int messageNumber, int nDouble, const double * vDouble, int nInt, const int * vInt, int nString, char ** vString) { const char prefix[] = "cbc_driverC_sos.cpp::callBack(): "; const int VERBOSE = 4; if (VERBOSE>0) printf("%s begin\n",prefix); if (VERBOSE>1) printf("%s messageNumber %i\n",prefix,messageNumber); if (messageNumber==1000002) { /* Coin0002 */ assert (nString==1&&nInt==3); printf("Name of problem is %s\n",vString[0]); printf("row %d col %d el %d\n",vInt[0],vInt[1],vInt[2]); } else if (messageNumber==5) { /* Clp0005 */ int i; assert (nInt==4&&nDouble==3); /* they may not all print */ for (i=0;i<3;i++) printf("%d %g\n",vInt[i],vDouble[i]); } if (VERBOSE>0) printf("%s return\n",prefix); } /** * Get default model */ Cbc_Model * getDefaultModel(int argc, const char *argv[]) { const char prefix[] = "cbc_driverC_sos.cpp::getDefaultModel(): "; const int VERBOSE = 4; Cbc_Model *model; int status; if (VERBOSE>0) printf("%s begin\n",prefix); model = Cbc_newModel(); /** Amount of print out: 0 - none 1 - just final 2 - just factorizations 3 - as 2 plus a bit more 4 - verbose above that 8,16,32 etc just for selective debug */ Cbc_setLogLevel(model, 1); if (VERBOSE>0) printf("%s Log Level %i\n", prefix, Cbc_logLevel(model)); /* register callback */ Cbc_registerCallBack(model,callBack); /* Keep names when reading an mps file */ if (argc < 2) { #if defined(SAMPLEDIR) /* SAMPLEDIR should be something like "path/to/mps/directory", including the quotes and excluding the final directory separator. Don't forget to properly escape '\' when using native Windows path syntax. */ status=Cbc_readMps(model, SAMPLEDIR "/p0033.mps") ; #else fprintf(stderr, "Please specify the full path to an MPS file on the command line\n"); exit(1); #endif } else status=Cbc_readMps(model,argv[1]); if (status) { fprintf(stderr,"Bad readMps %s\n",argv[1]); fprintf(stdout,"Bad readMps %s\n",argv[1]); exit(1); } Cbc_setOptimizationDirection(model, 1); if (1) Cbc_setIntegerTolerance(model, 1.0e-5); /* Solve initial LP relaxation */ Cbc_initialSolve(model); if (VERBOSE>0) printf("%s return\n",prefix); return model; } /* getDefaultModel() */ void printSolution(Cbc_Model *cbc_model) { /* Now to print out solution. The methods used return modifiable arrays while the alternative names return const pointers - which is of course much more virtuous. This version just does non-zero column and row values. */ /* If we have not kept names (parameter to readMps) this will be 0 assert(Cbc_lengthNames(cbc_model)); */ { int name_length = 256; char model_name[256]; Cbc_problemName(cbc_model, name_length, model_name); printf("Model Name = '%s'\n", model_name); } printf("Iteration Count = %i\n",Cbc_getIterationCount(cbc_model)); printf("Iteration Limit = %i\n",Cbc_maximumIterations(cbc_model)); printf("Is Abandoned = %i\n",Cbc_isAbandoned(cbc_model)); printf("Is Proven Optimal = %i\n",Cbc_isProvenOptimal(cbc_model)); printf("Is Proven Infeasible = %i\n",Cbc_isProvenPrimalInfeasible(cbc_model)); printf("Is Proven Dual Infeasible = %i\n",Cbc_isProvenDualInfeasible(cbc_model)); printf("Is Proven Unbounded = %i\n",(Cbc_infeasibilityRay(cbc_model) == NULL) ? 0 : 1); printf("Is Primal Objective Limit Reached = %i\n",Cbc_isPrimalObjectiveLimitReached(cbc_model)); printf("Is Dual Objective Limit Reached = %i\n",Cbc_isDualObjectiveLimitReached(cbc_model)); printf("Is Iteration Limit Reached = %i\n",Cbc_isIterationLimitReached(cbc_model)); printf("Objective Sense = %g\n",Cbc_getObjSense(cbc_model)); /* (1 - minimize, -1 - maximize, 0 - ignore) */ printf("Primal Feasible = %i\n",Cbc_primalFeasible(cbc_model)); printf("Dual Feasible = %i\n",Cbc_dualFeasible(cbc_model)); printf("Dual Bound = %g\n",Cbc_dualBound(cbc_model)); printf("Infeasibility Cost = %g\n",Cbc_infeasibilityCost(cbc_model)); printf("Sum Dual Infeasibilities = %g\n",Cbc_sumDualInfeasibilities(cbc_model)); printf("Number Dual Infeasibilities = %i\n",Cbc_numberDualInfeasibilities(cbc_model)); printf("Sum Primal Infeasibilities = %g\n",Cbc_sumPrimalInfeasibilities(cbc_model)); printf("Number Primal Infeasibilities = %i\n",Cbc_numberPrimalInfeasibilities(cbc_model)); printf("Objective Value = %g\n",Cbc_objectiveValue(cbc_model)); printf("Optimization Direction = %g\n", Cbc_optimizationDirection(cbc_model)); printf(" (1 - minimize, -1 - maximize, 0 - ignore)\n"); printf("--------------------------------------\n"); /* Rows */ { int numberRows = Cbc_numberRows(cbc_model); int iRow; const double * rowPrimal = Cbc_getRowActivity(cbc_model); const double * rowDual = Cbc_getRowPrice(cbc_model); const double * rowLower = Cbc_getRowLower(cbc_model); const double * rowUpper = Cbc_getRowUpper(cbc_model); assert(rowPrimal != NULL); assert(rowDual != NULL); assert(rowLower != NULL); assert(rowUpper != NULL); printf(" Primal Dual Lower Upper\n"); for (iRow=0;iRow1.0e-8||value<-1.0e-8) { char name[20]; sprintf(name," Row%-4i",iRow); printf("%6d %8s",iRow,name); printf(" %13g",rowPrimal[iRow]); printf(" %13g",rowDual[iRow]); printf(" %13g",rowLower[iRow]); printf(" %13g",rowUpper[iRow]); printf("\n"); } } } printf("--------------------------------------\n"); /* Columns */ { int numberColumns = Cbc_numberColumns(cbc_model); int iColumn; const double * columnPrimal = Cbc_getColSolution(cbc_model); const double * columnDual = Cbc_getReducedCost(cbc_model); const double * columnLower = Cbc_getColLower(cbc_model); const double * columnUpper = Cbc_getColUpper(cbc_model); const double * columnObjective = Cbc_getObjCoefficients(cbc_model); assert(columnPrimal != NULL); assert(columnDual != NULL); assert(columnLower != NULL); assert(columnUpper != NULL); assert(columnObjective != NULL); printf(" Primal Dual Lower Upper Cost\n"); for (iColumn=0;iColumn1.0e-8||value<-1.0e-8) { char name[20]; sprintf(name," Col%-4i",iColumn); /* Cbc_columnName(cbc_model,iColumn,name); */ printf("%6d %8s",iColumn,name); printf(" %13g",columnPrimal[iColumn]); printf(" %13g",columnDual[iColumn]); printf(" %13g",columnLower[iColumn]); printf(" %13g",columnUpper[iColumn]); printf(" %13g",columnObjective[iColumn]); printf("\n"); } } } printf("--------------------------------------\n"); } /* printSolution() */ int main (int argc, const char *argv[]) { const char prefix[] = "cbc_driverC_sos.cpp:main(): "; const int VERBOSE = 4; Cbc_Model * model, * model2; double time1; char modelName[80]; int numberIntegers; int * integerVariable; if (VERBOSE>0) printf("%s begin\n",prefix); if (VERBOSE>0) printf("%s Version %g\n",prefix,Cbc_getVersion()); /* set model using the local routine for reading an MPS file */ model = getDefaultModel(argc, argv); model2 = NULL; /* used to keep model around */ /* This clause ought to set the initial basis, but does not yet work. */ { int i; int row_length = Cbc_getNumRows(model); int col_length = Cbc_getNumCols(model); int rim_length = row_length + col_length; int elem_length = Cbc_getNumElements(model); int * cbc_rowStatus = NULL; int * cbc_columnStatus = NULL; if (0) { fprintf(stdout,"%s row_length = %i\n", prefix, row_length); fprintf(stdout,"%s col_length = %i\n", prefix, col_length); fprintf(stdout,"%s rim_length = %i\n", prefix, rim_length); fprintf(stdout,"%s elem_length = %i\n", prefix, elem_length); fflush(stdout); } /* print solution status variables */ if (0) { if (cbc_rowStatus) { for (i = 0; i < row_length; i++) { printf("%s cbc_rowStatus[%i] = %i\n", prefix, i, cbc_rowStatus[i]); fflush(stdout); } } else { fprintf(stdout,"%s cbc_rowStatus = %p\n", prefix, (void*)cbc_rowStatus); fflush(stdout); } if (cbc_columnStatus) { for (i = 0; i < row_length; i++) { fprintf(stdout,"%s cbc_rowStatus[%i] = %i\n", prefix, i, cbc_columnStatus[i]); fflush(stdout); } } else { fprintf(stdout,"%s cbc_columnStatus = %p\n", prefix, (void*)cbc_columnStatus); fflush(stdout); } } } /* Save model as a clone (does not work as of 2004). */ model2 = Cbc_clone(model); /* Store which variables are integer as defined in the MPS file. They will be set to Continuous before adding the SOS constraints. */ { int i; int numberColumns=Cbc_getNumCols(model); numberIntegers = 0; integerVariable = malloc(numberColumns*sizeof(int[1])); for ( i=0;i3) printf("%s integerVariable[%i] = %i\n",prefix, numberIntegers-1, integerVariable[numberIntegers-1]); } } } Cbc_problemName(model,80,modelName); /* Solve the MPS version of the problem */ if (1) { if (VERBOSE>1) { printf("%s Solve MPS version of the problem\n",prefix); printf("%s Optimization Direction = %g (1 - minimize, -1 - maximize, 0 - ignore)\n", prefix, Cbc_optimizationDirection(model)); } /* Cbc_setLogLevel(model, VERBOSE); // 4 is verbose */ time1 = Cbc_cpuTime(model) ; Cbc_branchAndBound(model); if (VERBOSE>1) printf("Model %s has %d rows and %d columns\n", modelName,Cbc_numberRows(model),Cbc_numberColumns(model)); if (VERBOSE>1) printf("%s Solving model %s took %g seconds, %i nodes with objective %g\n", prefix, modelName, (Cbc_cpuTime(model)-time1), Cbc_getNodeCount(model), Cbc_getObjValue(model)); if (VERBOSE>0) (!Cbc_status(model)) ? printf(" Finished\n") : printf(" Not finished\n"); if (VERBOSE>2) printSolution(model); } { /* SOS specification data specify numberSets, numPoints, and whichRanges explicitly NOTE: These need to be commented according to the MPS file. Example_1_1: Cbc0004I MPS reads 1081 only columns out of 1085 Then the 4th range goes out of bounds Example_2: Cbc0006I The LP relaxation is infeasible or too expensive Mod_RT_1: Cbc0006I The LP relaxation is infeasible or too expensive */ const int numberSets = 1; /* dummy // 4; // Example_1_1 // 2; // Example_2 // 2; // Mod_RT_1 // 2; // SITH */ const int numPoints = 1; /* dummy // 257; // Example_1_1 // 256; // Example_2 // 257; // Mod_RT_1 // 257; // SITH */ const int whichRanges[1][2] = { /* counting from zero? */ {0,0} /* dummy */ /* {56,312}, {313, 569}, {572, 828}, {829, 1085} // Example_1_1 {48, 303}, {304, 559} // Example_2 {45, 301}, {302, 558} // Mod_RT_1 {45, 301}, {302, 558} // SITH */ }; /* the rest is determined parametrically */ int *len = malloc(numberSets* sizeof(int[1])); int **which = malloc(numberSets* sizeof(int[1])); int setNum, pointNum; double *weights; int i, j; for (setNum = 0; setNum < numberSets; setNum++) { len[setNum] = whichRanges[setNum][1] - whichRanges[setNum][0] + 1; if (len[setNum] != numPoints) { printf("%s ERROR: len[%i] (%i) != numPoints (%i)\n", prefix, setNum, len[setNum], numPoints); return 1; } which[setNum] = malloc(numPoints*sizeof(int[1])); for (j = 0; j < len[setNum]; j++) which[setNum][j] = whichRanges[setNum][0] + j; /* Example_2 */ } weights = malloc(numPoints*sizeof(double[1])); for (pointNum = 0; pointNum < numPoints; pointNum++) weights[pointNum] = pointNum+1; /* Now use SOS2 NOTE: Only enable this if known good SOS Specification (above) */ if (1) { if (VERBOSE>1) printf("%s Use SOS2\n",prefix); /* Restore model */ Cbc_deleteModel(model); if (0) { model = Cbc_clone(model2); } else { model = getDefaultModel(argc, argv); } /* Cbc_setLogLevel(model, 4); // 4 is verbose */ if (VERBOSE>1) printf("%s Model %s has %d rows and %d columns\n", prefix, modelName,Cbc_numberRows(model),Cbc_numberColumns(model)); /* make SOS cuts */ for (i=0;i1) { printf("%s Solve MPS version of the problem\n",prefix); printf("%s Optimization Direction = %g (1 - minimize, -1 - maximize, 0 - ignore)\n", prefix, Cbc_optimizationDirection(model)); } if (VERBOSE>1) printf("%s calling Cbc_scaling()\n",prefix); Cbc_scaling(model,1); time1 = Cbc_cpuTime(model) ; if (VERBOSE>1) printf("%s calling Cbc_initialSolve()\n",prefix); Cbc_initialSolve(model); if (VERBOSE>3) Cbc_printModel(model,prefix); if (VERBOSE>1) printf("%s calling Cbc_branchAndBound()\n",prefix); Cbc_branchAndBound(model); if (VERBOSE>1) printf("%s %s took %g seconds, %i nodes with objective %g\n", prefix, modelName, (Cbc_cpuTime(model)-time1), Cbc_getNodeCount(model), Cbc_getObjValue(model)); if (VERBOSE>0) (!Cbc_status(model)) ? printf(" Finished\n") : printf(" Not finished\n"); if (VERBOSE>2) printSolution(model); } if (VERBOSE>1) printf("%s Log Level %i\n", prefix, Cbc_logLevel(model)); if (VERBOSE>0) printf("%s return 0\n",prefix); return 0; } /* main() */ Cbc-2.8.12/examples/sample5.cpp0000644000076600007660000002336612131315050014642 0ustar coincoin// $Id: sample5.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CbcConfig.h" #include "CoinPragma.hpp" #include #include // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchUser.hpp" #include "CbcCompareUser.hpp" #include "CbcCutGenerator.hpp" #include "CbcHeuristicLocal.hpp" #include "OsiClpSolverInterface.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglOddHole.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding.hpp" // Heuristics #include "CbcHeuristic.hpp" // Methods of building #include "CoinBuild.hpp" #include "CoinModel.hpp" #include "CoinTime.hpp" /************************************************************************ This main program creates an integer model and then solves it It then sets up some Cgl cut generators and calls branch and cut. Branching is simple binary branching on integer variables. Node selection is depth first until first solution is found and then based on objective and number of unsatisfied integer variables. In this example the functionality is the same as default but it is a user comparison function. Variable branching selection is on maximum minimum-of-up-down change after strong branching on 5 variables closest to 0.5. A simple rounding heuristic is used. ************************************************************************/ int main (int argc, const char *argv[]) { /* Define your favorite OsiSolver. CbcModel clones the solver so use solver1 up to the time you pass it to CbcModel then use a pointer to cloned solver (model.solver()) */ OsiClpSolverInterface solver1; /* From now on we can build model in a solver independent way. You can add rows one at a time but for large problems this is slow so this example uses CoinBuild or CoinModel */ OsiSolverInterface * solver = &solver1; // Data (is exmip1.mps in Mps/Sample // Objective double objValue[]={1.0,2.0,0.0,0.0,0.0,0.0,0.0,-1.0}; // Lower bounds for columns double columnLower[]={2.5,0.0,0.0,0.0,0.5,0.0,0.0,0.0}; // Upper bounds for columns double columnUpper[]={COIN_DBL_MAX,4.1,1.0,1.0,4.0, COIN_DBL_MAX,COIN_DBL_MAX,4.3}; // Lower bounds for row activities double rowLower[]={2.5,-COIN_DBL_MAX,-COIN_DBL_MAX,1.8,3.0}; // Upper bounds for row activities double rowUpper[]={COIN_DBL_MAX,2.1,4.0,5.0,15.0}; // Matrix stored packed int column[] = {0,1,3,4,7, 1,2, 2,5, 3,6, 4,7}; double element[] = {3.0,1.0,-2.0,-1.0,-1.0, 2.0,1.1, 1.0,1.0, 2.8,-1.2, 1.0,1.9}; int starts[]={0,5,7,9,11,13}; // Integer variables (note upper bound already 1.0) int whichInt[]={2,3}; int numberRows=(int) (sizeof(rowLower)/sizeof(double)); int numberColumns=(int) (sizeof(columnLower)/sizeof(double)); #define BUILD 2 #if BUILD==1 // Using CoinBuild // First do columns (objective and bounds) int i; // We are not adding elements for (i=0;iaddCol(0,NULL,NULL,columnLower[i],columnUpper[i], objValue[i]); } // mark as integer for (i=0;i<(int) (sizeof(whichInt)/sizeof(int));i++) solver->setInteger(whichInt[i]); // Now build rows CoinBuild build; for (i=0;iaddRows(build); #else /* using CoinModel - more flexible but still beta. Can do exactly same way but can mix and match much more. Also all operations are on building object */ CoinModel build; // First do columns (objective and bounds) int i; for (i=0;iloadFromCoinModel(build); #endif // Pass to solver CbcModel model(*solver); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); generator1.setMaxProbe(100); generator1.setMaxLook(50); generator1.setRowCuts(3); // generator1.snapshot(*model.solver()); //generator1.createCliques(*model.solver(),2,1000,true); //generator1.setMode(0); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglOddHole generator4; generator4.setMinimumViolation(0.005); generator4.setMinimumViolationPer(0.00002); // try larger limit generator4.setMaximumEntries(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding mixedGen; CglFlowCover flowGen; // Add in generators model.addCutGenerator(&generator1,-1,"Probing"); model.addCutGenerator(&generator2,-1,"Gomory"); model.addCutGenerator(&generator3,-1,"Knapsack"); model.addCutGenerator(&generator4,-1,"OddHole"); model.addCutGenerator(&generator5,-1,"Clique"); model.addCutGenerator(&flowGen,-1,"FlowCover"); model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver()); // go faster stripes if (osiclp->getNumRows()<300&&osiclp->getNumCols()<500) { osiclp->setupForRepeatedUse(2,0); printf("trying slightly less reliable but faster version (? Gomory cuts okay?)\n"); printf("may not be safe if doing cuts in tree which need accuracy (level 2 anyway)\n"); } // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // And local search when new solution found CbcHeuristicLocal heuristic2(model); model.addHeuristic(&heuristic2); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); // Do initial solve to continuous model.initialSolve(); // Could tune more model.setMinimumDrop(CoinMin(1.0, fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4)); if (model.getNumCols()<500) model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (model.getNumCols()<5000) model.setMaximumCutPassesAtRoot(100); // use minimum drop else model.setMaximumCutPassesAtRoot(20); //model.setMaximumCutPasses(5); // Switch off strong branching if wanted // model.setNumberStrong(0); // Do more strong branching if small if (model.getNumCols()<5000) model.setNumberStrong(10); model.solver()->setIntParam(OsiMaxNumIterationHotStart,100); // If time is given then stop after that number of minutes if (argc>2) { int minutes = atoi(argv[2]); std::cout<<"Stopping after "<=0); model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes); } // Switch off most output if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } double time1 = CoinCpuTime(); // Do complete search model.branchAndBound(); std::cout<<" Branch and cut took "<cutGeneratorName()<<" was tried " <numberTimesEntered()<<" times and created " <numberCutsInTotal()<<" cuts of which " <numberCutsActive()<<" were active after adding rounds of cuts" <getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7&&model.solver()->isInteger(iColumn)) std::cout< #include "CoinTime.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "ClpFactorization.hpp" #include "ClpObjective.hpp" #include "ClpSimplex.hpp" #include "CbcSolverLongThin.hpp" #include "CbcModel.hpp" #include "ClpPresolve.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchFollow2.hpp" #include "CbcCutGenerator.hpp" #include "CbcCompareUser.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglOddHole.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding.hpp" #include "CglTwomir.hpp" #include "CglDuplicateRow.hpp" #include "CbcFathomDynamicProgramming.hpp" static int timesBad_=0; //############################################################################# // Solve methods //############################################################################# static CglDuplicateRow * tryCut=NULL; void CbcSolverLongThin::initialSolve() { modelPtr_->scaling(0); setBasis(basis_,modelPtr_); modelPtr_->dual(); basis_ = getBasis(modelPtr_); assert(!modelPtr_->specialOptions()); modelPtr_->setLogLevel(0); if (!tryCut) { tryCut = new CglDuplicateRow(this); tryCut->setLogLevel(2); } } //----------------------------------------------------------------------------- void CbcSolverLongThin::resolve() { int * whichRow = NULL; int * whichColumn = NULL; // problem may be small enough to do nested search const double * colLower = modelPtr_->columnLower(); const double * colUpper = modelPtr_->columnUpper(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int numberRows=modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); int i; int nFix=0; int nNewRow=0; int nNewCol=0; int sizeDynamic = COIN_INT_MAX; int smallOriginalNumberRows=0; if (algorithm_==0) { for (i=0;igenerateCuts(*this,cs); int numberCuts = cs.sizeColCuts(); if (numberCuts) { for ( i = 0 ; i < numberCuts ; i++) { const OsiColCut *thisCut = cs.colCutPtr(i) ; const CoinPackedVector & ubs = thisCut->ubs() ; int n = ubs.getNumElements() ; const int * which = ubs.getIndices() ; const double * values = ubs.getElements() ; for (int j = 0;jsetColUpper(iColumn,values[j]) ; } } } #if 1 const int * duplicate = tryCut->duplicate(); sizeDynamic = tryCut->sizeDynamic(); int nOrig = tryCut->numberOriginalRows(); for (i=0;isetRowStatus(i,ClpSimplex::basic); } smallOriginalNumberRows=nNewRow; for (;icount_-memory_&&node_[i]>0); if ((choose&&colUpper[i]) ||(modelPtr_->getStatus(i)!=ClpSimplex::atLowerBound&& modelPtr_->getStatus(i)!=ClpSimplex::isFixed) ||colLower[i]>0.0) whichColumn[nNewCol++]=i; } } if (nestedSearch_<1.0&&model_&&model_->phase()==2) { if (((double) sizeDynamic)*((double) nNewCol)<1000000000&&sizeDynamic<10000000) { // could do Dynamic Programming // back to original number of rows nNewRow = smallOriginalNumberRows; // and get rid of any basics int nNewCol=0; for (i=0;i0.0) whichColumn[nNewCol++]=i; } ClpSimplex temp(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); int returnCode; double * rowLower2 = temp.rowLower(); double * rowUpper2 = temp.rowUpper(); int numberColumns2 = temp.numberColumns(); double * colLower2 = temp.columnLower(); double * colUpper2 = temp.columnUpper(); const CoinPackedMatrix * matrix = temp.matrix(); const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); double offset=0.0; const double * objective = temp.objective(); bool feasible=true; for (i=0;isetLogLevel(0); CbcFathomDynamicProgramming fathom1(modelSmall); // Set maximum space allowed fathom1.setMaximumSize(100000000); temp2.writeMps("small"); returnCode=fathom1.fathom(solutionDP); if (returnCode!=1) { printf("probably not enough memory\n"); abort(); } } if (solutionDP) { double objValue = 0.0; double * solution = modelPtr_->primalColumnSolution(); const double * objective = modelPtr_->objective(); for (i=0;igetCutoff()) { printf("good solution %g by dynamic programming\n",objValue); returnCode = 0; // paranoid check double * rowLower = modelPtr_->rowLower(); double * rowUpper = modelPtr_->rowUpper(); // Column copy const CoinPackedMatrix * matrix2 = modelPtr_->matrix(); element = matrix2->getElements(); row = matrix2->getIndices(); columnStart = matrix2->getVectorStarts(); columnLength = matrix2->getVectorLengths(); double * rowActivity = new double [numberRows]; memset(rowActivity,0,numberRows*sizeof(double)); for (i=0;i=colLower[i]&&value<=colUpper[i]); if (value) { printf("%d has value %g\n",i,value); for (j=columnStart[i]; jrowUpper[i]) { if (rowActivity[i]>rowUpper[i]+1.0e-8) feasible = false; } } if (!feasible) { printf("** Bad solution by dynamic programming\n"); abort(); } delete [] rowActivity; model_->setBestSolution(CBC_TREE_SOL,objValue,solution); } else { returnCode=2; } } else { returnCode=2; } temp2.releaseClp(); modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; return; } if (nFix>nestedSearch_*numberIntegers) { // Do nested search // back to original number of rows nNewRow = smallOriginalNumberRows; // and get rid of any basics int nNewCol=0; for (i=0;i0.0) whichColumn[nNewCol++]=i; } #if 0 // We clone from continuous solver so set some stuff OsiSolverInterface * solver = model_->continuousSolver(); CbcSolverLongThin * osiclp = dynamic_cast< CbcSolverLongThin*> (solver); assert (osiclp); // up special options if (osiclp->specialOptions()==3) osiclp->setSpecialOptions(7); double saveNested = osiclp->getNested(); int saveAlgorithm = osiclp->getAlgorithm(); osiclp->setNested(1.0); osiclp->setAlgorithm(0); int numberObjects = model_->numberObjects(); if (numberObjects>model_->numberIntegers()) { // for now only integers //assert (numberObjects == model_->numberIntegers()+1); model_->setNumberObjects(model_->numberIntegers()); // try follow on //model_->setNumberObjects(model_->numberIntegers()+1); } double saveMaxTime = model_->getDblParam(CbcModel::CbcMaximumSeconds); model_->setDblParam(CbcModel::CbcMaximumSeconds,1.0e5); // up special options #if 1 int returnCode= model_->subBranchAndBound(colLower,colUpper,2000); #else CbcModel * model3 = model_->cleanModel(colLower,colUpper); // integer presolve int returnCode=0; CbcModel * model2 = model3->integerPresolve(false); if (!model2||!model2->getNumRows()) { delete model2; delete model3; returnCode= 2; } else { if (handler_->logLevel()>1) printf("Reduced model has %d rows and %d columns\n", model2->getNumRows(),model2->getNumCols()); if (true) { OsiSolverInterface * solver = model2->solver(); OsiSolverInterface * osiclp = dynamic_cast< OsiSolverInterface*> (solver); assert (osiclp); int * priority = new int [numberColumns+1]; int n=0; int iColumn; for ( iColumn=0;iColumnisInteger(iColumn)) { priority[n++]=10000; } } priority[n]=1; CbcObject * newObject =new CbcFollowOn2(model2); model2->addObjects(1,&newObject); delete newObject; model2->passInPriorities(priority,false); delete [] priority; } returnCode= model_->subBranchAndBound(model3,model2,4000); } #endif model_->setDblParam(CbcModel::CbcMaximumSeconds,saveMaxTime); model_->setNumberObjects(numberObjects); osiclp->setNested(saveNested); osiclp->setAlgorithm(saveAlgorithm); #else // start again very simply ClpSimplex temp(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); int returnCode; OsiClpSolverInterface temp2(&temp); temp2.setupForRepeatedUse(2); int numberColumns2 = temp.numberColumns(); const double * colUpper2 = temp2.getColUpper(); const double * colLower2 = temp2.getColLower(); const double * solution2 = temp.getColSolution(); double * cleanSolution2 = new double [numberColumns2]; for (i=0;igetVectorLengths(); int * priority = new int [numberColumns2+1]; // do pseudo costs and priorities - take a reasonable guess CbcObject ** objects = new CbcObject * [numberColumns2+1]; int n=0; const double * objective = modelSmall.getObjCoefficients(); for (i=0;isetMethod(3); objects[n]= newObject; priority[n++]=10000-columnLength[i]; } priority[n]=1; objects[n++]=new CbcFollowOn2(&modelSmall); modelSmall.addObjects(n,objects); for (i=0;igetCutoff()); //if (!onPathX&&modelSmall.getCutoff()>480.5) //modelSmall.setCutoff(480.5); //printf("cutoff %g\n",model_->getCutoff()); modelSmall.messageHandler()->setLogLevel(1); modelSmall.solver()->messageHandler()->setLogLevel(0); modelSmall.messagesPointer()->setDetailMessage(3,9); modelSmall.messagesPointer()->setDetailMessage(3,6); modelSmall.messagesPointer()->setDetailMessage(3,4); modelSmall.messagesPointer()->setDetailMessage(3,13); modelSmall.messagesPointer()->setDetailMessage(3,14); modelSmall.messagesPointer()->setDetailMessage(3,1); modelSmall.messagesPointer()->setDetailMessage(3,3007); modelSmall.branchAndBound(); temp2.releaseClp(); if (modelSmall.bestSolution()) { double objValue = 0.0; const double * solution2 = modelSmall.bestSolution(); double * solution = modelPtr_->primalColumnSolution(); const double * objective = modelPtr_->objective(); for (i=0;igetCutoff()); if (objValuegetCutoff()) { //printf("good solution \n"); model_->setBestSolution(CBC_TREE_SOL,objValue,solution); returnCode = 0; } else { returnCode=2; } } else { returnCode=2; } #endif if (returnCode!=0&&returnCode!=2) { printf("pretending entire search done\n"); returnCode=0; } if (returnCode==0||returnCode==2) { modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; return; } } } if ((count_<100&&algorithm_==2)||!algorithm_) { delete [] whichRow; delete [] whichColumn; assert(!modelPtr_->specialOptions()); int saveOptions = modelPtr_->specialOptions(); bool takeHint; OsiHintStrength strength; getHintParam(OsiDoInBranchAndCut,takeHint,strength); if (strength!=OsiHintIgnore&&takeHint) { // could do something - think about it //printf("thin hint %d %c\n",strength,takeHint ? 'T' :'F'); } if((specialOptions_&1)==0) { modelPtr_->setSpecialOptions(saveOptions|(64|1024)); } else { if((specialOptions_&4)==0) modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|4096)); else modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|2048|4096)); } //printf("thin options %d size %d\n",modelPtr_->specialOptions(),modelPtr_->numberColumns()); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(saveOptions); if (modelPtr_->status()==0) { count_++; double * solution = modelPtr_->primalColumnSolution(); int i; for (i=0;i1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } } else { if (!algorithm_==2) printf("infeasible early on\n"); } } else { // use counts int i; const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); setBasis(basis_,modelPtr_); ClpSimplex * temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); //temp->setLogLevel(2); //printf("small has %d rows and %d columns\n",nNewRow,nNewCol); temp->setSpecialOptions(128+512); temp->setDualObjectiveLimit(1.0e50); temp->dual(); if (temp->status()) { // In some cases we know that it must be infeasible if (believeInfeasible_||algorithm_==1) { modelPtr_->setProblemStatus(1); printf("assuming infeasible!\n"); //modelPtr_->writeMps("infeas.mps"); //temp->writeMps("infeas2.mps"); //abort(); delete temp; delete [] whichRow; delete [] whichColumn; return; } } double * solution = modelPtr_->primalColumnSolution(); if (!temp->status()) { const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;isetStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;isetRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } // See if optimal double * dj = modelPtr_->dualColumnSolution(); // get reduced cost for large problem // this assumes minimization memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double)); modelPtr_->transposeTimes(-1.0,dual,dj); modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); int nBad=0; for (i=0;igetStatus(i)==ClpSimplex::atLowerBound &&upper[i]>lower[i]&&dj[i]<-1.0e-5) nBad++; } //modelPtr_->writeMps("bada.mps"); //temp->writeMps("badb.mps"); if (nBad) { assert (algorithm_==2); //printf("%d bad\n",nBad); timesBad_++; modelPtr_->primal(); } } else { // infeasible - do all modelPtr_->setSpecialOptions(64+128+512); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); if (modelPtr_->status()) { printf("really infeasible!\n"); delete temp; delete [] whichRow; delete [] whichColumn; return; } else { printf("initially infeasible\n"); } } delete temp; delete [] whichRow; delete [] whichColumn; basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); count_++; if ((count_%100)==0&&algorithm_==2) printf("count %d, bad %d\n",count_,timesBad_); for (i=0;i1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } if (modelPtr_->objectiveValue()>=modelPtr_->dualObjectiveLimit()) modelPtr_->setProblemStatus(1); } } //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CbcSolverLongThin::CbcSolverLongThin () : OsiClpSolverInterface() { node_=NULL; howMany_=NULL; count_=0; model_ = NULL; memory_=300; believeInfeasible_=false; nestedSearch_ = 1.0; algorithm_=0; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * CbcSolverLongThin::clone(bool CopyData) const { if (CopyData) { return new CbcSolverLongThin(*this); } else { printf("warning CbcSolveUser clone with copyData false\n"); return new CbcSolverLongThin(); } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CbcSolverLongThin::CbcSolverLongThin ( const CbcSolverLongThin & rhs) : OsiClpSolverInterface(rhs) { model_ = rhs.model_; int numberColumns = modelPtr_->numberColumns(); node_=CoinCopyOfArray(rhs.node_,numberColumns); howMany_=CoinCopyOfArray(rhs.howMany_,numberColumns); count_=rhs.count_; memory_=rhs.memory_; believeInfeasible_ = rhs.believeInfeasible_; nestedSearch_ = rhs.nestedSearch_; algorithm_=rhs.algorithm_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CbcSolverLongThin::~CbcSolverLongThin () { delete [] node_; delete [] howMany_; } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcSolverLongThin & CbcSolverLongThin::operator=(const CbcSolverLongThin& rhs) { if (this != &rhs) { OsiClpSolverInterface::operator=(rhs); delete [] node_; delete [] howMany_; model_ = rhs.model_; int numberColumns = modelPtr_->numberColumns(); node_=CoinCopyOfArray(rhs.node_,numberColumns); howMany_=CoinCopyOfArray(rhs.howMany_,numberColumns); count_=rhs.count_; memory_=rhs.memory_; believeInfeasible_ = rhs.believeInfeasible_; nestedSearch_ = rhs.nestedSearch_; algorithm_=rhs.algorithm_; } return *this; } //------------------------------------------------------------------- // Real initializer //------------------------------------------------------------------- void CbcSolverLongThin::initialize (CbcModel * model, const char * keep) { model_=model; int numberColumns = modelPtr_->numberColumns(); if (numberColumns) { node_ = new int[numberColumns]; howMany_ = new int[numberColumns]; for (int i=0;i #include #include //#define CBC_DEBUG #include "CoinPragma.hpp" #include "CbcMessage.hpp" #include "CbcModel.hpp" #include "CbcTree.hpp" #include "CbcCompareUser.hpp" #include "CoinError.hpp" #include "CoinHelperFunctions.hpp" /** Default Constructor */ CbcCompareUser::CbcCompareUser () : CbcCompareBase(), weight_(-1.0), saveWeight_(0.0), numberSolutions_(0), count_(0), treeSize_(0) { test_=this; } // Constructor with weight CbcCompareUser::CbcCompareUser (double weight) : CbcCompareBase(), weight_(weight) , saveWeight_(0.0), numberSolutions_(0), count_(0), treeSize_(0) { test_=this; } // Copy constructor CbcCompareUser::CbcCompareUser ( const CbcCompareUser & rhs) :CbcCompareBase(rhs) { weight_=rhs.weight_; saveWeight_ = rhs.saveWeight_; numberSolutions_=rhs.numberSolutions_; count_ = rhs.count_; treeSize_ = rhs.treeSize_; } // Clone CbcCompareBase * CbcCompareUser::clone() const { return new CbcCompareUser(*this); } // Assignment operator CbcCompareUser & CbcCompareUser::operator=( const CbcCompareUser& rhs) { if (this!=&rhs) { CbcCompareBase::operator=(rhs); weight_=rhs.weight_; saveWeight_ = rhs.saveWeight_; numberSolutions_=rhs.numberSolutions_; count_ = rhs.count_; treeSize_ = rhs.treeSize_; } return *this; } // Destructor CbcCompareUser::~CbcCompareUser () { } // For moment go to default #if 0 // Returns true if y better than x bool CbcCompareUser::test (CbcNode * x, CbcNode * y) { if (x) { if (y) { if (weight_==-1.0) { // before solution /* printf("x %d %d %g, y %d %d %g\n", x->numberUnsatisfied(),x->depth(),x->objectiveValue(), y->numberUnsatisfied(),y->depth(),y->objectiveValue()); */ if (x->numberUnsatisfied() > y->numberUnsatisfied()) return true; else if (x->numberUnsatisfied() < y->numberUnsatisfied()) return false; else return x->depth() < y->depth(); } else { // after solution double weight = CoinMax(weight_,0.0); return x->objectiveValue()+ weight*x->numberUnsatisfied() > y->objectiveValue() + weight*y->numberUnsatisfied(); //return x->guessedObjectiveValue()>y->guessedObjectiveValue(); } } else { return false; } } else { return true; } } // This allows method to change behavior as it is called // after each solution void CbcCompareUser::newSolution(CbcModel * model, double objectiveAtContinuous, int numberInfeasibilitiesAtContinuous) { // set to get close to this solution double costPerInteger = (model->getObjValue()-objectiveAtContinuous)/ ((double) numberInfeasibilitiesAtContinuous); weight_ = 0.95*costPerInteger; saveWeight_=weight_; if (model->getSolutionCount()==model->getNumberHeuristicSolutions()) return; // solution was got by rounding numberSolutions_++; if (numberSolutions_>5) weight_ =0.0; // this searches on objective return (true) ; } // This allows method to change behavior bool CbcCompareUser::every1000Nodes(CbcModel * model, int numberNodes) { if (numberNodes>10000) weight_ =0.0; // this searches on objective else if (numberNodes==1000&&weight_==-2.0) weight_=-1.0; // Go to depth first // get size of tree treeSize_ = model->tree()->size(); if (treeSize_>10000) { // set weight to reduce size most of time if (treeSize_>20000) weight_=-1.0; else if ((numberNodes%4000)!=0) weight_=-1.0; else weight_=saveWeight_; } return numberNodes==11000; // resort if first time } // Returns true if wants code to do scan with alternate criterion bool CbcCompareUser::fullScan() const { count_++; if (weight_) return (count_%10)==0; else return false; } // This is alternate test function bool CbcCompareUser::alternateTest (CbcNode * x, CbcNode * y) { if (x) { if (y) { return x->objectiveValue() > y->objectiveValue() ; } else { return false; } } else { return true; } } #else // Returns true if y better than x bool CbcCompareUser::test (CbcNode * x, CbcNode * y) { if (weight_==-1.0&&(y->depth()>7||x->depth()>7)) { // before solution /* printf("x %d %d %g, y %d %d %g\n", x->numberUnsatisfied(),x->depth(),x->objectiveValue(), y->numberUnsatisfied(),y->depth(),y->objectiveValue()); */ if (x->numberUnsatisfied() > y->numberUnsatisfied()) { return true; } else if (x->numberUnsatisfied() < y->numberUnsatisfied()) { return false; } else { int testX = x->depth(); int testY = y->depth(); if (testX!=testY) return testX < testY; else return equalityTest(x,y); // so ties will be broken in consistent manner } } else { // after solution double weight = CoinMax(weight_,0.0); double testX = x->objectiveValue()+ weight*x->numberUnsatisfied(); double testY = y->objectiveValue() + weight*y->numberUnsatisfied(); if (testX!=testY) return testX > testY; else return equalityTest(x,y); // so ties will be broken in consistent manner } } // This allows method to change behavior as it is called // after each solution bool CbcCompareUser::newSolution(CbcModel * model, double objectiveAtContinuous, int numberInfeasibilitiesAtContinuous) { if (model->getSolutionCount()==model->getNumberHeuristicSolutions()&& model->getSolutionCount()<5&&model->getNodeCount()<500) return (false) ; // solution was got by rounding // set to get close to this solution double costPerInteger = (model->getObjValue()-objectiveAtContinuous)/ ((double) numberInfeasibilitiesAtContinuous); weight_ = 0.95*costPerInteger; saveWeight_ = 0.95*weight_; numberSolutions_++; if (numberSolutions_>5) weight_ =0.0; // this searches on objective return (true) ; } // This allows method to change behavior bool CbcCompareUser::every1000Nodes(CbcModel * model, int numberNodes) { double saveWeight=weight_; int numberNodes1000 = numberNodes/1000; if (numberNodes>10000) { weight_ =0.0; // this searches on objective // but try a bit of other stuff if ((numberNodes1000%4)==1) weight_=saveWeight_; } else if (numberNodes==1000&&weight_==-2.0) { weight_=-1.0; // Go to depth first } // get size of tree treeSize_ = model->tree()->size(); if (treeSize_>10000) { int n1 = model->solver()->getNumRows()+model->solver()->getNumCols(); int n2 = model->numberObjects(); double size = n1*0.1 + n2*2.0; // set weight to reduce size most of time if (treeSize_*size>5.0e7) weight_=-1.0; else if ((numberNodes1000%4)==0&&treeSize_*size>1.0e6) weight_=-1.0; else if ((numberNodes1000%4)==1) weight_=0.0; else weight_=saveWeight_; } return (weight_!=saveWeight); } // Returns true if wants code to do scan with alternate criterion bool CbcCompareUser::fullScan() const { return false; } // This is alternate test function bool CbcCompareUser::alternateTest (CbcNode * x, CbcNode * y) { // not used abort(); return false; } #endif Cbc-2.8.12/examples/CbcSolver3.cpp0000644000076600007660000004027512131315050015237 0ustar coincoin// $Id: CbcSolver3.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include "CoinTime.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "ClpFactorization.hpp" #include "ClpObjective.hpp" #include "ClpSimplex.hpp" #include "CbcSolver3.hpp" #include "CbcModel.hpp" #include "ClpPresolve.hpp" #include "CbcHeuristicGreedy.hpp" #include "CbcBranchActual.hpp" #include "CbcCutGenerator.hpp" #include "CbcCompareUser.hpp" #include "CbcCompareActual.hpp" #include "CbcCompareObjective.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglOddHole.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding.hpp" #include "CglTwomir.hpp" static int timesBad_=0; //############################################################################# // Solve methods //############################################################################# void CbcSolver3::initialSolve() { modelPtr_->scaling(0); setBasis(basis_,modelPtr_); // Do long thin by sprint ClpSolve options; options.setSolveType(ClpSolve::usePrimalorSprint); options.setPresolveType(ClpSolve::presolveOff); options.setSpecialOption(1,3,30); modelPtr_->initialSolve(options); basis_ = getBasis(modelPtr_); modelPtr_->setLogLevel(0); } //----------------------------------------------------------------------------- void CbcSolver3::resolve() { int * whichRow = NULL; int * whichColumn = NULL; // problem may be small enough to do nested search const double * colLower = modelPtr_->columnLower(); const double * colUpper = modelPtr_->columnUpper(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int numberRows=modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); int i; int nFix=0; int nNewRow=0; int nNewCol=0; int smallOriginalNumberRows=0; if (algorithm_==0) { for (i=0;icount_-memory_&&node_[i]>0); if ((choose&&colUpper[i]) ||(modelPtr_->getStatus(i)!=ClpSimplex::atLowerBound&& modelPtr_->getStatus(i)!=ClpSimplex::isFixed) ||colLower[i]>0.0) whichColumn[nNewCol++]=i; } } if (nestedSearch_<1.0&&model_&&model_->phase()==2) { if (nFix>nestedSearch_*numberIntegers) { // Do nested search // back to original number of rows nNewRow = smallOriginalNumberRows; // and get rid of any basics int nNewCol=0; for (i=0;i0.0) whichColumn[nNewCol++]=i; } // start again very simply ClpSimplex temp(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); int returnCode; OsiClpSolverInterface temp2(&temp); temp2.setupForRepeatedUse(2); int numberColumns2 = temp.numberColumns(); const double * colUpper2 = temp2.getColUpper(); const double * colLower2 = temp2.getColLower(); const double * solution2 = temp.getColSolution(); double * cleanSolution2 = new double [numberColumns2]; for (i=0;igetVectorLengths(); int * priority = new int [numberColumns2+1]; // do pseudo costs and priorities - take a reasonable guess CbcObject ** objects = new CbcObject * [numberColumns2+1]; int n=0; const double * objective = modelSmall.getObjCoefficients(); for (i=0;isetMethod(3); objects[n]= newObject; priority[n++]=10000-columnLength[i]; } modelSmall.addObjects(n,objects); for (i=0;igetCutoff()); modelSmall.messageHandler()->setLogLevel(1); modelSmall.solver()->messageHandler()->setLogLevel(0); modelSmall.messagesPointer()->setDetailMessage(3,9); modelSmall.messagesPointer()->setDetailMessage(3,6); modelSmall.messagesPointer()->setDetailMessage(3,4); modelSmall.messagesPointer()->setDetailMessage(3,13); modelSmall.messagesPointer()->setDetailMessage(3,14); modelSmall.messagesPointer()->setDetailMessage(3,1); modelSmall.messagesPointer()->setDetailMessage(3,3007); // Definition of node choice CbcCompareObjective compare; modelSmall.setNodeComparison(compare); // And Greedy heuristic CbcHeuristicGreedyCover heuristic2(modelSmall); // Use original upper and perturb more heuristic2.setAlgorithm(11); modelSmall.addHeuristic(&heuristic2); modelSmall.branchAndBound(); temp2.releaseClp(); if (modelSmall.bestSolution()) { double objValue = 0.0; const double * solution2 = modelSmall.bestSolution(); double * solution = modelPtr_->primalColumnSolution(); const double * objective = modelPtr_->objective(); for (i=0;igetCutoff()); if (objValuegetCutoff()) { //printf("good solution \n"); model_->setBestSolution(CBC_TREE_SOL,objValue,solution); returnCode = 0; } else { returnCode=2; } } else { returnCode=2; } if (returnCode!=0&&returnCode!=2) { printf("pretending entire search done\n"); returnCode=0; } if (returnCode==0||returnCode==2) { modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; return; } } } if ((count_<100&&algorithm_==2)||!algorithm_) { delete [] whichRow; delete [] whichColumn; assert(!modelPtr_->specialOptions()); int saveOptions = modelPtr_->specialOptions(); bool takeHint; OsiHintStrength strength; getHintParam(OsiDoInBranchAndCut,takeHint,strength); if (strength!=OsiHintIgnore&&takeHint) { // could do something - think about it //printf("thin hint %d %c\n",strength,takeHint ? 'T' :'F'); } if((specialOptions_&1)==0) { modelPtr_->setSpecialOptions(saveOptions|(64|1024)); } else { if((specialOptions_&4)==0) modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|4096)); else modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|2048|4096)); } //printf("thin options %d size %d\n",modelPtr_->specialOptions(),modelPtr_->numberColumns()); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); printf("model has %d rows\n",modelPtr_->numberRows()); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(saveOptions); if (modelPtr_->status()==0) { count_++; double * solution = modelPtr_->primalColumnSolution(); int i; for (i=0;i1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } } else { if (!algorithm_==2) printf("infeasible early on\n"); } } else { // use counts int i; const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); setBasis(basis_,modelPtr_); ClpSimplex * temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); //temp->setLogLevel(2); //printf("small has %d rows and %d columns\n",nNewRow,nNewCol); temp->setSpecialOptions(128+512); temp->setDualObjectiveLimit(1.0e50); printf("model has %d rows\n",nNewRow); temp->dual(); if (temp->status()) { // In some cases we know that it must be infeasible if (believeInfeasible_||algorithm_==1) { modelPtr_->setProblemStatus(1); printf("assuming infeasible!\n"); //modelPtr_->writeMps("infeas.mps"); //temp->writeMps("infeas2.mps"); //abort(); delete temp; delete [] whichRow; delete [] whichColumn; return; } } double * solution = modelPtr_->primalColumnSolution(); if (!temp->status()) { const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;isetStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;isetRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } // See if optimal double * dj = modelPtr_->dualColumnSolution(); // get reduced cost for large problem // this assumes minimization memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double)); modelPtr_->transposeTimes(-1.0,dual,dj); modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); int nBad=0; for (i=0;igetStatus(i)==ClpSimplex::atLowerBound &&upper[i]>lower[i]&&dj[i]<-1.0e-5) nBad++; } //modelPtr_->writeMps("bada.mps"); //temp->writeMps("badb.mps"); if (nBad) { assert (algorithm_==2); //printf("%d bad\n",nBad); timesBad_++; modelPtr_->primal(); } } else { // infeasible - do all modelPtr_->setSpecialOptions(64+128+512); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); if (modelPtr_->status()) { printf("really infeasible!\n"); delete temp; delete [] whichRow; delete [] whichColumn; return; } else { printf("initially infeasible\n"); } } delete temp; delete [] whichRow; delete [] whichColumn; basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); count_++; if ((count_%100)==0&&algorithm_==2) printf("count %d, bad %d\n",count_,timesBad_); for (i=0;i1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } if (modelPtr_->objectiveValue()>=modelPtr_->dualObjectiveLimit()) modelPtr_->setProblemStatus(1); } } //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CbcSolver3::CbcSolver3 () : OsiClpSolverInterface() { node_=NULL; howMany_=NULL; count_=0; model_ = NULL; memory_=300; believeInfeasible_=false; nestedSearch_ = 1.0; algorithm_=0; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * CbcSolver3::clone(bool CopyData) const { if (CopyData) { return new CbcSolver3(*this); } else { printf("warning CbcSolveUser clone with copyData false\n"); return new CbcSolver3(); } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CbcSolver3::CbcSolver3 ( const CbcSolver3 & rhs) : OsiClpSolverInterface(rhs) { model_ = rhs.model_; int numberColumns = modelPtr_->numberColumns(); node_=CoinCopyOfArray(rhs.node_,numberColumns); howMany_=CoinCopyOfArray(rhs.howMany_,numberColumns); count_=rhs.count_; memory_=rhs.memory_; believeInfeasible_ = rhs.believeInfeasible_; nestedSearch_ = rhs.nestedSearch_; algorithm_=rhs.algorithm_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CbcSolver3::~CbcSolver3 () { delete [] node_; delete [] howMany_; } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcSolver3 & CbcSolver3::operator=(const CbcSolver3& rhs) { if (this != &rhs) { OsiClpSolverInterface::operator=(rhs); delete [] node_; delete [] howMany_; model_ = rhs.model_; int numberColumns = modelPtr_->numberColumns(); node_=CoinCopyOfArray(rhs.node_,numberColumns); howMany_=CoinCopyOfArray(rhs.howMany_,numberColumns); count_=rhs.count_; memory_=rhs.memory_; believeInfeasible_ = rhs.believeInfeasible_; nestedSearch_ = rhs.nestedSearch_; algorithm_=rhs.algorithm_; } return *this; } //------------------------------------------------------------------- // Real initializer //------------------------------------------------------------------- void CbcSolver3::initialize (CbcModel * model, const char * keep) { model_=model; int numberColumns = modelPtr_->numberColumns(); if (numberColumns) { node_ = new int[numberColumns]; howMany_ = new int[numberColumns]; for (int i=0;i #include "CoinPragma.hpp" // For Branch and bound #include "OsiClpSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcCutGenerator.hpp" #include "CoinHelperFunctions.hpp" #include "CbcStrategy.hpp" // Need stored cuts #include "CglStored.hpp" // For saying about solution validity #include "OsiAuxInfo.hpp" // Time #include "CoinTime.hpp" // Class to disallow strong branching solutions #include "CbcFeasibilityBase.hpp" class CbcFeasibilityNoStrong : public CbcFeasibilityBase{ public: // Default Constructor CbcFeasibilityNoStrong () {} virtual ~CbcFeasibilityNoStrong() {} // Copy constructor CbcFeasibilityNoStrong ( const CbcFeasibilityNoStrong &rhs) {} // Assignment operator CbcFeasibilityNoStrong & operator=( const CbcFeasibilityNoStrong& rhs) { return * this;} /// Clone virtual CbcFeasibilityBase * clone() const { return new CbcFeasibilityNoStrong();} /** On input mode: 0 - called after a solve but before any cuts -1 - called after strong branching Returns : 0 - no opinion -1 pretend infeasible 1 pretend integer solution */ virtual int feasible(CbcModel * model, int mode) {return mode;} }; /************************************************************************ This main program solves the following 0-1 problem: min -x0 - 2x1 - 3x2 - 4x3 subject to x0 + x1 + x2 + x3 <= 2 and quadratic constraints with positive random numbers It does it creating extra yij variables and constraints xi + xj -1 <= yij and putting quadratic elements on y The extra constraints are treated as stored cuts. This is to show how to keep branching even if we have a solution ************************************************************************/ int main (int argc, const char *argv[]) { // Define a Solver which inherits from OsiClpsolverInterface -> OsiSolverInterface OsiClpSolverInterface solver1; int nX=4; int nY = (nX * (nX-1)/2); // All columns double * obj = new double [nX+nY]; double * clo = new double[nX+nY]; double * cup = new double[nX+nY]; int i; for (i=0;isetMustCallAgain(true); // Say cuts needed at continuous (b) OsiBabSolver oddCuts; oddCuts.setSolverType(4); model.passInSolverCharacteristics(&oddCuts); // Say no to all solutions by strong branching (c) CbcFeasibilityNoStrong noStrong; model.setProblemFeasibility(noStrong); // Say don't recompute solution d) model.setSpecialOptions(4); double time1 = CoinCpuTime(); // Do complete search model.branchAndBound(); std::cout<getNumCols(); //const double * solution = model.bestSolution(); const double * solution = model.solver()->getColSolution(); int iColumn; for (iColumn=0;iColumn1.0e-7&&model.solver()->isInteger(iColumn)) printf("Column %d has value %g\n",iColumn,value); } } return 0; } Cbc-2.8.12/examples/ClpQuadInterface.hpp0000644000076600007660000000334111510742723016455 0ustar coincoin// $Id: ClpQuadInterface.hpp 1574 2011-01-05 01:13:55Z lou $ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef ClpQuadInterface_H #define ClpQuadInterface_H #include "OsiClpSolverInterface.hpp" //############################################################################# /** This is to allow the user to replace initialSolve and resolve */ class ClpQuadInterface : public OsiClpSolverInterface { public: //--------------------------------------------------------------------------- /**@name Solve methods */ //@{ /// Solve initial LP relaxation virtual void initialSolve(); /// Resolve an LP relaxation after problem modification virtual void resolve(); //@} /**@name Constructors and destructors */ //@{ /// Default Constructor ClpQuadInterface (); /// Clone virtual OsiSolverInterface * clone(bool CopyData=true) const; /// Copy constructor ClpQuadInterface (const ClpQuadInterface &); /// Assignment operator ClpQuadInterface & operator=(const ClpQuadInterface& rhs); /// Destructor virtual ~ClpQuadInterface (); //@} /**@name Sets and Getss */ //@{ /** Setup fake objective. It could also read an ampl .nl file or somehow get nonlinear info */ void initialize(); /// Get objective function value (can't use default) virtual double getObjValue() const; //@} //--------------------------------------------------------------------------- private: /**@name Private member data */ //@{ /// True quadratic objective ClpObjective * quadraticObjective_; //@} }; #endif Cbc-2.8.12/examples/Makefile.in0000644000076600007660000001300612131315050014623 0ustar coincoin# Copyright (C) 2006 International Business Machines and others. # All Rights Reserved. # This file is distributed under the Eclipse Public License. # $Id: Makefile.in 1902 2013-04-10 16:58:16Z stefan $ ########################################################################## # You can modify this example makefile to fit for your own program. # # Usually, you only need to change the five CHANGEME entries below. # ########################################################################## # To compile other examples, either changed the following line, or # add the argument DRIVER=problem_name to make DRIVER = driver # CHANGEME: This should be the name of your executable EXE = $(DRIVER)@EXEEXT@ # CHANGEME: Here is the name of all object files corresponding to the source # code that you wrote in order to define the problem statement OBJS = $(DRIVER).@OBJEXT@ # extra object files that are required by some examples (we just link them into each one) EXTRAOBJS = \ CbcCompareUser.@OBJEXT@ \ CbcSolver2.@OBJEXT@ \ CbcSolver3.@OBJEXT@ \ CbcSolverLongThin.@OBJEXT@ \ ClpQuadInterface.@OBJEXT@ \ CbcBranchFollow2.@OBJEXT@ \ CbcBranchUser.@OBJEXT@ \ CbcBranchLink.@OBJEXT@ # CHANGEME: Additional libraries # e.g., for driver2, put -lOsiCbc here ADDLIBS = # CHANGEME: Additional flags for compilation (e.g., include flags) ADDINCFLAGS = # CHANGEME: Directory to the sources for the (example) problem definition # files SRCDIR = @srcdir@ VPATH = @srcdir@ ########################################################################## # Usually, you don't have to change anything below. Note that if you # # change certain compiler options, you might have to recompile the # # package. # ########################################################################## COIN_HAS_PKGCONFIG = @COIN_HAS_PKGCONFIG_TRUE@TRUE COIN_CXX_IS_CL = @COIN_CXX_IS_CL_TRUE@TRUE COIN_HAS_SAMPLE = @COIN_HAS_SAMPLE_TRUE@TRUE COIN_HAS_MIPLIB3 = @COIN_HAS_MIPLIB3_TRUE@TRUE # C++ Compiler command CXX = @CXX@ # C++ Compiler options CXXFLAGS = @CXXFLAGS@ # C Compiler options CFLAGS = @CFLAGS@ # additional C++ Compiler options for linking CXXLINKFLAGS = @RPATH_FLAGS@ # Sample data directory ifeq ($(COIN_HAS_SAMPLE), TRUE) ifeq ($(COIN_HAS_PKGCONFIG), TRUE) CXXFLAGS += -DSAMPLEDIR=\"`PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ @PKG_CONFIG@ --variable=datadir coindatasample`\" CFLAGS += -DSAMPLEDIR=\"`PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ @PKG_CONFIG@ --variable=datadir coindatasample`\" else CXXFLAGS += -DSAMPLEDIR=\"@SAMPLE_DATA_INSTALLED@\" CFLAGS += -DSAMPLEDIR=\"@SAMPLE_DATA_INSTALLED@\" endif endif # Miplib3 data directory ifeq ($(COIN_HAS_MIPLIB3), TRUE) ifeq ($(COIN_HAS_PKGCONFIG), TRUE) CXXFLAGS += -DMIPLIB3DIR=\"`PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ @PKG_CONFIG@ --variable=datadir coindatamiplib3`\" else CXXFLAGS += -DMIPLIB3DIR=\"@MIPLIB3_DATA_INSTALLED@\" endif endif # Include directories (we use the CYGPATH_W variables to allow compilation with Windows compilers) ifeq ($(COIN_HAS_PKGCONFIG), TRUE) INCL = `PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ @PKG_CONFIG@ --cflags cbc` else INCL = @CBCLIB_CFLAGS_INSTALLED@ endif INCL += -I@srcdir@ $(ADDINCFLAGS) # Linker flags ifeq ($(COIN_HAS_PKGCONFIG), TRUE) LIBS = `PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ @PKG_CONFIG@ --libs cbc` else ifeq ($(COIN_CXX_IS_CL), TRUE) LIBS = -link -libpath:`$(CYGPATH_W) @abs_lib_dir@` libCbcSolver.lib libCbc.lib libOsiCbc.lib @CBCLIB_LIBS_INSTALLED@ else LIBS = -L@abs_lib_dir@ -lCbcSolver -lCbc -lOsiCbc @CBCLIB_LIBS_INSTALLED@ endif endif # The following is necessary under cygwin, if native compilers are used CYGPATH_W = @CYGPATH_W@ # Here we list all possible generated objects or executables to delete them CLEANFILES = $(EXTRAOBJS) \ allCuts.@OBJEXT@ allCuts@EXEEXT@ \ barrier.@OBJEXT@ barrier@EXEEXT@ \ cbc_driverC_sos.@OBJEXT@ cbc_driverC_sos@EXEEXT@ \ crew.@OBJEXT@ crew@EXEEXT@ \ driver.@OBJEXT@ driver@EXEEXT@ \ driver2.@OBJEXT@ driver2@EXEEXT@ \ driver3.@OBJEXT@ driver3@EXEEXT@ \ driver4.@OBJEXT@ driver4@EXEEXT@ \ fast0507b.@OBJEXT@ fast0507b@EXEEXT@ \ fast0507.@OBJEXT@ fast0507@EXEEXT@ \ gear.@OBJEXT@ gear@EXEEXT@ \ hotstart.@OBJEXT@ hotstart@EXEEXT@ \ interrupt.@OBJEXT@ interrupt@EXEEXT@ \ link.@OBJEXT@ link@EXEEXT@ \ longthin.@OBJEXT@ longthin@EXEEXT@ \ lotsize.@OBJEXT@ lotsize@EXEEXT@ \ minimum.@OBJEXT@ minimum@EXEEXT@ \ modify.@OBJEXT@ modify@EXEEXT@ \ nway.@OBJEXT@ nway@EXEEXT@ \ qmip.@OBJEXT@ qmip@EXEEXT@ \ qmip2.@OBJEXT@ qmip2@EXEEXT@ \ repeat.@OBJEXT@ repeat@EXEEXT@ \ sample1.@OBJEXT@ sample1@EXEEXT@ \ sample2.@OBJEXT@ sample2@EXEEXT@ \ sample3.@OBJEXT@ sample3@EXEEXT@ \ sample4.@OBJEXT@ sample4@EXEEXT@ \ sample5.@OBJEXT@ sample5@EXEEXT@ \ simpleBAB.@OBJEXT@ simpleBAB@EXEEXT@ \ sos.@OBJEXT@ sos@EXEEXT@ \ sudoku.@OBJEXT@ sudoku@EXEEXT@ all: $(EXE) .SUFFIXES: .cpp .c .o .obj $(EXE): $(OBJS) $(EXTRAOBJS) bla=;\ for file in $(OBJS) $(EXTRAOBJS); do bla="$$bla `$(CYGPATH_W) $$file`"; done; \ $(CXX) $(CXXLINKFLAGS) $(CXXFLAGS) -o $@ $$bla $(LIBS) $(ADDLIBS) clean: rm -rf $(CLEANFILES) $(OBJS) .cpp.o: $(CXX) $(CXXFLAGS) $(INCL) -c -o $@ `test -f '$<' || echo '$(SRCDIR)/'`$< .cpp.obj: $(CXX) $(CXXFLAGS) $(INCL) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(SRCDIR)/$<'; fi` .c.o: $(CC) $(CFLAGS) $(INCL) -c -o $@ `test -f '$<' || echo '$(SRCDIR)/'`$< .c.obj: $(CC) $(CFLAGS) $(INCL) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(SRCDIR)/$<'; fi` Cbc-2.8.12/examples/parallel.cpp0000644000076600007660000001613412254317402015074 0ustar coincoin// $Id: parallel.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include "CoinPragma.hpp" #include "CbcModel.hpp" #include "OsiClpSolverInterface.hpp" #include "CbcSolver.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program shows how to take advantage of the standalone cbc in your program, while still making major modifications. This is like driver4 but executes in parallel First it reads in a model from an mps file Then it initializes three integer models with cbc defaults Then it calls CbcMain0/1 using threads passing parameters Finally it prints solution (just for first model) All models have same parameters unless "-switch" is found so -- miplib/p0033 -solve -switch -heuristic off -solve would solve first model with heuristics and subsequent ones without This could be used to try different ideas OR on different models NOTE - The minimum has been done to make thread safe so no interrupts -quit is added to make sure just reads from argv */ /*************************************************************************/ #define USE_PTHREAD #ifdef USE_PTHREAD #include #endif /* Return non-zero to return quickly */ static int callBack(CbcModel * model, int whereFrom) { int returnCode=0; switch (whereFrom) { case 1: case 2: if (!model->status()&&model->secondaryStatus()) returnCode=1; break; case 3: { //CbcCompareUser compare; //model->setNodeComparison(compare); } break; case 4: // If not good enough could skip postprocessing break; case 5: break; default: abort(); } return returnCode; } // For threads typedef struct { CbcModel * model; CbcSolverUsefulData * data; int argc; char ** argv; } threadStuff; static void * doThread(void * voidInfo) { threadStuff * stuff = reinterpret_cast(voidInfo); CbcModel * model = stuff->model; CbcMain0(*model,*stuff->data); // Now go into code for standalone solver CbcMain1(stuff->argc,const_cast(stuff->argv), *model,callBack,*stuff->data); return NULL; } int main (int argc, const char *argv[]) { // Number of models to do at once int numberModels=3; // Stuff for each model CbcModel * allModels = new CbcModel[numberModels]; OsiClpSolverInterface * allSolvers = new OsiClpSolverInterface[numberModels]; CbcSolverUsefulData * data = new CbcSolverUsefulData[numberModels]; threadStuff * allData = new threadStuff[numberModels]; // First populate first model /* in a real application models would be different */ OsiClpSolverInterface & solver1 = allSolvers[0]; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } // Tell solver to return fast if presolve or initial solve infeasible solver1.getModelPtr()->setMoreSpecialOptions(3); // create models for (int iModel=1;iModel0) lastArgc=thisArgc; else thisArgc=lastArgc; // allow extra for -quit char ** thisArgv=new char *[thisArgc+2]; thisArgv[0]=strdup(argv[0]); int put=1; for (int iArgc=lastArgPosition;iArgcsolver(); // Print solution if finished (could get from model->bestSolution() as well if (model->bestSolution()) { const double * solution = solver->getColSolution(); int iColumn; int numberColumns = solver->getNumCols(); std::cout<1.0e-7&&solver->isInteger(iColumn)) std::cout<getColName(iColumn) <1.0e-7&&solver->isInteger(iColumn)) std::cout<columnName(iColumn) < #include #include //#define CBC_DEBUG #include "CoinPragma.hpp" #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchFollow2.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" // Default Constructor CbcFollowOn2::CbcFollowOn2 () : CbcObject(), rhs_(NULL), maximumRhs_(1) { } // Useful constructor CbcFollowOn2::CbcFollowOn2 (CbcModel * model) : CbcObject(model) { assert (model); OsiSolverInterface * solver = model_->solver(); matrix_ = *solver->getMatrixByCol(); matrix_.removeGaps(); matrixByRow_ = *solver->getMatrixByRow(); int numberRows = matrix_.getNumRows(); maximumRhs_ =1; rhs_ = new int[numberRows]; int i; const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); for (i=0;i=1.0&&value<100.0) { // check elements bool good=true; for (int j=rowStart[i];jisInteger(iColumn)) good=false; double elValue = elementByRow[j]; if (floor(elValue)!=elValue||elValue<1.0) good=false; } if (good) rhs_[i]=(int) value; } } } } // Copy constructor CbcFollowOn2::CbcFollowOn2 ( const CbcFollowOn2 & rhs) :CbcObject(rhs), matrix_(rhs.matrix_), matrixByRow_(rhs.matrixByRow_), maximumRhs_(rhs.maximumRhs_) { int numberRows = matrix_.getNumRows(); rhs_= CoinCopyOfArray(rhs.rhs_,numberRows); } // Clone CbcObject * CbcFollowOn2::clone() const { return new CbcFollowOn2(*this); } // Assignment operator CbcFollowOn2 & CbcFollowOn2::operator=( const CbcFollowOn2& rhs) { if (this!=&rhs) { CbcObject::operator=(rhs); delete [] rhs_; matrix_ = rhs.matrix_; matrixByRow_ = rhs.matrixByRow_; int numberRows = matrix_.getNumRows(); rhs_= CoinCopyOfArray(rhs.rhs_,numberRows); maximumRhs_ = rhs.maximumRhs_; } return *this; } // Destructor CbcFollowOn2::~CbcFollowOn2 () { delete [] rhs_; } /* As some computation is needed in more than one place - returns row. Also returns other row and effective rhs (so we can know if cut) */ int CbcFollowOn2::gutsOfFollowOn2(int & otherRow, int & preferredWay, int & effectiveRhs) const { int whichRow=-1; otherRow=-1; int numberRows = matrix_.getNumRows(); int i; // For sorting int * sort = new int [numberRows]; int * isort = new int [numberRows]; // Column copy //const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); const double * solution = solver->getColSolution(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); int nSort=0; for (i=0;iintegerTolerance) numberUnsatisfied++; } else { rhsValue -= (int)(value*floor(solValue+0.5)); } } if (numberUnsatisfied>1) { if (smallestrhsValue) printf("could fix\n"); if (number1==1&&largest==rhsValue) printf("could fix\n"); #endif if (rhsValue<=maximumRhs_&&0) { // will mean a cut but worth trying sort[nSort]=i; isort[nSort++]=100000-numberUnsatisfied; } } else if (largest==rhsValue) { sort[nSort]=i; isort[nSort++]=-numberUnsatisfied; } } } } if (nSort>1) { CoinSort_2(isort,isort+nSort,sort); assert (isort[1]<0); CoinZeroN(isort,numberRows); double * other = new double[numberRows]; CoinZeroN(other,numberRows); int * which = new int[numberRows]; //#define COUNT #ifndef COUNT bool beforeSolution = model_->getSolutionCount()==0; #endif for (int k=0;kintegerTolerance) { numberUnsatisfied++; for (int jj=columnStart[iColumn];jj>1; int best=numberUnsatisfied; #else double best; if (beforeSolution) best=dtarget; else best=1.0e30; #endif for (j=0;jbest) { best = fabs(dvalue-dtarget); iBest=iRow; if (dvalue=0) { whichRow=i; otherRow=iBest; //printf("Rows %d (%d) and %d (%d)\n",whichRow,rhs_[whichRow], // otherRow,rhs_[otherRow]); break; } } delete [] which; delete [] other; } delete [] sort; delete [] isort; return whichRow; } // Infeasibility - large is 0.5 double CbcFollowOn2::infeasibility(int & preferredWay) const { int otherRow=0; int effectiveRhs; int whichRow = gutsOfFollowOn2(otherRow,preferredWay,effectiveRhs); if (whichRow<0) { return 0.0; } else { assert (whichRow!=otherRow); return 2.0* model_->getDblParam(CbcModel::CbcIntegerTolerance); } } // This looks at solution and sets bounds to contain solution void CbcFollowOn2::feasibleRegion() { } // Creates a branching object CbcBranchingObject * CbcFollowOn2::createBranch(int way) { int otherRow=0; int preferredWay; int effectiveRhs; int whichRow = gutsOfFollowOn2(otherRow,preferredWay,effectiveRhs); assert(way==preferredWay); assert (whichRow>=0); int numberColumns = matrix_.getNumCols(); // Column copy //const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Row copy //const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); //const double * solution = solver->getColSolution(); #if 0 //printf("Rows %d (%d) and %d (%d)\n",whichRow,rhs_[whichRow], // otherRow,rhs_[otherRow]); int nFree=0; int nOut=0; int nImplicit=0; int i; int rhsx[100]; double * colUpper2 = new double [numberColumns]; memcpy(rhsx,rhs_,matrix_.getNumRows()*sizeof(int)); for ( i=0;i1.0e-5) { nonzero=true; //printf("column %d value %g ",i,solution[i]); for (int jj=columnStart[i];jjrhsx[iRow]) fixed=true; } if (fixed) { nImplicit++; colUpper2[i]=0.0; if (nonzero) nFixedBut++; assert (!columnLower[i]); } } } // See if anything odd char * check = new char[numberColumns]; memset(check,0,numberColumns); int * which2 = new int[numberColumns]; int numberRows=matrix_.getNumRows(); for (i=0;i=nn) abort(); } else if (nnsame==nn&&nn2>nn) { printf("row %d strict superset of row %d, fix some in row %d\n", k,i,k); } } } for (k=0;k #include #include "CoinPragma.hpp" #include "OsiClpSolverInterface.hpp" #include "CoinPackedVector.hpp" //#define USE_CBC #ifdef USE_CBC #include "CbcModel.hpp" #endif int main (int argc, const char *argv[]) { OsiClpSolverInterface model; int start[] = { 0, 1, 2}; int index[] = { 0, 0}; double values[] = {1.0, 2.0}; double collb[] = {0.0, 0.0}; double colub[] = {10.0, 10.0}; double obj[] = { 1.0, 1.0}; double rowlb[] = { 0.0}; double rowub[]= { 3.9}; // obj: Max x0 + x1 // st. x0 + 2 x1 <= 3.9 // 0 <= x0 <= 10 and integer // 0 <= x1 <= 10 model.loadProblem(2, 1, start, index, values, collb, colub, obj, rowlb, rowub); model.setInteger(0); model.setObjSense(-1.0); //bool optimal; #ifndef USE_CBC // Save bounds - that and dual limit should be all that is needed // For this simple example we could just re-use collb and colub double saveLower[2]; double saveUpper[2]; int numberColumns = model.getNumCols(); CoinCopyN(model.getColLower(),numberColumns,saveLower); CoinCopyN(model.getColUpper(),numberColumns,saveUpper); double objLimit; model.getDblParam(OsiDualObjectiveLimit,objLimit); model.branchAndBound(); //optimal = model.isProvenOptimal(); const double *val = model.getColSolution(); // x0 = 3, x1 = 0.45 printf("Solution %g %g\n",val[0],val[1]); // Restore bounds and dual limit model.setColLower(saveLower); model.setColUpper(saveUpper); model.setDblParam(OsiDualObjectiveLimit,objLimit); #else { CbcModel model2(model); model2.branchAndBound(); //optimal = model2.isProvenOptimal(); const double *val = model2.getColSolution(); // x0 = 3, x1 = 0.45 printf("Solution %g %g\n",val[0],val[1]); } #endif const int rowCols[] = {0}; const double rowElements = { 1.0}; // add x0 <= 2, and solve once again. CoinPackedVector v(1, rowCols, rowElements); model.addRow(v, 0.0, 2.0); #ifndef USE_CBC model.branchAndBound(); //optimal = model.isProvenOptimal(); // should be x0 = 2, x1 = 0.95 // Address of solution will be same as only adding rows - but be safe val = model.getColSolution(); printf("Solution %g %g\n",val[0],val[1]); #else { CbcModel model2(model); model2.branchAndBound(); //optimal = model2.isProvenOptimal(); // should be x0 = 2, x1 = 0.95 const double *val = model2.getColSolution(); printf("Solution %g %g\n",val[0],val[1]); } #endif return 0; } Cbc-2.8.12/examples/sudoku.cpp0000644000076600007660000003473512131315050014610 0ustar coincoin// $Id: sudoku.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CoinModel.hpp" // For all different #include "CbcBranchCut.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchAllDifferent.hpp" #include "CbcCutGenerator.hpp" #include "CglAllDifferent.hpp" #include "OsiClpSolverInterface.hpp" #include "CglStored.hpp" #include "CoinTime.hpp" /************************************************************************ This shows how we can define a new branching method to solve problems with all different constraints. We are going to solve a sudoku problem such as 1, , ,4, , ,7, , ,2, , ,5, , ,8, 8,7,3, , ,6, , ,9 4, , ,7, , ,1, , ,5, , ,8, , ,2, , ,6, ,4,9, , ,3 7, , ,1, , ,4, , ,8, ,6,2, , ,5, , ,9, ,7,3, ,1,6 The input should be exported from spreadsheet as a csv file where cells are empty unless value is known. We set up a fake objective and simple constraints to say sum must be 45 and then we add all different branching (CbcBranchAllDifferent) and all different cuts (to fix variables) (CglAllDifferent). CbcBranchAllDifferent is really just an example of a cut branch. If we wish to stop x==y then we can have two branches - one x <= y-1 and the other x >= y+1. It should be easy for the user to make up similar cut branches for other uses. Note - this is all we need to solve most 9 x 9 puzzles because they seem to solve at root node or easily. To solve 16 x 16 puzzles we need more. All different cuts need general integer variables to be fixed while we can branch so they are just at bounds. To get round that we can introduce extra 0-1 variables such that general integer x = sum j * delta j and then do N way branching on these (CbcNWay) so that we fix one delta j to 1. At the same time we use the new class CbcConsequence (used in N way branching) which when delta j goes to 1 fixes other variables. So it will fix x to the correct value and while we are at it we can fix some delta variables in other sets to zero (as per all different rules). Finally as well as storing the instructions which say if delta 11 is 1 then delta 21 is 0 we can also add this in as a cut using new trivial cut class CglStored. ************************************************************************/ int main (int argc, const char *argv[]) { // Get data std::string fileName = "./sudoku_sample.csv"; if (argc>=2) fileName = argv[1]; FILE * fp = fopen(fileName.c_str(),"r"); if (!fp) { printf("Unable to open file %s\n",fileName.c_str()); exit(0); } #define MAX_SIZE 16 int valueOffset=1; double lo[MAX_SIZE*MAX_SIZE],up[MAX_SIZE*MAX_SIZE]; char line[80]; int row,column; /*************************************** Read .csv file and see if 9 or 16 Su Doku ***************************************/ int size=9; for (row=0;row=32) { if (line[get]==',') size++; get++; } assert (size==9||size==16); printf("Solving Su Doku of size %d\n",size); if (size==16) valueOffset=0; } int get=0; for (column=0;column=32) { // skip blanks if (line[get]==' ') { get++; continue; } int value = line[get]-'0'; if (size==9) { assert (value>=1&&value<=9); } else { assert (size==16); if (value<0||value>9) { if (line[get]=='"') { get++; value = 10 + line[get]-'A'; if (value<10||value>15) { value = 10 + line[get]-'a'; } get++; } else { value = 10 + line[get]-'A'; if (value<10||value>15) { value = 10 + line[get]-'a'; } } } assert (value>=0&&value<=15); } lo[size*row+column]=value; up[size*row+column]=value; get++; } get++; } } int block_size = (int) sqrt ((double) size); /*************************************** Now build rules for all different 3*9 or 3*16 sets of variables Number variables by row*size+column ***************************************/ int starts[3*MAX_SIZE+1]; int which[3*MAX_SIZE*MAX_SIZE]; int put=0; int set=0; starts[0]=0; // By row for (row=0;rowsetHintParam(OsiDoReducePrint,true,OsiHintTry); model.solver()->setHintParam(OsiDoScale,false,OsiHintTry); /*************************************** Add in All different cut generator and All different branching So we will have integers then cut branching then N way branching in reverse priority order ***************************************/ // Cut generator CglAllDifferent allDifferent(3*size,starts,which); model.addCutGenerator(&allDifferent,-99,"allDifferent"); model.cutGenerator(0)->setWhatDepth(5); CbcObject ** objects = new CbcObject * [4*size*size]; int nObj=0; for (row=0;row<3*size;row++) { int iStart = starts[row]; objects[row]= new CbcBranchAllDifferent(&model,size,which+iStart); objects[row]->setPriority(2000+nObj); // do after rest satisfied nObj++; } /*************************************** Add in N way branching and while we are at it add in cuts ***************************************/ CglStored stored; for (row=0;rowsetConsequence(indices[i],fix); // Now do as cuts for (int kk=1;kkkColumn) { cutInd[1]=jColumn; stored.addCut(-COIN_DBL_MAX,1.0,2,cutInd,values); } } } objects[nObj]= obj; objects[nObj]->setPriority(nObj); nObj++; } } model.addObjects(nObj,objects); for (row=0;rowsetLogLevel(1); model.addCutGenerator(&stored,1,"stored"); // Say we want timings int numberGenerators = model.numberCutGenerators(); int iGenerator; for (iGenerator=0;iGeneratorsetTiming(true); } // Set this to get all solutions (all ones in newspapers should only have one) //model.setCutoffIncrement(-1.0e6); /*************************************** Do branch and bound ***************************************/ // Do complete search model.branchAndBound(); std::cout<<"took "<=lo[put]&&value<=up[put]); // save for later test lo[put++]=value; printf("%d ",value); } printf("\n"); } // check valid bool valid=true; // By row for (row=0;row #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchUser.hpp" #include "CbcCompareUser.hpp" #include "CbcCutGenerator.hpp" #include "CbcStrategy.hpp" #include "CbcHeuristicLocal.hpp" #include "OsiClpSolverInterface.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglRedSplit.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding2.hpp" // Preprocessing #include "CglPreProcess.hpp" // For saying about solution validity #include "OsiAuxInfo.hpp" // Heuristics (But any will have to be special) #include "CbcHeuristic.hpp" #include "CoinTime.hpp" // Need stored cuts #include "CglStored.hpp" /** Stored Cut Generator Class */ class CglStoredUser : public CglStored { public: /**@name Generate Cuts */ //@{ /** Generate Mixed Integer Stored cuts for the model of the solver interface, si. Insert the generated cuts into OsiCut, cs. This generator just looks at previously stored cuts and inserts any that are violated by enough */ virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo info = CglTreeInfo()) const; //@} /**@name Cut stuff */ //@{ OsiRowCut * mutableRowCutPointer(int index) { return cuts_.rowCutPtr(index);} //@} /**@name Constructors and destructors */ //@{ /// Default constructor CglStoredUser (); /// Copy constructor CglStoredUser (const CglStoredUser & rhs); /// Clone virtual CglCutGenerator * clone() const; /// Assignment operator CglStoredUser & operator=(const CglStoredUser& rhs); /// Destructor virtual ~CglStoredUser (); //@} protected: // Protected member methods // Protected member data /**@name Protected member data */ //@{ /** Don't add any more cuts after this number passes (per node) unless looks integer feasible */ int numberPasses_; //@} }; //------------------------------------------------------------------- // Generate Stored cuts //------------------------------------------------------------------- void CglStoredUser::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo info) const { // Get basic problem information const double * solution = si.getColSolution(); if (info.inTree&&info.pass>numberPasses_) { // only continue if integer feasible int numberColumns=si.getNumCols(); int i; const double * colUpper = si.getColUpper(); const double * colLower = si.getColLower(); int numberAway=0; for (i=0;i1.0e-5) numberAway++; } if (numberAway) return; // let code branch } int numberRowCuts = cuts_.sizeRowCuts(); for (int i=0;iviolated(solution); if (violation>=requiredViolation_) cs.insert(*rowCutPointer); } } //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CglStoredUser::CglStoredUser () : CglStored(), numberPasses_(5) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CglStoredUser::CglStoredUser (const CglStoredUser & source) : CglStored(source), numberPasses_(source.numberPasses_) { } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- CglCutGenerator * CglStoredUser::clone() const { return new CglStoredUser(*this); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CglStoredUser::~CglStoredUser () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CglStoredUser & CglStoredUser::operator=(const CglStoredUser& rhs) { if (this != &rhs) { CglStored::operator=(rhs); numberPasses_=rhs.numberPasses_; } return *this; } // Class to disallow strong branching solutions #include "CbcFeasibilityBase.hpp" class CbcFeasibilityNoStrong : public CbcFeasibilityBase{ public: // Default Constructor CbcFeasibilityNoStrong () {}; virtual ~CbcFeasibilityNoStrong() {}; // Copy constructor CbcFeasibilityNoStrong ( const CbcFeasibilityNoStrong &rhs) {}; // Assignment operator CbcFeasibilityNoStrong & operator=( const CbcFeasibilityNoStrong& rhs) { return * this;}; /// Clone virtual CbcFeasibilityBase * clone() const { return new CbcFeasibilityNoStrong();}; /** On input mode: 0 - called after a solve but before any cuts -1 - called after strong branching Returns : 0 - no opinion -1 pretend infeasible 1 pretend integer solution */ virtual int feasible(CbcModel * model, int mode) {return mode;}; }; //############################################################################# /************************************************************************ This main program reads in an integer model from an mps file. It makes L or G rows into cuts ************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); OsiClpSolverInterface solverSave = solver1; /* Options are: preprocess to do preprocessing time in minutes if 2 parameters and numeric taken as time */ bool preProcess=false; double minutes=-1.0; int nGoodParam=0; for (int iParam=2; iParam=0.0) { nGoodParam+=2; iParam++; // skip time } } } } if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) { // If time is given then stop after that number of minutes minutes = atof(argv[2]); if (minutes>=0.0) nGoodParam=1; } if (nGoodParam!=argc-2&&argc>=2) { printf("Usage [preprocess] [time ] or \n"); exit(1); } // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); // See if we want preprocessing OsiSolverInterface * solver2=&solver1; CglPreProcess process; // Never do preprocessing until dual tests out as can fix incorrectly preProcess=false; if (preProcess) { /* Do not try and produce equality cliques and do up to 5 passes */ solver2 = process.preProcess(solver1,false,5); if (!solver2) { printf("Pre-processing says infeasible\n"); exit(2); } solver2->resolve(); } // Turn L rows into cuts CglStoredUser stored; { int numberRows = solver2->getNumRows(); int * whichRow = new int[numberRows]; // get row copy const CoinPackedMatrix * rowCopy = solver2->getMatrixByRow(); const int * column = rowCopy->getIndices(); const int * rowLength = rowCopy->getVectorLengths(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const double * rowLower = solver2->getRowLower(); const double * rowUpper = solver2->getRowUpper(); const double * element = rowCopy->getElements(); int iRow,nDelete=0; for (iRow=0;iRow1.0e20) { // take out whichRow[nDelete++]=iRow; } } // leave some rows to avoid empty problem (Gomory does not like) nDelete = CoinMax(CoinMin(nDelete,numberRows-5),0); for (int jRow=0;jRowsetEffectiveness(1.0e50); } solver2->deleteRows(nDelete,whichRow); delete [] whichRow; } CbcModel model(*solver2); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(1); generator1.setMaxPassRoot(5); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); generator1.setMaxProbeRoot(1000); // How far to follow the consequences generator1.setMaxLook(50); generator1.setMaxLookRoot(500); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglRedSplit generator4; // try larger limit generator4.setLimit(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding2 mixedGen; CglFlowCover flowGen; // Add in generators // Experiment with -1 and -99 etc // This is just for one particular model model.addCutGenerator(&generator1,-1,"Probing"); //model.addCutGenerator(&generator2,-1,"Gomory"); model.addCutGenerator(&generator2,1,"Gomory"); model.addCutGenerator(&generator3,-1,"Knapsack"); // model.addCutGenerator(&generator4,-1,"RedSplit"); //model.addCutGenerator(&generator5,-1,"Clique"); model.addCutGenerator(&generator5,1,"Clique"); model.addCutGenerator(&flowGen,-1,"FlowCover"); model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); // Add stored cuts (making sure at all depths) model.addCutGenerator(&stored,1,"Stored",true,false,false,-100,1,-1); int numberGenerators = model.numberCutGenerators(); int iGenerator; // Say we want timings for (iGenerator=0;iGeneratorsetTiming(true); } OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver()); // go faster stripes if (osiclp) { if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) { //osiclp->setupForRepeatedUse(2,0); osiclp->setupForRepeatedUse(0,0); } // Don't allow dual stuff osiclp->setSpecialOptions(osiclp->specialOptions()|262144); } // Uncommenting this should switch off all CBC messages // model.messagesPointer()->setDetailMessages(10,10000,NULL); // No heuristics // Do initial solve to continuous model.initialSolve(); /* You need the next few lines - a) so that cut generator will always be called again if it generated cuts b) it is known that matrix is not enough to define problem so do cuts even if it looks integer feasible at continuous optimum. c) a solution found by strong branching will be ignored. d) don't recompute a solution once found */ // Make sure cut generator called correctly (a) iGenerator=numberGenerators-1; model.cutGenerator(iGenerator)->setMustCallAgain(true); // Say cuts needed at continuous (b) OsiBabSolver oddCuts; oddCuts.setSolverType(4); // owing to bug must set after initialSolve model.passInSolverCharacteristics(&oddCuts); // Say no to all solutions by strong branching (c) CbcFeasibilityNoStrong noStrong; model.setProblemFeasibility(noStrong); // Say don't recompute solution d) model.setSpecialOptions(4); // Could tune more double objValue = model.solver()->getObjSense()*model.solver()->getObjValue(); double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4); double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4; printf("min drop %g (A %g)\n",minimumDrop,minimumDropA); model.setMinimumDrop(minimumDrop); if (model.getNumCols()<500) model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (model.getNumCols()<5000) model.setMaximumCutPassesAtRoot(100); // use minimum drop else model.setMaximumCutPassesAtRoot(20); model.setMaximumCutPasses(10); //model.setMaximumCutPasses(2); // Switch off strong branching if wanted // model.setNumberStrong(0); // Do more strong branching if small if (model.getNumCols()<5000) model.setNumberStrong(10); model.setNumberStrong(20); //model.setNumberStrong(5); model.setNumberBeforeTrust(5); model.solver()->setIntParam(OsiMaxNumIterationHotStart,100); // If time is given then stop after that number of minutes if (minutes>=0.0) { std::cout<<"Stopping after "<setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } //model.messageHandler()->setLogLevel(2); //model.solver()->messageHandler()->setLogLevel(2); //model.setPrintFrequency(50); //#define DEBUG_CUTS #ifdef DEBUG_CUTS // Set up debugger by name (only if no preprocesing) if (!preProcess) { std::string problemName ; model.solver()->getStrParam(OsiProbName,problemName) ; model.solver()->activateRowCutDebugger(problemName.c_str()) ; } #endif // Do complete search model.branchAndBound(); std::cout<cutGeneratorName()<<" was tried " <numberTimesEntered()<<" times and created " <numberCutsInTotal()<<" cuts of which " <numberCutsActive()<<" were active after adding rounds of cuts"; if (generator->timing()) std::cout<<" ( "<timeInCutGenerator()<<" seconds)"<getNumCols(); const double * solution = solver->getColSolution(); // Get names from solver1 (as OsiSolverInterface may lose) std::vector columnNames = *solver1.getModelPtr()->columnNames(); int iColumn; std::cout<1.0e-7&&solver->isInteger(iColumn)) { std::cout< #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchUser.hpp" #include "CbcBranchFollow2.hpp" #include "CbcCompareUser.hpp" #include "CbcCutGenerator.hpp" #include "CbcHeuristicGreedy.hpp" #include "OsiClpSolverInterface.hpp" #include "CbcSolver2.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglOddHole.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding.hpp" #include "CglMixedIntegerRounding2.hpp" // Preprocessing #include "CglPreProcess.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program reads in an integer model from an mps file. It then sets up some Cgl cut generators and calls branch and cut. Branching is simple binary branching on integer variables. Node selection is depth first until first solution is found and then based on objective and number of unsatisfied integer variables. In this example the functionality is the same as default but it is a user comparison function. Variable branching selection is on maximum minimum-of-up-down change after strong branching on 5 variables closest to 0.5. A simple rounding heuristic is used. ************************************************************************/ // ****** define comparison to choose best next node int main (int argc, const char *argv[]) { // Define your favorite OsiSolver #ifdef COIN_USE_CLPxx OsiClpSolverInterface solver1; #else CbcSolver2 solver1; #endif // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); /* Options are: preprocess to do preprocessing time in minutes if 2 parameters and numeric taken as time */ bool preProcess=false; double minutes=-1.0; int nGoodParam=0; for (int iParam=2; iParam=0.0) { nGoodParam+=2; iParam++; // skip time } } } } if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) { // If time is given then stop after that number of minutes minutes = atof(argv[2]); if (minutes>=0.0) nGoodParam=1; } if (nGoodParam!=argc-2) { printf("Usage [preprocess] [time ] or \n"); exit(1); } solver1.initialSolve(); // Reduce printout //solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); // Say we want scaling //solver1.setHintParam(OsiDoScale,true,OsiHintTry); //solver1.setCleanupScaling(1); // See if we want preprocessing OsiSolverInterface * solver2=&solver1; CglPreProcess process; if (preProcess) { /* Do not try and produce equality cliques and do up to 5 passes */ solver2 = process.preProcess(solver1,false,5); if (!solver2) { printf("Pre-processing says infeasible\n"); exit(2); } solver2->resolve(); } CbcModel model(*solver2); // Point to solver OsiSolverInterface * solver3 = model.solver(); CbcSolver2 * osiclp = dynamic_cast< CbcSolver2*> (solver3); assert (osiclp); osiclp->initialize(&model,NULL); osiclp->setAlgorithm(2); int numberColumns = osiclp->getNumCols(); int * priority = new int [numberColumns+1]; int n=0; int iColumn; for ( iColumn=0;iColumnsetTiming(true); } // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // And Greedy heuristic CbcHeuristicGreedyCover heuristic2(model); // Use original upper and perturb more heuristic2.setAlgorithm(0); heuristic2.setWhen(13); // say do even though looks odd (nObjects>nInts) model.addHeuristic(&heuristic2); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); // Do initial solve to continuous model.initialSolve(); // Could tune more model.setMinimumDrop(CoinMin(1.0, fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4)); if (model.getNumCols()<500) model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (model.getNumCols()<5000) model.setMaximumCutPassesAtRoot(100); // use minimum drop else model.setMaximumCutPassesAtRoot(20); //model.setMaximumCutPasses(1); // Do more strong branching if small //if (model.getNumCols()<5000) //model.setNumberStrong(10); // Switch off strong branching if wanted model.setNumberStrong(0); model.solver()->setIntParam(OsiMaxNumIterationHotStart,50); // If time is given then stop after that number of minutes if (minutes>=0.0) { std::cout<<"Stopping after "<setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } //model.messageHandler()->setLogLevel(2); //model.solver()->messageHandler()->setLogLevel(2); //model.setPrintFrequency(50); #define DEBUG_CUTS #ifdef DEBUG_CUTS // Set up debugger by name (only if no preprocesing) if (!preProcess) { std::string problemName ; //model.solver()->getStrParam(OsiProbName,problemName) ; //model.solver()->activateRowCutDebugger(problemName.c_str()) ; model.solver()->activateRowCutDebugger("cap6000a") ; } #endif // Do complete search model.branchAndBound(); //void printHowMany(); //printHowMany(); std::cout<cutGeneratorName()<<" was tried " <numberTimesEntered()<<" times and created " <numberCutsInTotal()<<" cuts of which " <numberCutsActive()<<" were active after adding rounds of cuts"; if (generator->timing()) std::cout<<" ( "<timeInCutGenerator()<<" seconds)"<getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7&&model.solver()->isInteger(iColumn)) std::cout< #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcStrategy.hpp" #include "CbcBranchUser.hpp" #include "CbcCompareUser.hpp" #include "CbcCutGenerator.hpp" #include "OsiClpSolverInterface.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglRedSplit.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding2.hpp" // Preprocessing #include "CglPreProcess.hpp" // Heuristics #include "CbcHeuristic.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program reads in an integer model from an mps file. It then sets up some Cgl cut generators and calls branch and cut. Then it uses solution as hot start ************************************************************************/ int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); /* Options are: preprocess to do preprocessing time in minutes if 2 parameters and numeric taken as time */ bool preProcess=false; double minutes=-1.0; int nGoodParam=0; for (int iParam=2; iParam=0.0) { nGoodParam+=2; iParam++; // skip time } } } } if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) { // If time is given then stop after that number of minutes minutes = atof(argv[2]); if (minutes>=0.0) nGoodParam=1; } if (nGoodParam!=argc-2&&argc>=2) { printf("Usage [preprocess] [time ] or \n"); exit(1); } //solver1.getModelPtr()->setLogLevel(0); solver1.messageHandler()->setLogLevel(0); solver1.initialSolve(); // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); CbcModel model(solver1); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(1); generator1.setMaxPassRoot(5); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); generator1.setMaxProbeRoot(1000); // How far to follow the consequences generator1.setMaxLook(50); generator1.setMaxLookRoot(500); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglRedSplit generator4; // try larger limit generator4.setLimit(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding2 mixedGen; CglFlowCover flowGen; // Add in generators // Experiment with -1 and -99 etc model.addCutGenerator(&generator1,-1,"Probing"); model.addCutGenerator(&generator2,-1,"Gomory"); model.addCutGenerator(&generator3,-1,"Knapsack"); // model.addCutGenerator(&generator4,-1,"RedSplit"); model.addCutGenerator(&generator5,-1,"Clique"); model.addCutGenerator(&flowGen,-1,"FlowCover"); model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver()); // go faster stripes if (osiclp) { // Turn this off if you get problems // Used to be automatically set osiclp->setSpecialOptions(128); if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) { //osiclp->setupForRepeatedUse(2,1); osiclp->setupForRepeatedUse(0,1); } } // Uncommenting this should switch off most CBC messages //model.messagesPointer()->setDetailMessages(10,5,5000); // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); // Do initial solve to continuous model.initialSolve(); // Could tune more double objValue = model.solver()->getObjSense()*model.solver()->getObjValue(); double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4); double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4; printf("min drop %g (A %g)\n",minimumDrop,minimumDropA); model.setMinimumDrop(minimumDrop); if (model.getNumCols()<500) model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (model.getNumCols()<5000) model.setMaximumCutPassesAtRoot(100); // use minimum drop else model.setMaximumCutPassesAtRoot(20); model.setMaximumCutPasses(10); //model.setMaximumCutPasses(2); // Switch off strong branching if wanted // model.setNumberStrong(0); // Do more strong branching if small if (model.getNumCols()<5000) model.setNumberStrong(10); model.setNumberStrong(20); //model.setNumberStrong(5); model.setNumberBeforeTrust(5); //model.setSizeMiniTree(2); model.solver()->setIntParam(OsiMaxNumIterationHotStart,100); // Switch off most output if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } model.messageHandler()->setLogLevel(6); model.solver()->messageHandler()->setLogLevel(1); // If time is given then stop after that number of minutes if (minutes>=0.0) { std::cout<<"Stopping after "<getNumCols(); double * bestSolution=NULL; int * priority = new int[numberColumns]; // Do two passes for (int iPass=0;iPass<2;iPass++) { time1 = CoinCpuTime(); // Do hot start on second pass if (bestSolution) { model.setHotstartSolution(bestSolution,priority); delete [] bestSolution; bestSolution=NULL; delete [] priority; model.setMaximumNodes(40000); } else { model.setMaximumNodes(40000); } // Do complete search model.branchAndBound(); std::cout<getNumCols(); const double * solution = solver->getColSolution(); // save solution if (!iPass) { bestSolution = CoinCopyOfArray(solution,numberColumns); for (int i=0;i0.5) priority[i]=-1; else priority[i]=2; } } //const double * lower = solver->getColLower(); //const double * upper = solver->getColUpper(); // Get names from solver1 (as OsiSolverInterface may lose) std::vector columnNames = *solver1.getModelPtr()->columnNames(); int iColumn; std::cout<1.0e-7&&solver->isInteger(iColumn)) std::cout< #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiClpSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchActual.hpp" #include "CbcCompareUser.hpp" #include "CoinTime.hpp" /************************************************************************ This main program reads in an integer model from an mps file. It expects it to be unit coefficients and unit rhs. Branching is follow-on branching plus simple binary branching on integer variables. */ int main (int argc, const char *argv[]) { // Define a Solver for long thin problems OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); solver1.initialSolve(); // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); OsiSolverInterface * solver2=&solver1; CbcModel model(*solver2); // Point to solver OsiSolverInterface * solver3 = model.solver(); assert (dynamic_cast< OsiClpSolverInterface*> (solver3)); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); int iColumn; int numberColumns = solver3->getNumCols(); /* We are going to add a single follow on object but we want to give low priority to existing integers. As the default priority is 1000 we don't actually need to give integer priorities but it is here to show how. */ // Normal integer priorities int * priority = new int [numberColumns]; int numberIntegers=0; for (iColumn=0;iColumnisInteger(iColumn)) { priority[numberIntegers++]= 100; // low priority } } /* Second parameter is true if we are adding objects, false if integers. So this does integers */ model.passInPriorities(priority,false); delete [] priority; /* Add in objects before we can give priority. In this case just one - but this shows general method */ CbcObject ** objects = new CbcObject * [1]; objects[0]=new CbcFollowOn(&model); model.addObjects(1,objects); delete objects[0]; delete [] objects; // High priority int followPriority=1; model.passInPriorities(&followPriority,true); // Do initial solve to continuous model.initialSolve(); // Do more strong branching if small // Switch off strong branching if wanted model.setNumberStrong(0); model.solver()->setIntParam(OsiMaxNumIterationHotStart,100); // Switch off most output if (model.getNumCols()<3000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } //model.setPrintFrequency(50); // Do complete search try { model.branchAndBound(); } catch (CoinError e) { e.print(); if (e.lineNumber()>=0) std::cout<<"This was from a CoinAssert"<getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7&&model.solver()->isInteger(iColumn)) std::cout< #include #include "CoinPragma.hpp" // For Branch and bound #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchUser.hpp" #include "CbcBranchCut.hpp" #include "CbcBranchToFixLots.hpp" #include "CbcCompareUser.hpp" #include "CbcCutGenerator.hpp" #include "CbcHeuristicGreedy.hpp" #include "OsiClpSolverInterface.hpp" #include "CbcSolver3.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglOddHole.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding.hpp" #include "CglMixedIntegerRounding2.hpp" // Preprocessing #include "CglPreProcess.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program reads in an integer model from an mps file. It then sets up some Cgl cut generators and calls branch and cut. Branching is simple binary branching on integer variables. Node selection is depth first until first solution is found and then based on objective and number of unsatisfied integer variables. In this example the functionality is the same as default but it is a user comparison function. Variable branching selection is on maximum minimum-of-up-down change after strong branching on 5 variables closest to 0.5. A simple rounding heuristic is used. ************************************************************************/ // ****** define comparison to choose best next node int main (int argc, const char *argv[]) { CbcSolver3 solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } double time1 = CoinCpuTime(); /* Options are: preprocess to do preprocessing time in minutes if 2 parameters and numeric taken as time */ bool preProcess=false; double minutes=-1.0; int nGoodParam=0; for (int iParam=2; iParam=0.0) { nGoodParam+=2; iParam++; // skip time } } } } if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) { // If time is given then stop after that number of minutes minutes = atof(argv[2]); if (minutes>=0.0) nGoodParam=1; } if (nGoodParam!=argc-2) { printf("Usage [preprocess] [time ] or \n"); exit(1); } solver1.initialSolve(); // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); // Say we want scaling //solver1.setHintParam(OsiDoScale,true,OsiHintTry); //solver1.setCleanupScaling(1); // See if we want preprocessing OsiSolverInterface * solver2=&solver1; CglPreProcess process; if (preProcess) { /* Do not try and produce equality cliques and do up to 5 passes */ solver2 = process.preProcess(solver1,false,5); if (!solver2) { printf("Pre-processing says infeasible\n"); exit(2); } solver2->resolve(); } CbcModel model(*solver2); // Point to solver OsiSolverInterface * solver3 = model.solver(); CbcSolver3 * osiclp = dynamic_cast< CbcSolver3*> (solver3); assert (osiclp); const double fractionFix=0.985; osiclp->initialize(&model,NULL); osiclp->setAlgorithm(2); osiclp->setMemory(1000); osiclp->setNested(fractionFix); //osiclp->setNested(1.0); //off // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); // How far to follow the consequences generator1.setMaxLook(50); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglOddHole generator4; generator4.setMinimumViolation(0.005); generator4.setMinimumViolationPer(0.00002); // try larger limit generator4.setMaximumEntries(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding mixedGen; /* This is same as default constructor - (1,true,1) I presume if maxAggregate larger then slower but maybe better criterion can be 1 through 3 Reference: Hugues Marchand and Laurence A. Wolsey Aggregation and Mixed Integer Rounding to Solve MIPs Operations Research, 49(3), May-June 2001. */ int maxAggregate=1; bool multiply=true; int criterion=1; CglMixedIntegerRounding2 mixedGen2(maxAggregate,multiply,criterion); CglFlowCover flowGen; // Add in generators // Experiment with -1 and -99 etc model.addCutGenerator(&generator1,-99,"Probing"); //model.addCutGenerator(&generator2,-1,"Gomory"); //model.addCutGenerator(&generator3,-1,"Knapsack"); //model.addCutGenerator(&generator4,-1,"OddHole"); //model.addCutGenerator(&generator5,-1,"Clique"); //model.addCutGenerator(&flowGen,-1,"FlowCover"); //model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); //model.addCutGenerator(&mixedGen2,-1,"MixedIntegerRounding2"); // Say we want timings int numberGenerators = model.numberCutGenerators(); int iGenerator; for (iGenerator=0;iGeneratorsetTiming(true); } // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // And Greedy heuristic CbcHeuristicGreedyCover heuristic2(model); // Use original upper and perturb more heuristic2.setAlgorithm(11); model.addHeuristic(&heuristic2); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); int iColumn; int numberColumns = solver3->getNumCols(); // do pseudo costs CbcObject ** objects = new CbcObject * [numberColumns+1]; const CoinPackedMatrix * matrix = solver3->getMatrixByCol(); // Column copy const int * columnLength = matrix->getVectorLengths(); const double * objective = model.getObjCoefficients(); int n=0; for (iColumn=0;iColumnisInteger(iColumn)) { double costPer = objective[iColumn]/ ((double) columnLength[iColumn]); CbcSimpleIntegerPseudoCost * newObject = new CbcSimpleIntegerPseudoCost(&model,n,iColumn, costPer,costPer); newObject->setMethod(3); objects[n++]= newObject; } } // and special fix lots branch objects[n++]=new CbcBranchToFixLots(&model,-1.0e-6,fractionFix+0.01,1,0,NULL); model.addObjects(n,objects); for (iColumn=0;iColumnsetIntParam(OsiMaxNumIterationHotStart,100); // If time is given then stop after that number of minutes if (minutes>=0.0) { std::cout<<"Stopping after "<setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } //model.messageHandler()->setLogLevel(2); //model.solver()->messageHandler()->setLogLevel(2); //model.setPrintFrequency(50); #define DEBUG_CUTS #ifdef DEBUG_CUTS // Set up debugger by name (only if no preprocesing) if (!preProcess) { std::string problemName ; //model.solver()->getStrParam(OsiProbName,problemName) ; //model.solver()->activateRowCutDebugger(problemName.c_str()) ; model.solver()->activateRowCutDebugger("cap6000a") ; } #endif // Do complete search try { model.branchAndBound(); } catch (CoinError e) { e.print(); if (e.lineNumber()>=0) std::cout<<"This was from a CoinAssert"<cutGeneratorName()<<" was tried " <numberTimesEntered()<<" times and created " <numberCutsInTotal()<<" cuts of which " <numberCutsActive()<<" were active after adding rounds of cuts"; if (generator->timing()) std::cout<<" ( "<timeInCutGenerator()<<" seconds)"<getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<1.0e-7&&model.solver()->isInteger(iColumn)) std::cout< #include #include "CoinPragma.hpp" #include "CbcModel.hpp" #include "OsiClpSolverInterface.hpp" #include "CbcSolver.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program shows how to take advantage of the standalone cbc in your program, while still making major modifications. This is very like driver4 but allows interrupts in clp for faster stopping It would be up to user to clean up output as stopping in Clp seems to give correct results but can think it is stopping in an odd way. To make cleaner would need more events defined (in Cbc AND Clp) First it reads in an integer model from an mps file Then it initializes the integer model with cbc defaults Then it calls CbcMain1 passing all parameters apart from first but with callBack to modify stuff Finally it prints solution ************************************************************************/ /* Meaning of whereFrom: 1 after initial solve by dualsimplex etc 2 after preprocessing 3 just before branchAndBound (so user can override) 4 just after branchAndBound (before postprocessing) 5 after postprocessing */ /* Meaning of model status is as normal status -1 before branchAndBound 0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found (or check value of best solution) 1 stopped - on maxnodes, maxsols, maxtime 2 difficulties so run was abandoned (5 event user programmed event occurred) cbc secondary status of problem -1 unset (status_ will also be -1) 0 search completed with solution 1 linear relaxation not feasible (or worse than cutoff) 2 stopped on gap 3 stopped on nodes 4 stopped on time 5 stopped on user event 6 stopped on solutions 7 linear relaxation unbounded but initially check if status is 0 and secondary status is 1 -> infeasible or you can check solver status. */ /* Return non-zero to return quickly */ static int callBack(CbcModel * model, int whereFrom) { int returnCode=0; switch (whereFrom) { case 1: case 2: if (!model->status()&&model->secondaryStatus()) returnCode=1; break; case 3: { //CbcCompareUser compare; //model->setNodeComparison(compare); } break; case 4: // If not good enough could skip postprocessing break; case 5: break; default: abort(); } return returnCode; } #include "CbcEventHandler.hpp" static int cancelAsap=0; /* 0 - not yet in Cbc 1 - in Cbc with new signal handler 2 - ending Cbc */ static int statusOfCbc=0; #include "CoinSignal.hpp" static CoinSighandler_t saveSignal = static_cast (0); extern "C" { static void #if defined(_MSC_VER) __cdecl #endif // _MSC_VER signal_handler(int /*whichSignal*/) { cancelAsap=3; return; } } /** This is so user can trap events and do useful stuff. CbcModel model_ is available as well as anything else you care to pass in */ class MyEventHandler3 : public CbcEventHandler { public: /**@name Overrides */ //@{ virtual CbcAction event(CbcEvent whichEvent); //@} /**@name Constructors, destructor etc*/ //@{ /** Default constructor. */ MyEventHandler3(); /// Constructor with pointer to model (redundant as setEventHandler does) MyEventHandler3(CbcModel * model); /** Destructor */ virtual ~MyEventHandler3(); /** The copy constructor. */ MyEventHandler3(const MyEventHandler3 & rhs); /// Assignment MyEventHandler3& operator=(const MyEventHandler3 & rhs); /// Clone virtual CbcEventHandler * clone() const ; //@} protected: // data goes here }; //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- MyEventHandler3::MyEventHandler3 () : CbcEventHandler() { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- MyEventHandler3::MyEventHandler3 (const MyEventHandler3 & rhs) : CbcEventHandler(rhs) { } // Constructor with pointer to model MyEventHandler3::MyEventHandler3(CbcModel * model) : CbcEventHandler(model) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- MyEventHandler3::~MyEventHandler3 () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- MyEventHandler3 & MyEventHandler3::operator=(const MyEventHandler3& rhs) { if (this != &rhs) { CbcEventHandler::operator=(rhs); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- CbcEventHandler * MyEventHandler3::clone() const { return new MyEventHandler3(*this); } CbcEventHandler::CbcAction MyEventHandler3::event(CbcEvent whichEvent) { if(!statusOfCbc) { // override signal handler // register signal handler saveSignal = signal(SIGINT, signal_handler); statusOfCbc=1; } if ( (cancelAsap&2)!=0 ) { printf("Cbc got cancel\n"); // switch off Clp cancel cancelAsap &= 2; return stop; } // If in sub tree carry on if (!model_->parentModel()) { if (whichEvent==endSearch&&statusOfCbc==1) { // switch off cancel cancelAsap=0; // restore signal handler signal(SIGINT, saveSignal); statusOfCbc=2; } if (whichEvent==solution||whichEvent==heuristicSolution) { #ifdef STOP_EARLY return stop; // say finished #else #ifdef WANT_SOLUTION // If preprocessing was done solution will be to processed model int numberColumns = model_->getNumCols(); const double * bestSolution = model_->bestSolution(); assert (bestSolution); printf("value of solution is %g\n",model_->getObjValue()); for (int i=0;i1.0e-8) printf("%d %g\n",i,bestSolution[i]); } #endif return noAction; // carry on #endif } else { return noAction; // carry on } } else { return noAction; // carry on } } /** This is so user can trap events and do useful stuff. ClpSimplex model_ is available as well as anything else you care to pass in */ class MyEventHandler4 : public ClpEventHandler { public: /**@name Overrides */ //@{ virtual int event(Event whichEvent); //@} /**@name Constructors, destructor etc*/ //@{ /** Default constructor. */ MyEventHandler4(); /// Constructor with pointer to model (redundant as setEventHandler does) MyEventHandler4(ClpSimplex * model); /** Destructor */ virtual ~MyEventHandler4(); /** The copy constructor. */ MyEventHandler4(const MyEventHandler4 & rhs); /// Assignment MyEventHandler4& operator=(const MyEventHandler4 & rhs); /// Clone virtual ClpEventHandler * clone() const ; //@} protected: // data goes here }; //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- MyEventHandler4::MyEventHandler4 () : ClpEventHandler() { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- MyEventHandler4::MyEventHandler4 (const MyEventHandler4 & rhs) : ClpEventHandler(rhs) { } // Constructor with pointer to model MyEventHandler4::MyEventHandler4(ClpSimplex * model) : ClpEventHandler(model) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- MyEventHandler4::~MyEventHandler4 () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- MyEventHandler4 & MyEventHandler4::operator=(const MyEventHandler4& rhs) { if (this != &rhs) { ClpEventHandler::operator=(rhs); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpEventHandler * MyEventHandler4::clone() const { return new MyEventHandler4(*this); } int MyEventHandler4::event(Event whichEvent) { if ( (cancelAsap&1)!=0 ) { printf("Clp got cancel\n"); return 5; } else { return -1; } } int main (int argc, const char *argv[]) { OsiClpSolverInterface solver1; //#define USE_OSI_NAMES #ifdef USE_OSI_NAMES // Say we are keeping names (a bit slower this way) solver1.setIntParam(OsiNameDiscipline,1); #endif // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } // Tell solver to return fast if presolve or initial solve infeasible solver1.getModelPtr()->setMoreSpecialOptions(3); // allow Clp to handle interrupts MyEventHandler4 clpEventHandler; solver1.getModelPtr()->passInEventHandler(&clpEventHandler); /* Two ways of doing this depending on whether NEW_STYLE_SOLVER defined. So we need pointer to model. Old way could use modelA. rather than model-> */ // Messy code below copied from CbcSolver.cpp #if NEW_STYLE_SOLVER==0 // Pass to Cbc initialize defaults CbcModel modelA(solver1); CbcModel * model = &modelA; CbcMain0(modelA); // Event handler MyEventHandler3 eventHandler; model->passInEventHandler(&eventHandler); /* Now go into code for standalone solver Could copy arguments and add -quit at end to be safe but this will do */ if (argc>2) { CbcMain1(argc-1,argv+1,modelA,callBack); } else { const char * argv2[]={"driver4","-solve","-quit"}; CbcMain1(3,argv2,modelA,callBack); } #else CbcSolver control(solver1); // initialize control.fillValuesInSolver(); // Event handler MyEventHandler3 eventHandler; CbcModel * model = control.model(); model->passInEventHandler(&eventHandler); control.solve (argc-1, argv+1, 1); #endif // Solver was cloned so get current copy OsiSolverInterface * solver = model->solver(); // Print solution if finished (could get from model->bestSolution() as well if (model->bestSolution()) { const double * solution = solver->getColSolution(); int iColumn; int numberColumns = solver->getNumCols(); std::cout<1.0e-7&&solver->isInteger(iColumn)) std::cout<getColName(iColumn) <1.0e-7&&solver->isInteger(iColumn)) std::cout<columnName(iColumn) < #include #include "CoinPragma.hpp" #include "CbcModel.hpp" #include "OsiClpSolverInterface.hpp" #include "CbcBranchDynamic.hpp" #include "CoinTime.hpp" //############################################################################# /************************************************************************ This main program shows how to take advantage of the standalone cbc in your program. It should perform very nearly the same as cbc First it reads in an integer model from an mps file and saves and strips off integer information. Then it initializes the integer model with cbc defaults Then it puts back integers - here you could do anything and also set parameters Then it calls CbcMain1 passing all parameters apart from first Finally it prints solution ************************************************************************/ int main (int argc, const char *argv[]) { OsiClpSolverInterface solver1; //#define USE_OSI_NAMES #ifdef USE_OSI_NAMES // Say we are keeping names (a bit slower this way) solver1.setIntParam(OsiNameDiscipline,1); #endif // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } // Strip off integer information and save int numberColumns = solver1.getNumCols(); char * integer = new char[numberColumns]; int i; for (i=0;isetInteger(i); } #else CbcObject ** objects = new CbcObject * [ numberColumns]; int n=0; for (i=0;i2) { CbcMain1(argc-1,argv+1,model); } else { const char * argv2[]={"driver3","-solve","-quit"}; CbcMain1(3,argv2,model); } // Print solution if finished (could get from model.bestSolution() as well if (solver->getObjValue()*solver->getObjSense()<1.0e50) { const double * solution = solver->getColSolution(); int iColumn; std::cout<1.0e-7&&solver->isInteger(iColumn)) std::cout<getColName(iColumn) <1.0e-7&&solver->isInteger(iColumn)) std::cout<columnName(iColumn) < $(addlibsdir)/cbc_addlibs.txt else if COIN_CXX_IS_CL echo "-libpath:`$(CYGPATH_W) @abs_lib_dir@` libCbc.lib @CBCLIB_LIBS_INSTALLED@" > $(addlibsdir)/cbc_addlibs.txt else echo -L@abs_lib_dir@ -lCbcSolver -lCbc @CBCLIB_LIBS_INSTALLED@ > $(addlibsdir)/cbc_addlibs.txt endif endif uninstall-hook: rm -f $(addlibsdir)/cbc_addlibs.txt ######################################################################## # Maintainer Stuff # ######################################################################## CLEANFILES = # Files that are generated and should be cleaned with make distclean DISTCLEANFILES = include BuildTools/Makemain.inc Cbc-2.8.12/CbcSourceFilesTable.csv0000644000076600007660000001425711277055727015317 0ustar coincoinFilename,Group,Person,Status,Age,CPP Lines,HPP Lines,Total Lines,libCbc,cbcSolve,cbcGeneric,Other Projects,First Object,Other Objects,Comment CbcBranchActual.cpp,Branch,Edwin,,8,5340,1823,7163,x,,,,Multiple,"CbcClique, CbcSos, CbcSimpleInteger, CbcIntegerBranchingObject, CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject, CbcSosBranchingObject, CbcBranchDefaultDecision, CbcFollowOn, CbcFixingBranchingObject, CbcNWay, CbcNWayBranchingObject, CbcFixVariable, CbcDummyBranchingObject, CbcGeneral, CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject, CbcSubProblem", CbcBranchBase.cpp,Branch,Edwin,,10,352,707,1059,x,,,,CbcObject,"CbcBranchingObject, CbcBranchDecision, CbcConsequence, CbcObjectUpdateData", CbcBranchCut.cpp,Branch,Edwin,,10,1023,315,1338,x,,,,CbcBranchCut,"CbcCutBranchingObject, CbcBranchToFixLots, CbcBranchAllDifferent", CbcBranchDynamic.cpp,Branch,Edwin,,8,1911,557,2468,x,,,,CbcSimpleIntegerDynamicPseudoCost,"CbcDynamicPseudoCostBranchingObject, CbcBranchDynamicDecision", CbcBranchLotsize.cpp,Branch,Edwin,,15,809,250,1059,x,,,,CbcLotsize,CbcLotsizeBranchingObject, CbcCbcParam.cpp,Solver,Bjarni,,24,1,,1,x,,,,"#include ""CbcOrClpParam.cpp""",, CbcCompareActual.cpp,Compare,,,8,463,165,628,x,,,,CbcCompareDepth,"CbcCompareObjective, CbcCompareDefault, CbcCompareEstimate", CbcCompareBase.hpp,Compare,,,24,,170,170,x,,,,CbcCompareBase,"CbcCompare, CbcChooseVariable", CbcConfig.h,,,,20,,102,102,x,,,,#defines,, CbcCountRowCut.cpp,,,,10,126,115,241,x,,,,CbcCountRowCut,, CbcCutGenerator.cpp,,,,2,1223,510,1733,x,,,,CbcCutGenerator,"CbcCutModifier, CbcCutSubsetModifier", CbcEventHandler.cpp,,,,36,101,221,322,x,,,,CbcEventHandler,, CbcFathom.cpp,,,,19,106,126,232,x,,,,CbcFathom,CbcOsiSolver, CbcFathomDynamicProgramming.cpp,,,,10,1051,166,1217,x,,,,CbcFathomDynamicProgramming,, CbcFeasibilityBase.hpp,,,,24,,53,53,x,,,,CbcFeasibilityBase,, CbcGenBaB.cpp,Generic,Lou,,14,886,,886,,,x,,namespace CbcGenParamUtils,namespace,The support functions for the main branch-and-cut action routine. CbcGenCbcParam.cpp,Generic,Lou,,24,155,189,344,,,x,,CbcCbcParam,,Constructors and destructors for CbcCbcParam CbcGenCbcParamUtils.cpp,Generic,Lou,,18,401,,401,,,x,,namespace CbcCbcParamUtils,,Implementation functions for CbcGenParam parameters. CbcGenCtlBlk.cpp,Generic,Lou,,24,681,948,1629,x,,x,,CbcGenCtlBlk,,Constructor for cbc-generic control block. CbcGeneric.cpp,Generic,Lou,,24,415,,415,,,x,,namespace CbcGenSolvers,namespace,Unnamed local namespace for cbc-generic support types and functions. CbcGenMessages.cpp,Generic,Lou,,24,192,,192,x,,,,CbcGenCtlBlk,,Message definitions. CbcGenOsiParam.cpp,Generic,Lou,,24,156,197,353,,,x,,CbcOsiParam,,Constructors and destructors for CbcOsiParam CbcGenOsiParamUtils.cpp,Generic,Lou,,18,528,,528,,,x,,namespace CbcOsiParamUtils,,Implementation functions for CbcOsiParam parameters CbcGenParam.cpp,Generic,Lou,,24,154,219,373,,,x,,CbcGenParam,,Constructors and destructors for CbcGenParam CbcGenParamUtils.cpp,Generic,Lou,,18,1497,,1497,,,x,,namespace CbcGenParamUtils,"namespace CbcGenSolvers, ",Implementation functions for CbcGenParam parameters CbcGenSolution.cpp,Generic,Lou,,22,584,,584,,,x,,CbcGenParamUtils,namespace,"Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise." CbcGenSolvers.cpp,Generic,Lou,,24,261,,261,,,x,,namespace CbcGenSolvers,namespace,This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers. CbcHeuristic.cpp,Heuristic,,,10,2901,650,3551,x,,,,CbcHeuristic,"CbcHeuristicNode, CbcHeuristicNodeList, CbcRounding, CbcHeuristicPartial, CbcSerendipity, CbcHeuristicJustOne", CbcHeuristicDive.cpp,Heuristic,,,10,1068,160,1228,x,,,,CbcHeuristicDive,, CbcHeuristicDiveCoefficient.cpp,Heuristic,,,12,128,49,177,x,,,,CbcHeuristicDiveCoefficient,, CbcHeuristicDiveFractional.cpp,Heuristic,,,18,112,49,161,x,,,,CbcHeuristicDiveFractional,, CbcHeuristicDiveGuided.cpp,Heuristic,,,18,123,52,175,x,,,,CbcHeuristicDiveGuided, CbcHeuristicDiveLineSearch.cpp,Heuristic,,,18,120,49,169,x,,,,CbcHeuristicDiveLineSearch, CbcHeuristicDivePseudoCost.cpp,Heuristic,,,18,227,57,284,x,,,,CbcHeuristicDivePseudoCost, CbcHeuristicDiveVectorLength.cpp,Heuristic,,,10,123,49,172,x,,,,CbcHeuristicDiveVectorLength, CbcHeuristicFPump.cpp,Heuristic,,,8,2764,319,3083,x,,,,CbcHeuristicFPump,CbcDisasterHandler CbcHeuristicGreedy.cpp,Heuristic,,,17,861,189,1050,x,,,,CbcHeuristicGreedyCover,CbcHeuristicGreedyEquality CbcHeuristicLocal.cpp,Heuristic,,,8,1104,208,1312,x,,,,CbcHeuristicLocal,CbcHeuristicNaive CbcHeuristicPivotAndFix.cpp,Heuristic,,,14,537,55,592,x,,,,CbcHeuristicPivotAndFix, CbcHeuristicRandRound.cpp,Heuristic,,,10,514,55,569,x,,,,CbcHeuristicRandRound, CbcHeuristicRINS.cpp,Heuristic,,,10,1207,296,1503,x,,,,CbcHeuristicRINS,"CbcHeuristicRENS, CbcHeuristicDINS, CbcHeuristicVND" CbcLinked.cpp,,,,10,8302,1403,9705,x,,,,OsiSolverLink,"OsiLinkedBound, OsiHeuristicDynamic3, OsiOldLink, OsiBiLinear*, OsiSimpleFixedInteger, Multiple" CbcMain.cpp,,,,14,1651,,1651,,,,x,main,"CbcCompareUser, namespace" CbcMessage.cpp,,,,13,104,87,191,x,,,,CbcMessage, CbcModel.cpp,,,,0,16557,2622,19179,x,,,,CbcModel, CbcNode.cpp,,,,0,5135,806,5941,x,,,,CbcNode,"CbcNodeInfo, CbcFullNodeInfo, CbcPartialNodeInfo, " CbcParam.cpp,Solver,Bjarni,,24,502,237,739,x,,,,CbcParam, CbcSolver.cpp,Solver,Bjarni,,0,11365,,11365,,x,,,CbcSolver,CbcMain CbcStatistics.cpp,,,,21,136,98,234,x,,,,CbcStatistics, CbcStrategy.cpp,,,,8,940,255,1195,x,,,,CbcStrategy,CbcStrategyDefault* CbcTree.cpp,,,,8,1178,419,1597,x,,,,CbcTree,CbcTreeArray CbcTreeLocal.cpp,,,,10,1747,369,2116,x,,,,CbcTreeLocal, Cbc_ampl.cpp,Ampl,,,4,1504,65,1569,,,,x,global, Cbc_C_Interface.cpp,Interface,Bjarni,,4,2554,658,3212,,,,x,global, ClpAmplObjective.cpp,Ampl,,,14,750,110,860,,,,x,ClpAmplObjective, ClpAmplStuff.cpp,Ampl,,,3,1370,,1370,x,,,,CbcAmpl,"CbcAmpl*, Multiple" ClpConstraintAmpl.hpp,Ampl,,,24,,105,105,,,,,, CoinSolve.cpp,Solver,,,8,342,,342,,x,,,MyMessageHandler2,main unitTest.cpp,Test,,,8,418,,418,,,,x,global, unitTestClp.cpp,Test,,,5,714,,714,,x,,,global, Cbc-2.8.12/configure.ac0000644000076600007660000003622112377521104013245 0ustar coincoin# Copyright (C) 2006, 2007 International Business Machines. # All Rights Reserved. # This file is distributed under the Eclipse Public License. ## $Id: configure.ac 2065 2014-08-28 03:30:12Z tkr $ # Author: Andreas Waechter IBM 2006-04-13 ############################################################################# # Names and other basic things # ############################################################################# AC_PREREQ(2.59) AC_INIT([Cbc],[2.8.12],[cbc@lists.coin-or.org]) AC_COPYRIGHT([ Copyright 2006 International Business Machines and others. All Rights Reserved. This file is part of the open source package Coin which is distributed under the Eclipse Public License.]) # List one file in the package so that the configure script can test # whether the package is actually there AC_CONFIG_SRCDIR(src/CbcTree.hpp) # Where should everything be installed by default? Here, we want it # to be installed directly in 'bin', 'lib', 'include' subdirectories # of the directory where configure is run. The default would be # /usr/local. AC_PREFIX_DEFAULT([`pwd`]) ############################################################################# # Standard build tool stuff # ############################################################################# # Get the system type AC_CANONICAL_BUILD # If this project depends on external projects, the Externals file in # the source root directory contains definition of where to find those # externals. The following macro ensures that those externals are # retrieved by svn if they are not there yet. AC_COIN_PROJECTDIR_INIT(Cbc,11:12:8) # Check if user wants to produce debugging code AC_COIN_DEBUG_COMPILE(Cbc) # Get the name of the C++ compiler and appropriate compiler options AC_COIN_PROG_CXX # Initialize automake and libtool AC_COIN_INIT_AUTO_TOOLS ############################################################################# # COIN-OR components # ############################################################################# AC_COIN_CHECK_PACKAGE(CoinDepend, [cgl osi coinutils], [CbcLib CbcGeneric]) if test $coin_has_coindepend != yes ; then AC_MSG_ERROR([One or more required packages CoinUtils, Osi, and Cgl are not available.]) fi # Clp and OsiClp are inseparable here. AC_COIN_CHECK_PACKAGE(Clp, [osi-clp], [CbcLib CbcGeneric]) if test $coin_has_clp != yes ; then AC_MSG_ERROR("Required package Clp unavailable.") fi # The rest are not required for linking against Cbc AC_COIN_CHECK_PACKAGE(OsiTests, [osi-unittests]) AC_COIN_CHECK_PACKAGE(Sample, [coindatasample]) AC_COIN_CHECK_PACKAGE(Netlib, [coindatanetlib]) AC_COIN_CHECK_PACKAGE(Miplib3, [coindatamiplib3]) # Cbc really should make these tests; right now it assumes far too much about # its environment. Needed for cbc-generic. AC_COIN_CHECK_CXX_CHEADER(math) AC_COIN_CHECK_CXX_CHEADER(float) AC_COIN_CHECK_CXX_CHEADER(ieeefp) AC_COIN_CHECK_GNU_READLINE(CbcLib CbcGeneric) ############################################################################# # LP solvers other than CLP # ############################################################################# # Check which other LP solvers are available, some of them become a dependency of CbcGeneric AC_COIN_CHECK_PACKAGE(DyLP, [osi-dylp], [CbcGeneric]) AC_COIN_CHECK_PACKAGE(Vol, [osi-vol]) AC_COIN_CHECK_PACKAGE(Cpx, [osi-cplex], [CbcLib CbcGeneric]) AC_COIN_CHECK_PACKAGE(Glpk, [osi-glpk], [CbcGeneric]) AC_COIN_CHECK_PACKAGE(Grb, [osi-gurobi]) AC_COIN_CHECK_PACKAGE(Msk, [osi-mosek], [CbcGeneric]) AC_COIN_CHECK_PACKAGE(Spx, [osi-soplex], [CbcGeneric]) AC_COIN_CHECK_PACKAGE(Xpr, [osi-xpress]) ############################################################################# # Other third party software # ############################################################################# # Ampl Solver library AC_COIN_CHECK_PACKAGE(ASL, [coinasl], [CbcLib CbcGeneric]) ############################################################################# # CbcGeneric configuration # ############################################################################# # Are we building cbc-generic? Default is no (false). AC_ARG_WITH([cbc-generic], AS_HELP_STRING([--with-cbc-generic], [specify whether to build cbc-generic (default: no)]), [case $withval in yes) cbc_with_cbc_generic=true ;; *) cbc_with_cbc_generic=false ;; esac], [cbc_with_cbc_generic=false]) if test x"$cbc_with_cbc_generic" = xyes ; then AC_MSG_NOTICE([building cbc-generic]) fi AM_CONDITIONAL(CBC_BUILD_CBC_GENERIC, test x"$cbc_with_cbc_generic" = xtrue) # Set the default solver for cbc-generic. In theory, any OsiXXX should work. # In practice, only the three listed below have had any testing. AC_MSG_CHECKING(for cbc-generic default solver) AC_ARG_WITH([cbc-generic-solver], AC_HELP_STRING([--with-cbc-generic-solver], [specify default solver for cbc-generic in lower case letters (if not given, clp is assumed)]), [cbc_default_solver=$withval], [cbc_default_solver=clp]) AC_MSG_RESULT($cbc_default_solver) # FIXME what about cplex and mosek here? case $cbc_default_solver in clp) ;; dylp) ;; glpk) ;; soplex) ;; *) AC_MSG_WARN([Unrecognised solver $cbc_default_solver chosen as cbc-generic default solver.]) ;; esac AC_DEFINE_UNQUOTED([CBC_DEFAULT_SOLVER],"$cbc_default_solver", [Define to the name of the default solver to be used in cbc-generic in small letters]) ############################################################################# # Cbc parallel configuration # ############################################################################# # First we define a new option, --enable-cbc-parallel AC_ARG_ENABLE([cbc-parallel], [AC_HELP_STRING([--enable-cbc-parallel], [enables compilation of the SMP version of Cbc])]) if test "$enable_cbc_parallel" = yes; then # Define the preprocessor macro AC_DEFINE([CBC_THREAD],[1],[Define to 1 if the SMP version of Cbc should be compiled]) if test $coin_cxx_is_cl = true ; then # TODO we should check whether the library works and pthread.h is indeed there AC_ARG_WITH(pthreadsw32-lib, AC_HELP_STRING([--with-pthreadsw32-lib], [specify the name of the pthreads win32 library (for cl/icl builds only)]), [CBCLIB_LIBS="$withval $CBCLIB_LIBS" CBCLIB_PCLIBS="$withval $CBCLIB_PCLIBS"], [AC_MSG_WARN([--enable-cbc-parallel selected, but --with-pthreadsw32-lib not given]) CBCLIB_LIBS="pthreadVCE2.lib $CBCLIB_LIBS"]) AC_ARG_WITH(pthreadsw32-incdir, AC_HELP_STRING([--with-pthreadsw32-incdir], [specify the path of the pthreads win32 header file (for cl/icl builds only)]), [CXXFLAGS="$CXXFLAGS -I$withval"], [AC_MSG_WARN([--enable-cbc-parallel selected, but --with-pthreadsw32-incdir not given])]) else AC_CHECK_LIB([rt],[clock_gettime], [CBCLIB_LIBS="-lrt $CBCLIB_LIBS" CBCLIB_PCLIBS="-lrt $CBCLIB_PCLIBS" AC_DEFINE([HAVE_CLOCK_GETTIME],[1],[Define if clock_gettime and rt library is available]) ], [AC_MSG_WARN([--enable-cbc-parallel selected, but -lrt unavailable; using gettimeofday instead of clock_gettime])]) AC_CHECK_LIB([pthread],[pthread_create], [CBCLIB_LIBS="-lpthread $CBCLIB_LIBS" CBCLIB_PCLIBS="-lpthread $CBCLIB_PCLIBS" ], [AC_MSG_ERROR([--enable-cbc-parallel selected, but -lpthreads unavailable])]) fi AC_MSG_NOTICE([Cbc multithreading enabled]); fi ############################################################################## # OsiCbc configuration # ############################################################################## # Handles configuration of the underlying default solver in OsiCbc. The issue # is that OsiCbc defines a default solver, used when the client does not # specify a solver in the constructor. The default solver must, therefore, # be present in the build. This macro checks that this is true, and sets the # compile-time symbols OSICBC_DFLT_SOLVER, OSICBC_CLP_DFLT_SOLVER, and # OSICBC_DFLT_SOLVER_HPP that control the build. The parameter default_solver # should normally be clp, unless you're working on some other solver. # Ideally, this macro would not require enumeration of solvers, but the # effort required to avoid it is just not justified at present. One enumeration # is hidden in AC_OSI_CANONICAL. The other is visible, the AM_CONDITIONAL # list at the end. # In an ideal world this macro would do absolutely nothing if Cbc is not # present, but autotools is not an ideal world and we have to satisfy its # requirements. In particular, the AM_CONDITIONAL macros need to execute or # automake will complain. Really the only thing we need to suppress is the # check that the default solver exists. All the rest is irrelevant when Cbc # isn't present (hence OsiCbc will be configured but not actually compiled). # Process the with-osicbc-default-solver option. AC_ARG_WITH([osicbc-default-solver], AS_HELP_STRING([--with-osicbc-default-solver], [specify underlying solver for OsiCbc (default clp)]), [osicbc_with_solver=$withval], [osicbc_with_solver=clp]) case "${osicbc_with_solver}" in @<:@Cc@:>@@<:@Ll@:>@@<:@Pp@:>@*) osi_lc_solver=clp ; osi_mc_solver=Clp ; osi_uc_solver=CLP ; osi_exists_solver=${coin_has_clp-"unavailable"} ;; @<:@Dd@:>@@<:@Yy@:>@@<:@Ll@:>@@<:@Pp@:>@*) osi_lc_solver=dylp ; osi_mc_solver=Dylp osi_uc_solver=DYLP osi_exists_solver=${coin_has_dylp-"unavailable"} ;; @<:@Cc@:>@@<:@Pp@:>@@<:@Xx@:>@*) osi_lc_solver=cpx ; osi_mc_solver=Cpx osi_uc_solver=CPX osi_exists_solver=${coin_has_cpx-"unavailable"} ;; @<:@Gg@:>@@<:@Ll@:>@@<:@Pp@:>@@<:@Kk@:>@*) osi_lc_solver=glpk ; osi_mc_solver=Glpk osi_uc_solver=GLPK osi_exists_solver=${coin_has_glpk-"unavailable"} ;; @<:@Gg@:>@@<:@Rr@:>@@<:@Bb@:>@*) osi_lc_solver=grb ; osi_mc_solver=Grb ; osi_uc_solver=GRB ; osi_exists_solver=${coin_has_grb-"unavailable"} ;; @<:@Mm@:>@@<:@Ss@:>@@<:@Kk@:>@*) osi_lc_solver=msk ; osi_mc_solver=Msk osi_uc_solver=MSK osi_exists_solver=${coin_has_msk-"unavailable"} ;; @<:@Ss@:>@@<:@Pp@:>@@<:@Xx@:>@*) osi_lc_solver=spx ; osi_mc_solver=Spx osi_uc_solver=SPX osi_exists_solver=${coin_has_spx-"unavailable"} ;; @<:@Ss@:>@@<:@Yy@:>@@<:@Mm@:>@*) osi_lc_solver=sym ; osi_mc_solver=Sym osi_uc_solver=SYM osi_exists_solver=${coin_has_sym-"unavailable"} ;; @<:@Vv@:>@@<:@Oo@:>@@<:@Ll@:>@*) osi_lc_solver=vol ; osi_mc_solver=Vol osi_uc_solver=VOL osi_exists_solver=${coin_has_vol-"unavailable"} ;; @<:@Xx@:>@@<:@Pp@:>@@<:@Rr@:>@*) osi_lc_solver=xpr ; osi_mc_solver=Xpr osi_uc_solver=XPR osi_exists_solver=${coin_has_xpr-"unavailable"} ;; *) osi_lc_solver=clp ; osi_mc_solver=Clp ; osi_uc_solver=CLP ; osi_exists_solver=${coin_has_clp-"unavailable"} AC_MSG_WARN([Unrecognised solver $1; defaulting to $osi_lc_solver.]) ;; esac # Check that the requested solver is available. if test $osi_exists_solver = no; then AC_MSG_ERROR([selected default solver $osicbc_with_solver is unavailable. Please select an available solver using the --with-osicbc-default-solver option.]) fi # State the result. AC_MSG_NOTICE([OsiCbc default solver is $osi_lc_solver]) # And set the configuration variables. AC_DEFINE_UNQUOTED([OSICBC_DFLT_SOLVER], [Osi${osi_mc_solver}SolverInterface], [define to the name of the default solver interface class, e.g., OsiClpSolverInterface]) AC_DEFINE_UNQUOTED([OSICBC_DFLT_SOLVER_HPP], ["Osi${osi_mc_solver}SolverInterface.hpp"], [define to the name of the .hpp file for the default solver interface class, e.g., "OsiClpSolverInterface.hpp" (include quotes)]) if test $osi_mc_solver = "Clp"; then AC_DEFINE([OSICBC_DFLT_SOLVER_CLP],[1],[define this symbol if clp is the default solver]) fi # Last but not least, we need automake conditionals. AM_CONDITIONAL([OSICBC_DFLT_SOLVER_CLP],[test $osi_mc_solver = Clp]) AM_CONDITIONAL([OSICBC_DFLT_SOLVER_CPX],[test $osi_mc_solver = Cpx]) AM_CONDITIONAL([OSICBC_DFLT_SOLVER_DYLP],[test $osi_mc_solver = Dylp]) AM_CONDITIONAL([OSICBC_DFLT_SOLVER_GLPK],[test $osi_mc_solver = Glpk]) AM_CONDITIONAL([OSICBC_DFLT_SOLVER_GRB],[test $osi_mc_solver = Grb]) AM_CONDITIONAL([OSICBC_DFLT_SOLVER_MSK],[test $osi_mc_solver = Msk]) AM_CONDITIONAL([OSICBC_DFLT_SOLVER_SPX],[test $osi_mc_solver = Spx]) AM_CONDITIONAL([OSICBC_DFLT_SOLVER_SYM],[test $osi_mc_solver = Sym]) AM_CONDITIONAL([OSICBC_DFLT_SOLVER_VOL],[test $osi_mc_solver = Vol]) AM_CONDITIONAL([OSICBC_DFLT_SOLVER_XPR],[test $osi_mc_solver = Xpr]) ############################################################################## # VPATH links for example input files # ############################################################################## # In case this is a VPATH configuration we need to make sure that the # input files for the examples are available in the VPATH directory. AC_COIN_VPATH_LINK(examples/sudoku_sample.csv) AC_COIN_VPATH_LINK(examples/quad.mps) AC_COIN_VPATH_LINK(examples/quad2.mps) ############################################################################# # Check for doxygen # ############################################################################# AC_COIN_DOXYGEN(CoinUtils Osi Clp DyLP Cgl Vol) ############################################################################## # Finishing up by writing all the output # ############################################################################## # Here list all the files that configure should create (except for the # configuration header file) AC_CONFIG_FILES([Makefile examples/Makefile src/Makefile src/OsiCbc/Makefile test/Makefile cbc.pc cbc-uninstalled.pc osi-cbc.pc osi-cbc-uninstalled.pc]) AC_CONFIG_FILES([doxydoc/doxygen.conf]) # Here put the location and name of the configuration header file AC_CONFIG_HEADER([src/config.h src/config_cbc.h]) # Finally, we let configure write all the output... AC_COIN_FINALIZE Cbc-2.8.12/src/0000755000076600007660000000000012377555231011552 5ustar coincoinCbc-2.8.12/src/CbcCountRowCut.hpp0000644000076600007660000001204412075572125015124 0ustar coincoin/* $Id: CbcCountRowCut.hpp 1839 2013-01-16 18:41:25Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcCountRowCut_H #define CbcCountRowCut_H class OsiCuts; class OsiRowCut; class CbcNodeInfo; //############################################################################# /** \brief OsiRowCut augmented with bookkeeping CbcCountRowCut is an OsiRowCut object augmented with bookkeeping information: a reference count and information that specifies the the generator that created the cut and the node to which it's associated. The general principles for handling the reference count are as follows:
  • Once it's determined how the node will branch, increment the reference count under the assumption that all children will use all cuts currently tight at the node and will survive to be placed in the search tree.
  • As this assumption is proven incorrect (a cut becomes loose, or a child is fathomed), decrement the reference count accordingly.
When all possible uses of a cut have been demonstrated to be unnecessary, the reference count (#numberPointingToThis_) will fall to zero. The CbcCountRowCut object (and its included OsiRowCut object) are then deleted. */ class CbcCountRowCut : public OsiRowCut { public: /** @name Constructors & destructors */ //@{ /// Default Constructor CbcCountRowCut (); /// `Copy' constructor using an OsiRowCut CbcCountRowCut ( const OsiRowCut &); /// `Copy' constructor using an OsiRowCut and an CbcNodeInfo CbcCountRowCut(const OsiRowCut &, CbcNodeInfo *, int whichOne, int whichGenerator = -1, int numberPointingToThis = 0); /** Destructor \note The destructor will reach out (via #owner_) and NULL the reference to the cut in the owner's \link CbcNodeInfo::cuts_ cuts_ \endlink list. */ virtual ~CbcCountRowCut (); //@} /// Increment the number of references void increment(int change = 1); /// Decrement the number of references and return the number left. int decrement(int change = 1); /** \brief Set the information associating this cut with a node An CbcNodeInfo object and an index in the cut set of the node. For locally valid cuts, the node will be the search tree node where the cut was generated. For globally valid cuts, it's the node where the cut was activated. */ void setInfo(CbcNodeInfo *, int whichOne); /// Number of other CbcNodeInfo objects pointing to this row cut inline int numberPointingToThis() { return numberPointingToThis_; } /// Which generator for cuts - as user order inline int whichCutGenerator() const { return whichCutGenerator_; } /// Returns true if can drop cut if slack basic bool canDropCut(const OsiSolverInterface * solver, int row) const; #ifdef CHECK_CUT_COUNTS // Just for printing sanity checks int tempNumber_; #endif private: /// Standard copy is illegal (reference counts would be incorrect) CbcCountRowCut(const CbcCountRowCut &); /// Standard assignment is illegal (reference counts would be incorrect) CbcCountRowCut & operator=(const CbcCountRowCut& rhs); /// Backward pointer to owning CbcNodeInfo CbcNodeInfo * owner_; /// Index of cut in owner's cut set /// (\link CbcNodeInfo::cuts_ cuts_ \endlink). int ownerCut_; /// Number of other CbcNodeInfo objects pointing to this cut int numberPointingToThis_; /** Which generator created this cut (add 10000 if globally valid) if -1 then from global cut pool -2 cut branch -3 unknown */ int whichCutGenerator_; }; /** Really for Conflict cuts to - a) stop duplicates b) allow half baked cuts The whichRow_ field in OsiRowCut2 is used for a type 0 - normal 1 - processed cut 2 - unprocessed cut i.e. dual ray computation */ // for hashing typedef struct { int index, next; } CoinHashLink; class CbcRowCuts { public: CbcRowCuts(int initialMaxSize=0, int hashMultiplier=4 ); ~CbcRowCuts(); CbcRowCuts(const CbcRowCuts& rhs); CbcRowCuts& operator=(const CbcRowCuts& rhs); inline OsiRowCut2 * cut(int sequence) const { return rowCut_[sequence];} inline int numberCuts() const { return numberCuts_;} inline int sizeRowCuts() const { return numberCuts_;} inline OsiRowCut * rowCutPtr(int sequence) { return rowCut_[sequence];} void eraseRowCut(int sequence); // Return 0 if added, 1 if not, -1 if not added because of space int addCutIfNotDuplicate(const OsiRowCut & cut,int whichType=0); // Return 0 if added, 1 if not, -1 if not added because of space int addCutIfNotDuplicateWhenGreedy(const OsiRowCut & cut,int whichType=0); // Add in cuts as normal cuts (and delete) void addCuts(OsiCuts & cs); private: OsiRowCut2 ** rowCut_; /// Hash table CoinHashLink *hash_; int size_; int hashMultiplier_; int numberCuts_; int lastHash_; }; #endif Cbc-2.8.12/src/CbcCutGenerator.hpp0000644000076600007660000003647412130022033015263 0ustar coincoin/* $Id: CbcCutGenerator.hpp 1883 2013-04-06 13:33:15Z stefan $ */ // Copyright (C) 2003, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcCutGenerator_H #define CbcCutGenerator_H #include "OsiSolverInterface.hpp" #include "OsiCuts.hpp" #include "CglCutGenerator.hpp" #include "CbcCutModifier.hpp" class CbcModel; class OsiRowCut; class OsiRowCutDebugger; //############################################################################# /** Interface between Cbc and Cut Generation Library. \c CbcCutGenerator is intended to provide an intelligent interface between Cbc and the cutting plane algorithms in the CGL. A \c CbcCutGenerator is bound to a \c CglCutGenerator and to an \c CbcModel. It contains parameters which control when and how the \c generateCuts method of the \c CglCutGenerator will be called. The builtin decision criteria available to use when deciding whether to generate cuts are limited: every X nodes, when a solution is found, and when a subproblem is found to be infeasible. The idea is that the class will grow more intelligent with time. \todo Add a pointer to function member which will allow a client to install their own decision algorithm to decide whether or not to call the CGL \p generateCuts method. Create a default decision method that looks at the builtin criteria. \todo It strikes me as not good that generateCuts contains code specific to individual CGL algorithms. Another set of pointer to function members, so that the client can specify the cut generation method as well as pre- and post-generation methods? Taken a bit further, should this class contain a bunch of pointer to function members, one for each of the places where the cut generator might be referenced? Initialization, root node, search tree node, discovery of solution, and termination all come to mind. Initialization and termination would also be useful for instrumenting cbc. */ class CbcCutGenerator { public: /** \name Generate Cuts */ //@{ /** Generate cuts for the client model. Evaluate the state of the client model and decide whether to generate cuts. The generated cuts are inserted into and returned in the collection of cuts \p cs. If \p fullScan is !=0, the generator is obliged to call the CGL \c generateCuts routine. Otherwise, it is free to make a local decision. Negative fullScan says things like at integer solution The current implementation uses \c whenCutGenerator_ to decide. The routine returns true if reoptimisation is needed (because the state of the solver interface has been modified). If node then can find out depth */ bool generateCuts( OsiCuts &cs, int fullScan, OsiSolverInterface * solver, CbcNode * node); //@} /**@name Constructors and destructors */ //@{ /// Default constructor CbcCutGenerator (); /// Normal constructor CbcCutGenerator(CbcModel * model, CglCutGenerator * generator, int howOften = 1, const char * name = NULL, bool normal = true, bool atSolution = false, bool infeasible = false, int howOftenInsub = -100, int whatDepth = -1, int whatDepthInSub = -1, int switchOffIfLessThan = 0); /// Copy constructor CbcCutGenerator (const CbcCutGenerator &); /// Assignment operator CbcCutGenerator & operator=(const CbcCutGenerator& rhs); /// Destructor ~CbcCutGenerator (); //@} /**@name Gets and sets */ //@{ /** Set the client model. In addition to setting the client model, refreshModel also calls the \c refreshSolver method of the CglCutGenerator object. */ void refreshModel(CbcModel * model); /// return name of generator inline const char * cutGeneratorName() const { return generatorName_; } /// Create C++ lines to show how to tune void generateTuning( FILE * fp); /** Set the cut generation interval Set the number of nodes evaluated between calls to the Cgl object's \p generateCuts routine. If \p value is positive, cuts will always be generated at the specified interval. If \p value is negative, cuts will initially be generated at the specified interval, but Cbc may adjust the value depending on the success of cuts produced by this generator. A value of -100 disables the generator, while a value of -99 means just at root. */ void setHowOften(int value) ; /// Get the cut generation interval. inline int howOften() const { return whenCutGenerator_; } /// Get the cut generation interval.in sub tree inline int howOftenInSub() const { return whenCutGeneratorInSub_; } /// Get level of cut inaccuracy (0 means exact e.g. cliques) inline int inaccuracy() const { return inaccuracy_; } /// Set level of cut inaccuracy (0 means exact e.g. cliques) inline void setInaccuracy(int level) { inaccuracy_ = level; } /** Set the cut generation depth Set the depth criterion for calls to the Cgl object's \p generateCuts routine. Only active if > 0. If whenCutGenerator is positive and this is positive then this overrides. If whenCutGenerator is -1 then this is used as criterion if any cuts were generated at root node. If whenCutGenerator is anything else this is ignored. */ void setWhatDepth(int value) ; /// Set the cut generation depth in sub tree void setWhatDepthInSub(int value) ; /// Get the cut generation depth criterion. inline int whatDepth() const { return depthCutGenerator_; } /// Get the cut generation depth criterion.in sub tree inline int whatDepthInSub() const { return depthCutGeneratorInSub_; } /// Set maximum number of times to enter inline void setMaximumTries(int value) { maximumTries_ = value;} /// Get maximum number of times to enter inline int maximumTries() const { return maximumTries_;} /// Get switches (for debug) inline int switches() const { return switches_; } /// Get whether the cut generator should be called in the normal place inline bool normal() const { return (switches_&1) != 0; } /// Set whether the cut generator should be called in the normal place inline void setNormal(bool value) { switches_ &= ~1; switches_ |= value ? 1 : 0; } /// Get whether the cut generator should be called when a solution is found inline bool atSolution() const { return (switches_&2) != 0; } /// Set whether the cut generator should be called when a solution is found inline void setAtSolution(bool value) { switches_ &= ~2; switches_ |= value ? 2 : 0; } /** Get whether the cut generator should be called when the subproblem is found to be infeasible. */ inline bool whenInfeasible() const { return (switches_&4) != 0; } /** Set whether the cut generator should be called when the subproblem is found to be infeasible. */ inline void setWhenInfeasible(bool value) { switches_ &= ~4; switches_ |= value ? 4 : 0; } /// Get whether the cut generator is being timed inline bool timing() const { return (switches_&64) != 0; } /// Set whether the cut generator is being timed inline void setTiming(bool value) { switches_ &= ~64; switches_ |= value ? 64 : 0; timeInCutGenerator_ = 0.0; } /// Return time taken in cut generator inline double timeInCutGenerator() const { return timeInCutGenerator_; } inline void incrementTimeInCutGenerator(double value) { timeInCutGenerator_ += value; } /// Get the \c CglCutGenerator corresponding to this \c CbcCutGenerator. inline CglCutGenerator * generator() const { return generator_; } /// Number times cut generator entered inline int numberTimesEntered() const { return numberTimes_; } inline void setNumberTimesEntered(int value) { numberTimes_ = value; } inline void incrementNumberTimesEntered(int value = 1) { numberTimes_ += value; } /// Total number of cuts added inline int numberCutsInTotal() const { return numberCuts_; } inline void setNumberCutsInTotal(int value) { numberCuts_ = value; } inline void incrementNumberCutsInTotal(int value = 1) { numberCuts_ += value; } /// Total number of elements added inline int numberElementsInTotal() const { return numberElements_; } inline void setNumberElementsInTotal(int value) { numberElements_ = value; } inline void incrementNumberElementsInTotal(int value = 1) { numberElements_ += value; } /// Total number of column cuts inline int numberColumnCuts() const { return numberColumnCuts_; } inline void setNumberColumnCuts(int value) { numberColumnCuts_ = value; } inline void incrementNumberColumnCuts(int value = 1) { numberColumnCuts_ += value; } /// Total number of cuts active after (at end of n cut passes at each node) inline int numberCutsActive() const { return numberCutsActive_; } inline void setNumberCutsActive(int value) { numberCutsActive_ = value; } inline void incrementNumberCutsActive(int value = 1) { numberCutsActive_ += value; } inline void setSwitchOffIfLessThan(int value) { switchOffIfLessThan_ = value; } inline int switchOffIfLessThan() const { return switchOffIfLessThan_; } /// Say if optimal basis needed inline bool needsOptimalBasis() const { return (switches_&128) != 0; } /// Set if optimal basis needed inline void setNeedsOptimalBasis(bool yesNo) { switches_ &= ~128; switches_ |= yesNo ? 128 : 0; } /// Whether generator MUST be called again if any cuts (i.e. ignore break from loop) inline bool mustCallAgain() const { return (switches_&8) != 0; } /// Set whether generator MUST be called again if any cuts (i.e. ignore break from loop) inline void setMustCallAgain(bool yesNo) { switches_ &= ~8; switches_ |= yesNo ? 8 : 0; } /// Whether generator switched off for moment inline bool switchedOff() const { return (switches_&16) != 0; } /// Set whether generator switched off for moment inline void setSwitchedOff(bool yesNo) { switches_ &= ~16; switches_ |= yesNo ? 16 : 0; } /// Whether last round of cuts did little inline bool ineffectualCuts() const { return (switches_&512) != 0; } /// Set whether last round of cuts did little inline void setIneffectualCuts(bool yesNo) { switches_ &= ~512; switches_ |= yesNo ? 512 : 0; } /// Whether to use if any cuts generated inline bool whetherToUse() const { return (switches_&1024) != 0; } /// Set whether to use if any cuts generated inline void setWhetherToUse(bool yesNo) { switches_ &= ~1024; switches_ |= yesNo ? 1024 : 0; } /// Whether in must call again mode (or after others) inline bool whetherInMustCallAgainMode() const { return (switches_&2048) != 0; } /// Set whether in must call again mode (or after others) inline void setWhetherInMustCallAgainMode(bool yesNo) { switches_ &= ~2048; switches_ |= yesNo ? 2048 : 0; } /// Whether to call at end inline bool whetherCallAtEnd() const { return (switches_&4096) != 0; } /// Set whether to call at end inline void setWhetherCallAtEnd(bool yesNo) { switches_ &= ~4096; switches_ |= yesNo ? 4096 : 0; } /// Number of cuts generated at root inline int numberCutsAtRoot() const { return numberCutsAtRoot_; } inline void setNumberCutsAtRoot(int value) { numberCutsAtRoot_ = value; } /// Number of cuts active at root inline int numberActiveCutsAtRoot() const { return numberActiveCutsAtRoot_; } inline void setNumberActiveCutsAtRoot(int value) { numberActiveCutsAtRoot_ = value; } /// Number of short cuts at root inline int numberShortCutsAtRoot() const { return numberShortCutsAtRoot_; } inline void setNumberShortCutsAtRoot(int value) { numberShortCutsAtRoot_ = value; } /// Set model inline void setModel(CbcModel * model) { model_ = model; } /// Whether global cuts at root inline bool globalCutsAtRoot() const { return (switches_&32) != 0; } /// Set whether global cuts at root inline void setGlobalCutsAtRoot(bool yesNo) { switches_ &= ~32; switches_ |= yesNo ? 32 : 0; } /// Whether global cuts inline bool globalCuts() const { return (switches_&256) != 0; } /// Set whether global cuts inline void setGlobalCuts(bool yesNo) { switches_ &= ~256; switches_ |= yesNo ? 256 : 0; } /// Add in statistics from other void addStatistics(const CbcCutGenerator * other); /// Scale back statistics by factor void scaleBackStatistics(int factor); //@} private: /**@name Private gets and sets */ //@{ //@} /// Saved cuts OsiCuts savedCuts_; /// Time in cut generator double timeInCutGenerator_; /// The client model CbcModel *model_; // The CglCutGenerator object CglCutGenerator * generator_; /// Name of generator char * generatorName_; /** Number of nodes between calls to the CglCutGenerator::generateCuts routine. */ int whenCutGenerator_; /** Number of nodes between calls to the CglCutGenerator::generateCuts routine in sub tree. */ int whenCutGeneratorInSub_; /** If first pass at root produces fewer than this cuts then switch off */ int switchOffIfLessThan_; /** Depth at which to call the CglCutGenerator::generateCuts routine (If >0 then overrides when and is called if depth%depthCutGenerator==0). */ int depthCutGenerator_; /** Depth at which to call the CglCutGenerator::generateCuts routine (If >0 then overrides when and is called if depth%depthCutGenerator==0). In sub tree. */ int depthCutGeneratorInSub_; /// Level of cut inaccuracy (0 means exact e.g. cliques) int inaccuracy_; /// Number times cut generator entered int numberTimes_; /// Total number of cuts added int numberCuts_; /// Total number of elements added int numberElements_; /// Total number of column cuts added int numberColumnCuts_; /// Total number of cuts active after (at end of n cut passes at each node) int numberCutsActive_; /// Number of cuts generated at root int numberCutsAtRoot_; /// Number of cuts active at root int numberActiveCutsAtRoot_; /// Number of short cuts at root int numberShortCutsAtRoot_; /// Switches - see gets and sets int switches_; /// Maximum number of times to enter int maximumTries_; }; // How often to do if mostly switched off (A) # define SCANCUTS 1000 // How often to do if mostly switched off (probing B) # define SCANCUTS_PROBING 1000 #endif Cbc-2.8.12/src/CbcGenCbcParam.hpp0000644000076600007660000001202212131315050014747 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenCbcParam.hpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #ifndef CbcCbcParam_H #define CbcCbcParam_H /* \file CbcGenCbcParam.hpp \brief Declarations for parameters that act on a CbcModel object. */ /* $Id: CbcGenCbcParam.hpp 1902 2013-04-10 16:58:16Z stefan $ */ /*! \class CbcCbcParam \brief Class for control parameters that act on a CbcModel object. Adds parameter type codes and push/pull functions to the generic parameter object. */ class CbcCbcParam : public CoinParam { public: /*! \name Subtypes */ //@{ /*! \enum CbcCbcParamCode \brief Enumeration for parameters that control a CbcModel object These are parameters that control the operation of a CbcModel object. CBCCBC_FIRSTPARAM and CBCCBC_LASTPARAM are markers to allow convenient separation of parameter groups. */ typedef enum { CBCCBC_FIRSTPARAM = CbcGenParam::CBCGEN_LASTPARAM + 1, ALLOWABLEGAP, COSTSTRATEGY, CUTDEPTH, CUTOFF, CUTPASS, DIRECTION, GAPRATIO, INCREMENT, INFEASIBILITYWEIGHT, INTEGERTOLERANCE, LOGLEVEL, MAXIMIZE, MAXNODES, MINIMIZE, MIPOPTIONS, MOREMIPOPTIONS, NUMBERANALYZE, NUMBERBEFORE, NUMBERMINI, STRONGBRANCHING, TIMELIMIT_BAB, CBCCBC_LASTPARAM } CbcCbcParamCode ; //@} /*! \name Constructors and Destructors Be careful how you specify parameters for the constructors! There's great potential for confusion. */ //@{ /*! \brief Default constructor */ CbcCbcParam() ; /*! \brief Constructor for a parameter with a double value The default value is 0.0. Be careful to clearly indicate that \p lower and \p upper are real (double) values to distinguish this constructor from the constructor for an integer parameter. */ CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, double lower, double upper, double dflt = 0.0, bool display = true) ; /*! \brief Constructor for a parameter with an integer value The default value is 0. */ CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, int lower, int upper, int dflt = 0, bool display = true) ; /*! \brief Constructor for a parameter with keyword values The string supplied as \p firstValue becomes the first keyword. Additional keywords can be added using appendKwd(). Keywords are numbered from zero. It's necessary to specify both the first keyword (\p firstValue) and the default keyword index (\p dflt) in order to distinguish this constructor from the string and action parameter constructors. */ CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, std::string firstValue, int dflt, bool display = true) ; /*! \brief Constructor for a string parameter The default string value must be specified explicitly to distinguish a string constructor from an action parameter constructor. */ CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, std::string dflt, bool display = true) ; /*! \brief Constructor for an action parameter */ CbcCbcParam(CbcCbcParamCode code, std::string name, std::string help, bool display = true) ; /*! \brief Copy constructor */ CbcCbcParam(const CbcCbcParam &orig) ; /*! \brief Clone */ CbcCbcParam *clone() ; /*! \brief Assignment */ CbcCbcParam &operator=(const CbcCbcParam &rhs) ; /*! \brief Destructor */ ~CbcCbcParam() ; //@} /*! \name Methods to query and manipulate a parameter object */ //@{ /*! \brief Get the parameter code */ inline CbcCbcParamCode paramCode() const { return (paramCode_) ; } /*! \brief Set the parameter code */ inline void setParamCode(CbcCbcParamCode code) { paramCode_ = code ; } /*! \brief Get the underlying CbcModel object */ inline CbcModel *obj() const { return (obj_) ; } /*! \brief Set the underlying CbcModel object */ inline void setObj(CbcModel *obj) { obj_ = obj ; } //@} private: /*! \name Data */ //@{ /// Parameter code CbcCbcParamCode paramCode_ ; /// CbcModel object CbcModel *obj_ ; //@} } ; /* Declare the utility functions. */ namespace CbcCbcParamUtils { void addCbcCbcParams(int &numParams, CoinParamVec ¶mVec, CbcModel *model) ; void loadCbcParamObj(const CoinParamVec paramVec, int first, int last, CbcModel *model) ; void setCbcModelDefaults (CbcModel *model) ; int pushCbcCbcDbl(CoinParam *param) ; int pushCbcCbcInt(CoinParam *param) ; } #endif Cbc-2.8.12/src/Cbc_C_Interface.cpp0000644000076600007660000007350012376140747015175 0ustar coincoin// $Id: Cbc_C_Interface.cpp 2059 2014-08-23 16:31:35Z tkr $ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include "CoinPragma.hpp" //#include "CoinHelperFunctions.hpp" //#include "CoinPackedMatrix.hpp" #include "CoinTime.hpp" #include "CbcModel.hpp" #include "CbcBranchActual.hpp" #include "CoinMessageHandler.hpp" #include "OsiClpSolverInterface.hpp" // bobe including extras.h to get strdup() #if defined(__MWERKS__) // #include // bobe 06-02-14 #endif // Get C stuff but with extern C #define CBC_EXTERN_C #include "Coin_C_defines.h" #define CbcGetProperty(T,prop) \ COINLIBAPI T COINLINKAGE \ Cbc_ ## prop (Cbc_Model *m) \ { \ return m->model_->prop(); \ } #define CbcSetSolverProperty(T,prop) \ COINLIBAPI void COINLINKAGE \ Cbc_ ## prop (Cbc_Model *m, int index, T val) \ { \ m->model_->solver()->prop(index,val); \ } const int VERBOSE = 0; // To allow call backs class Cbc_MessageHandler : public CoinMessageHandler { public: /**@name Overrides */ //@{ virtual int print(); //@} /**@name set and get */ //@{ /// Model const Cbc_Model * model() const; void setModel(Cbc_Model * model); /// Call back void setCallBack(cbc_callback callback); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ Cbc_MessageHandler(); /// Constructor with pointer to model Cbc_MessageHandler(Cbc_Model * model, FILE * userPointer = NULL); /** Destructor */ virtual ~Cbc_MessageHandler(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ Cbc_MessageHandler(const Cbc_MessageHandler&); /** The copy constructor from an CoinSimplexMessageHandler. */ Cbc_MessageHandler(const CoinMessageHandler&); Cbc_MessageHandler& operator=(const Cbc_MessageHandler&); /// Clone virtual CoinMessageHandler * clone() const ; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Pointer back to model Cbc_Model * model_; /// call back cbc_callback callback_; //@} }; //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- Cbc_MessageHandler::Cbc_MessageHandler () : CoinMessageHandler(), model_(NULL), callback_(NULL) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- Cbc_MessageHandler::Cbc_MessageHandler (const Cbc_MessageHandler & rhs) : CoinMessageHandler(rhs), model_(rhs.model_), callback_(rhs.callback_) { } Cbc_MessageHandler::Cbc_MessageHandler (const CoinMessageHandler & rhs) : CoinMessageHandler(rhs), model_(NULL), callback_(NULL) { } // Constructor with pointer to model Cbc_MessageHandler::Cbc_MessageHandler(Cbc_Model * model, FILE * /*userPointer*/) : CoinMessageHandler(), model_(model), callback_(NULL) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- Cbc_MessageHandler::~Cbc_MessageHandler () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- Cbc_MessageHandler & Cbc_MessageHandler::operator=(const Cbc_MessageHandler & rhs) { if (this != &rhs) { CoinMessageHandler::operator=(rhs); model_ = rhs.model_; callback_ = rhs.callback_; } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- CoinMessageHandler * Cbc_MessageHandler::clone() const { return new Cbc_MessageHandler(*this); } int Cbc_MessageHandler::print() { if (callback_) { int messageNumber = currentMessage().externalNumber(); if (currentSource() != "Cbc") messageNumber += 1000000; int i; int nDouble = numberDoubleFields(); assert (nDouble <= 200); double vDouble[200]; for (i = 0; i < nDouble; i++) vDouble[i] = doubleValue(i); int nInt = numberIntFields(); assert (nInt <= 200); int vInt[200]; for (i = 0; i < nInt; i++) vInt[i] = intValue(i); int nString = numberStringFields(); assert (nString <= 200); char * vString[200]; for (i = 0; i < nString; i++) { std::string value = stringValue(i); vString[i] = CoinStrdup(value.c_str()); } callback_(model_, messageNumber, nDouble, vDouble, nInt, vInt, nString, vString); for (i = 0; i < nString; i++) free(vString[i]); } return CoinMessageHandler::print(); return 0; } const Cbc_Model * Cbc_MessageHandler::model() const { return model_; } void Cbc_MessageHandler::setModel(Cbc_Model * model) { model_ = model; } // Call back void Cbc_MessageHandler::setCallBack(cbc_callback callback) { callback_ = callback; } /** * * C Interface Routines * */ #include "Cbc_C_Interface.h" #include #include #include #if defined(__MWERKS__) #pragma export on #endif /* Version */ COINLIBAPI const char* COINLINKAGE Cbc_getVersion() { return CBC_VERSION; } /* Default Cbc_Model constructor */ COINLIBAPI Cbc_Model * COINLINKAGE Cbc_newModel() { const char prefix[] = "Cbc_C_Interface::Cbc_newModel(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); Cbc_Model * model = new Cbc_Model(); OsiClpSolverInterface solver1; model->solver_ = &solver1; model->model_ = new CbcModel(solver1); CbcMain0(*model->model_); model->handler_ = NULL; if (VERBOSE > 0) printf("%s return\n", prefix); return model; } /* Cbc_Model Destructor */ COINLIBAPI void COINLINKAGE Cbc_deleteModel(Cbc_Model * model) { const char prefix[] = "Cbc_C_Interface::Cbc_deleteModel(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); fflush(stdout); if (VERBOSE > 1) printf("%s delete model->model_\n", prefix); fflush(stdout); delete model->model_; if (VERBOSE > 1) printf("%s delete model->handler_\n", prefix); fflush(stdout); delete model->handler_; if (VERBOSE > 1) printf("%s delete model\n", prefix); fflush(stdout); delete model; if (VERBOSE > 0) printf("%s return\n", prefix); fflush(stdout); } /* Loads a problem (the constraints on the rows are given by lower and upper bounds). If a pointer is NULL then the following values are the default:
  • colub: all columns have upper bound infinity
  • collb: all columns have lower bound 0
  • rowub: all rows have upper bound infinity
  • rowlb: all rows have lower bound -infinity
  • obj: all variables have 0 objective coefficient
Just like the other loadProblem() method except that the matrix is given in a standard column major ordered format (without gaps). */ COINLIBAPI void COINLINKAGE Cbc_loadProblem (Cbc_Model * model, const int numcols, const int numrows, const CoinBigIndex * start, const int* index, const double* value, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub) { const char prefix[] = "Cbc_C_Interface::Cbc_loadProblem(): "; // const int VERBOSE = 2; if (VERBOSE > 0) printf("%s begin\n", prefix); OsiSolverInterface * solver = model->model_->solver(); if (VERBOSE > 1) { printf("%s numcols = %i, numrows = %i\n", prefix, numcols, numrows); printf("%s model = %p, start = %p, index = %p, value = %p\n", prefix, static_cast(model), static_cast(start), static_cast(index), static_cast(value)); printf("%s collb = %p, colub = %p, obj = %p, rowlb = %p, rowub = %p\n", prefix, static_cast(collb), static_cast(colub), static_cast(obj), static_cast(rowlb), static_cast(rowub)); } if (VERBOSE > 1) printf("%s Calling solver->loadProblem()\n", prefix); fflush(stdout); solver->loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); if (VERBOSE > 1) printf("%s Finished solver->loadProblem()\n", prefix); fflush(stdout); if (VERBOSE > 0) printf("%s return\n", prefix); } // Cbc_loadProblem() /* Read an mps file from the given filename */ COINLIBAPI int COINLINKAGE Cbc_readMps(Cbc_Model * model, const char *filename) { const char prefix[] = "Cbc_C_Interface::Cbc_readMps(): "; // const int VERBOSE = 2; if (VERBOSE > 0) printf("%s begin\n", prefix); if (VERBOSE > 1) printf("%s filename = '%s'\n", prefix, filename); int result = 1; result = model->model_->solver()->readMps(filename); assert(result == 0); if (VERBOSE > 0) printf("%s return %i\n", prefix, result); return result; } /* Write an mps file from the given filename */ COINLIBAPI void COINLINKAGE Cbc_writeMps(Cbc_Model * model, const char *filename) { const char prefix[] = "Cbc_C_Interface::Cbc_writeMps(): "; // const int VERBOSE = 2; if (VERBOSE > 0) printf("%s begin\n", prefix); if (VERBOSE > 1) printf("%s filename = '%s'\n", prefix, filename); model->model_->solver()->writeMps(filename, "mps", Cbc_getObjSense(model)); if (VERBOSE > 0) printf("%s return\n", prefix); return; } COINLIBAPI void COINLINKAGE Cbc_setInitialSolution(Cbc_Model *model, const double * sol) { int n = Cbc_getNumCols(model); // We need to manually compute the objective here for some reason const double *objvec = Cbc_getObjCoefficients(model); double objval = 0; for (int i = 0; i < n; i++) { objval += objvec[i]*sol[i]; } model->model_->setBestSolution(sol, n, objval, true); } COINLIBAPI void COINLINKAGE Cbc_setParameter(Cbc_Model * model, const char * name, const char * value) { model->cmdargs_.push_back(std::string("-")+name); model->cmdargs_.push_back(value); } /* Fills in array with problem name */ COINLIBAPI void COINLINKAGE Cbc_problemName(Cbc_Model * model, int maxNumberCharacters, char * array) { std::string name; model->model_->solver()->getStrParam(OsiProbName, name); strncpy(array, name.c_str(), maxNumberCharacters); } /* Sets problem name. Must have \0 at end. */ COINLIBAPI int COINLINKAGE Cbc_setProblemName(Cbc_Model * model, const char * array) { bool result = false; result = model->model_->solver()->setStrParam(OsiProbName, array); return (result) ? 1 : 0; } CbcGetProperty(int, status) CbcGetProperty(int, secondaryStatus) /* Number of elements in matrix */ COINLIBAPI int COINLINKAGE Cbc_getNumElements(Cbc_Model * model) { const char prefix[] = "Cbc_C_Interface::Cbc_getNumElements(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); int result = 0; result = model->model_->getNumElements(); if (VERBOSE > 0) printf("%s return %i\n", prefix, result); return result; } // Column starts in matrix COINLIBAPI const CoinBigIndex * COINLINKAGE Cbc_getVectorStarts(Cbc_Model * model) { const CoinPackedMatrix * matrix = NULL; matrix = model->model_->solver()->getMatrixByCol(); return (matrix == NULL) ? NULL : matrix->getVectorStarts(); } // Row indices in matrix COINLIBAPI const int * COINLINKAGE Cbc_getIndices(Cbc_Model * model) { const char prefix[] = "Cbc_C_Interface::Cbc_getIndices(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); const int * result = NULL; const CoinPackedMatrix * matrix = NULL; matrix = model->model_->solver()->getMatrixByCol(); result = (matrix == NULL) ? NULL : matrix->getIndices(); if (VERBOSE > 0) printf("%s return %p\n", prefix, static_cast(result)); return result; } // Element values in matrix COINLIBAPI const double * COINLINKAGE Cbc_getElements(Cbc_Model * model) { const char prefix[] = "Cbc_C_Interface::Cbc_getElements(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); const double * result = NULL; const CoinPackedMatrix * matrix = NULL; matrix = model->model_->solver()->getMatrixByCol(); result = (matrix == NULL) ? NULL : matrix->getElements(); if (VERBOSE > 0) printf("%s return %p\n", prefix, static_cast(result)); return result; } // ====================================================================== /* Pass in Callback function */ COINLIBAPI void COINLINKAGE Cbc_registerCallBack(Cbc_Model * model, cbc_callback userCallBack) { const char prefix[] = "Cbc_C_Interface::Cbc_registerCallBack(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); // Will be copy of users one delete model->handler_; model->handler_ = new Cbc_MessageHandler(*(model->model_->messageHandler())); model->handler_->setCallBack(userCallBack); model->handler_->setModel(model); model->model_->passInMessageHandler(model->handler_); if (VERBOSE > 0) printf("%s return\n", prefix); } /* Unset Callback function */ COINLIBAPI void COINLINKAGE Cbc_clearCallBack(Cbc_Model * model) { const char prefix[] = "Cbc_C_Interface::Cbc_clearCallBack(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); delete model->handler_; model->handler_ = NULL; if (VERBOSE > 0) printf("%s return\n", prefix); } /* length of names (0 means no names0 */ COINLIBAPI size_t COINLINKAGE Cbc_maxNameLength(Cbc_Model * model) { size_t result = 0; OsiSolverInterface::OsiNameVec const & rownames = model->model_->solver()->getRowNames(); for (size_t i = 0; i < rownames.size(); i++) { if (rownames[i].length() > result) result = rownames[i].length(); } OsiSolverInterface::OsiNameVec const & colnames = model->model_->solver()->getColNames(); for (size_t i = 0; i < colnames.size(); i++) { if (colnames[i].length() > result) result = colnames[i].length(); } return result; } COINLIBAPI void COINLINKAGE Cbc_getRowName(Cbc_Model * model, int iRow, char * name, size_t maxLength) { std::string rowname = model->model_->solver()->getRowName(iRow); strncpy(name, rowname.c_str(), maxLength); name[maxLength-1] = '\0'; } COINLIBAPI void COINLINKAGE Cbc_getColName(Cbc_Model * model, int iRow, char * name, size_t maxLength) { std::string colname = model->model_->solver()->getColName(iRow); strncpy(name, colname.c_str(), maxLength); name[maxLength-1] = '\0'; } COINLIBAPI void COINLINKAGE Cbc_setColName(Cbc_Model * model, int iColumn, const char * name) { model->model_->solver()->setColName(iColumn, name); } COINLIBAPI void COINLINKAGE Cbc_setRowName(Cbc_Model * model, int iRow, const char * name) { model->model_->solver()->setRowName(iRow, name); } COINLIBAPI int COINLINKAGE Cbc_solve(Cbc_Model * model) { const char prefix[] = "Cbc_C_Interface::Cbc_solve(): "; int result = 0; std::vector argv; argv.push_back("Cbc_C_Interface"); for (size_t i = 0; i < model->cmdargs_.size(); i++) { argv.push_back(model->cmdargs_[i].c_str()); } argv.push_back("-solve"); argv.push_back("-quit"); try { CbcMain1((int)argv.size(), &argv[0], *model->model_); } catch (CoinError e) { printf("%s ERROR: %s::%s, %s\n", prefix, e.className().c_str(), e.methodName().c_str(), e.message().c_str()); } result = model->model_->status(); return result; } /* Sum of primal infeasibilities */ COINLIBAPI double COINLINKAGE Cbc_sumPrimalInfeasibilities(Cbc_Model * /*model*/) { const char prefix[] = "Cbc_C_Interface::Cbc_sumPrimalInfeasibilities(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); double result = 0; // cannot find names in Cbc, Osi, or OsiClp //tbd result = model->model_->sumPrimalInfeasibilities(); if (VERBOSE > 0) printf("%s WARNING: NOT IMPLEMENTED\n", prefix); if (VERBOSE > 0) printf("%s return %g\n", prefix, result); return result; } /* Number of primal infeasibilities */ COINLIBAPI int COINLINKAGE Cbc_numberPrimalInfeasibilities(Cbc_Model * /*model*/) { const char prefix[] = "Cbc_C_Interface::Cbc_numberPrimalInfeasibilities(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); int result = 0; //tbd result = model->model_->getContinuousInfeasibilities(); if (VERBOSE > 0) printf("%s WARNING: NOT IMPLEMENTED\n", prefix); if (VERBOSE > 0) printf("%s return %i\n", prefix, result); return result; } /** Call this to really test if a valid solution can be feasible Solution is number columns in size. If fixVariables true then bounds of continuous solver updated. Returns objective value (worse than cutoff if not feasible) */ COINLIBAPI void COINLINKAGE Cbc_checkSolution(Cbc_Model * /*model*/) { const char prefix[] = "Cbc_C_Interface::Cbc_checkSolution(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); // see CbcModel::checkSolution(double cutoff, const double * solution, // bool fixVariables); // model->model_->checkSolution(); if (VERBOSE > 0) printf("%s return\n", prefix); return; } CbcGetProperty(int, getNumCols) CbcGetProperty(int, getNumRows) CbcGetProperty(int, getIterationCount) CbcGetProperty(int, isAbandoned) CbcGetProperty(int, isProvenOptimal) CbcGetProperty(int, isProvenInfeasible) CbcGetProperty(int, isContinuousUnbounded) CbcGetProperty(int, isNodeLimitReached) CbcGetProperty(int, isSecondsLimitReached) CbcGetProperty(int, isSolutionLimitReached) CbcGetProperty(int, isInitialSolveAbandoned) CbcGetProperty(int, isInitialSolveProvenOptimal) CbcGetProperty(int, isInitialSolveProvenPrimalInfeasible) CbcGetProperty(double, getObjSense) COINLIBAPI void COINLINKAGE Cbc_setObjSense(Cbc_Model * model, double sense) { model->model_->setObjSense(sense); } CbcGetProperty(const double*, getRowActivity) CbcGetProperty(const double*, getColSolution) CbcGetProperty(const double*, getRowLower) CbcSetSolverProperty(double, setRowLower) CbcGetProperty(const double*, getRowUpper) CbcSetSolverProperty(double, setRowUpper) CbcGetProperty(const double*, getObjCoefficients) CbcSetSolverProperty(double, setObjCoeff) CbcGetProperty(const double*, getColLower) CbcSetSolverProperty(double, setColLower) CbcGetProperty(const double*, getColUpper) CbcSetSolverProperty(double, setColUpper) CbcGetProperty(double, getObjValue) CbcGetProperty(double, getBestPossibleObjValue) /* Print model */ COINLIBAPI void COINLINKAGE Cbc_printModel(Cbc_Model * model, const char * argPrefix) { const char prefix[] = "Cbc_C_Interface::Cbc_printModel(): "; const int VERBOSE = 4; if (VERBOSE > 0) printf("%s begin\n", prefix); CbcModel *cbc_model = model->model_; int numrows = cbc_model->getNumRows(); int numcols = cbc_model->getNumCols(); int numelem = cbc_model->getNumElements(); const CoinPackedMatrix * matrix = cbc_model->solver()->getMatrixByCol(); const CoinBigIndex * start = matrix->getVectorStarts(); const int * index = matrix->getIndices(); const double * value = matrix->getElements(); const double * collb = cbc_model->getColLower(); const double * colub = cbc_model->getColUpper(); const double * obj = cbc_model->getObjCoefficients(); const double * rowlb = cbc_model->getRowLower(); const double * rowub = cbc_model->getRowUpper(); printf("%s numcols = %i, numrows = %i, numelem = %i\n", argPrefix, numcols, numrows, numelem); printf("%s model = %p, start = %p, index = %p, value = %p\n", argPrefix, static_cast(model), static_cast(start), static_cast(index), static_cast(value)); matrix->dumpMatrix(NULL); { int i; for (i = 0; i <= numcols; i++) printf("%s start[%i] = %i\n", argPrefix, i, start[i]); for (i = 0; i < numelem; i++) printf("%s index[%i] = %i, value[%i] = %g\n", argPrefix, i, index[i], i, value[i]); } printf("%s collb = %p, colub = %p, obj = %p, rowlb = %p, rowub = %p\n", argPrefix, static_cast(collb), static_cast(colub), static_cast(obj), static_cast(rowlb), static_cast(rowub)); printf("%s optimization direction = %g\n", argPrefix, Cbc_getObjSense(model)); printf(" (1 - minimize, -1 - maximize, 0 - ignore)\n"); { int i; for (i = 0; i < numcols; i++) printf("%s collb[%i] = %g, colub[%i] = %g, obj[%i] = %g\n", argPrefix, i, collb[i], i, colub[i], i, obj[i]); for (i = 0; i < numrows; i++) printf("%s rowlb[%i] = %g, rowub[%i] = %g\n", argPrefix, i, rowlb[i], i, rowub[i]); } if (VERBOSE > 0) printf("%s return\n", prefix); } // Cbc_printModel() COINLIBAPI int COINLINKAGE Cbc_isInteger(Cbc_Model * model, int i) { const char prefix[] = "Cbc_C_Interface::Cbc_isInteger(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); bool result = false; result = model->model_->isInteger(i); if (VERBOSE > 0) printf("%s return %i\n", prefix, result); return (result) ? 1 : 0; } CbcGetProperty(int, getNodeCount) /** Return a copy of this model */ COINLIBAPI Cbc_Model * COINLINKAGE Cbc_clone(Cbc_Model * model) { const char prefix[] = "Cbc_C_Interface::Cbc_clone(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); Cbc_Model * result = new Cbc_Model(); result->model_ = new CbcModel(*(model->model_)); result->solver_ = dynamic_cast< OsiClpSolverInterface*> (result->model_->solver()); result->handler_ = NULL; result->cmdargs_ = model->cmdargs_; if (VERBOSE > 0) printf("%s return\n", prefix); return model; } /** Set this the variable to be continuous */ COINLIBAPI void COINLINKAGE Cbc_setContinuous(Cbc_Model * model, int iColumn) { const char prefix[] = "Cbc_C_Interface::Cbc_setContinuous(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); model->model_->solver()->setContinuous(iColumn); if (VERBOSE > 0) printf("%s return\n", prefix); } /** Set this the variable to be integer */ COINLIBAPI void COINLINKAGE Cbc_setInteger(Cbc_Model * model, int iColumn) { const char prefix[] = "Cbc_C_Interface::Cbc_setContinuous(): "; // const int VERBOSE = 1; if (VERBOSE > 0) printf("%s begin\n", prefix); model->model_->solver()->setInteger(iColumn); if (VERBOSE > 0) printf("%s return\n", prefix); } /** Add SOS constraints to the model using row-order matrix */ COINLIBAPI void COINLINKAGE Cbc_addSOS(Cbc_Model * model, int numRows, const int * rowStarts, const int * colIndices, const double * weights, const int type) { const char prefix[] = "Cbc_C_Interface::Cbc_addSOS(): "; //const int VERBOSE = 4; if (VERBOSE > 0) printf("%sbegin\n", prefix); if (VERBOSE > 0) printf("%s numRows = %i\n", prefix, numRows); int row, i; const int *colIndex; const double *colWeight; // loop on rows and count number of objects according to numWeights>0 int numObjects = 0; for (row = 0; row < numRows; row++) { if (VERBOSE > 2) { printf("%s row = %i\n", prefix, row); printf("%s rowStarts[%i] = %i\n", prefix, row, rowStarts[row]); printf("%s rowStarts[%i+1] = %i\n", prefix, row, rowStarts[row+1]); fflush(stdout); } const int numWeights = rowStarts[row+1] - rowStarts[row]; if (VERBOSE > 2) printf("%s numWeights = %i\n", prefix, numWeights); if (numWeights > 0) numObjects++; } // make objects CbcObject ** objects = new CbcObject * [numObjects]; // if (VERBOSE>1) printf("%s numObjects = %i, objects = %X\n",prefix,numObjects,objects); // loop on rows and make an object when numWeights>0 int objNum = 0; for (row = 0; row < numRows; row++) { if (VERBOSE > 2) { printf("%s row = %i\n", prefix, row); printf("%s rowStarts[%i] = %i\n", prefix, row, rowStarts[row]); printf("%s rowStarts[%i+1] = %i\n", prefix, row, rowStarts[row+1]); } const int numWeights = rowStarts[row+1] - rowStarts[row]; if (VERBOSE > 2) printf("%s numWeights = %i\n", prefix, numWeights); colIndex = colIndices + rowStarts[row]; colWeight = weights + rowStarts[row]; if (numWeights > 0) { // Make a CbcSOS and assign it to objects if (VERBOSE > 3) { for (i = 0; i < numWeights; i++) { printf("%s colIndex [%i] = %i\n", prefix, i, colIndex[i]); printf("%s colWeight[%i] = %f\n", prefix, i, colWeight[i]); } fflush(stdout); } objects[objNum] = new CbcSOS(model->model_, (int)(numWeights), (const int*)colIndex, (const double*)colWeight, (int)objNum, (int)type); // if (VERBOSE>2) printf("%s objects[%i] = %X\n",prefix,objNum,objects[objNum]); if (objects[objNum] == NULL) { printf("%s ERROR: objects[%i] == NULL\n", prefix, objNum); fflush(stdout); assert(objects[objNum] != NULL); } objNum++; } } if (VERBOSE > 2) { printf("%s calling addObjects()\n", prefix); // printf("%s numObjects = %i, objects = %X\n",prefix,numObjects,objects); // for (row=0; rowmodel_->addObjects(numObjects, objects); if (VERBOSE > 1) printf("%s finished addObjects()\n", prefix); for (objNum = 0; objNum < numObjects; objNum++) delete objects[objNum]; delete [] objects; if (VERBOSE > 0) printf("%sreturn\n", prefix); return; } /** Print the solution */ COINLIBAPI void COINLINKAGE Cbc_printSolution(Cbc_Model * model) { { // // Now to print out row solution. The methods used return const // pointers - which is of course much more virtuous. // // This version just does non-zero columns // // * Rows int numberRows = Cbc_getNumRows(model); int iRow; const double * rowPrimal = Cbc_getRowActivity(model); const double * rowLower = Cbc_getRowLower(model); const double * rowUpper = Cbc_getRowUpper(model); printf("--------------------------------------\n"); // * If we have not kept names (parameter to readMps) this will be 0 // assert(Cbc_lengthNames(model)); printf(" Primal Lower Upper\n"); for (iRow = 0; iRow < numberRows; iRow++) { double value; value = rowPrimal[iRow]; if (value > 1.0e-8 || value < -1.0e-8) { char name[20]; // Cbc_columnName(model,iColumn,name); sprintf(name, "ROW%5i", iRow); printf("%6d %8s", iRow, name); printf(" %13g", rowPrimal[iRow]); printf(" %13g", rowLower[iRow]); printf(" %13g", rowUpper[iRow]); printf("\n"); } } printf("--------------------------------------\n"); } { // // Now to print out column solution. The methods used return const // pointers - which is of course much more virtuous. // // This version just does non-zero columns // // // * Columns int numberColumns = Cbc_getNumCols(model); int iColumn; const double * columnPrimal = Cbc_getColSolution(model); const double * columnLower = Cbc_getColLower(model); const double * columnUpper = Cbc_getColUpper(model); const double * columnObjective = Cbc_getObjCoefficients(model); printf("--------------------------------------\n"); // * If we have not kept names (parameter to readMps) this will be 0 // assert(Cbc_lengthNames(model)); printf(" Primal Lower Upper Cost isInteger\n"); for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value; value = columnPrimal[iColumn]; if (value > 1.0e-8 || value < -1.0e-8) { char name[20]; // Cbc_columnName(model,iColumn,name); sprintf(name, "COL%5i", iColumn); printf("%6d %8s", iColumn, name); printf(" %13g", columnPrimal[iColumn]); printf(" %13g", columnLower[iColumn]); printf(" %13g", columnUpper[iColumn]); printf(" %13g", columnObjective[iColumn]); printf(" %13i", Cbc_isInteger(model,iColumn)); printf("\n"); } } printf("--------------------------------------\n"); } if (0) Cbc_printModel(model, "cbc::main(): "); return; } #if defined(__MWERKS__) #pragma export off #endif Cbc-2.8.12/src/CbcLinked.cpp0000644000076600007660000115707712131315050014073 0ustar coincoin/* $Id: CbcLinked.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CbcConfig.h" #include "CoinTime.hpp" #include "CoinHelperFunctions.hpp" #include "CoinModel.hpp" #include "ClpSimplex.hpp" // returns jColumn (-2 if linear term, -1 if unknown) and coefficient static int decodeBit(char * phrase, char * & nextPhrase, double & coefficient, bool ifFirst, const CoinModel & model) { char * pos = phrase; // may be leading - (or +) char * pos2 = pos; double value = 1.0; if (*pos2 == '-' || *pos2 == '+') pos2++; // next terminator * or + or - while (*pos2) { if (*pos2 == '*') { break; } else if (*pos2 == '-' || *pos2 == '+') { if (pos2 == pos || *(pos2 - 1) != 'e') break; } pos2++; } // if * must be number otherwise must be name if (*pos2 == '*') { char * pos3 = pos; while (pos3 != pos2) { pos3++; #ifndef NDEBUG char x = *(pos3 - 1); assert ((x >= '0' && x <= '9') || x == '.' || x == '+' || x == '-' || x == 'e'); #endif } char saved = *pos2; *pos2 = '\0'; value = atof(pos); *pos2 = saved; // and down to next pos2++; pos = pos2; while (*pos2) { if (*pos2 == '-' || *pos2 == '+') break; pos2++; } } char saved = *pos2; *pos2 = '\0'; // now name // might have + or - if (*pos == '+') { pos++; } else if (*pos == '-') { pos++; assert (value == 1.0); value = - value; } int jColumn = model.column(pos); // must be column unless first when may be linear term if (jColumn < 0) { if (ifFirst) { char * pos3 = pos; while (pos3 != pos2) { pos3++; #ifndef NDEBUG char x = *(pos3 - 1); assert ((x >= '0' && x <= '9') || x == '.' || x == '+' || x == '-' || x == 'e'); #endif } assert(*pos2 == '\0'); // keep possible - value = value * atof(pos); jColumn = -2; } else { // bad *pos2 = saved; printf("bad nonlinear term %s\n", phrase); abort(); } } *pos2 = saved; pos = pos2; coefficient = value; nextPhrase = pos; return jColumn; } #include "ClpQuadraticObjective.hpp" #include #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcLinked.hpp" #include "CoinIndexedVector.hpp" #include "CoinMpsIO.hpp" //#include "OsiSolverLink.hpp" //#include "OsiBranchLink.hpp" #include "ClpPackedMatrix.hpp" #include "CoinTime.hpp" #include "CbcModel.hpp" #include "CbcCutGenerator.hpp" #include "CglStored.hpp" #include "CglPreProcess.hpp" #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglRedSplit.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding2.hpp" #include "CglTwomir.hpp" #include "CglDuplicateRow.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcHeuristic.hpp" #include "CbcHeuristicLocal.hpp" #include "CbcHeuristicGreedy.hpp" #include "ClpLinearObjective.hpp" #include "CbcBranchActual.hpp" #include "CbcCompareActual.hpp" //############################################################################# // Solve methods //############################################################################# void OsiSolverLink::initialSolve() { //writeMps("yy"); //exit(77); specialOptions_ = 0; modelPtr_->setWhatsChanged(0); if (numberVariables_) { CoinPackedMatrix * temp = new CoinPackedMatrix(*matrix_); // update all bounds before coefficients for (int i = 0; i < numberVariables_; i++ ) { info_[i].updateBounds(modelPtr_); } int updated = updateCoefficients(modelPtr_, temp); if (updated || 1) { temp->removeGaps(1.0e-14); ClpMatrixBase * save = modelPtr_->clpMatrix(); ClpPackedMatrix * clpMatrix = dynamic_cast (save); assert (clpMatrix); if (save->getNumRows() > temp->getNumRows()) { // add in cuts int numberRows = temp->getNumRows(); int * which = new int[numberRows]; for (int i = 0; i < numberRows; i++) which[i] = i; save->deleteRows(numberRows, which); delete [] which; temp->bottomAppendPackedMatrix(*clpMatrix->matrix()); } modelPtr_->replaceMatrix(temp, true); } else { delete temp; } } if (0) { const double * lower = getColLower(); const double * upper = getColUpper(); int n = 0; for (int i = 84; i < 84 + 16; i++) { if (lower[i] + 0.01 < upper[i]) { n++; } } if (!n) writeMps("sol_query"); } //static int iPass=0; //char temp[50]; //iPass++; //sprintf(temp,"cc%d",iPass); //writeMps(temp); //writeMps("tight"); //exit(33); //printf("wrote cc%d\n",iPass); OsiClpSolverInterface::initialSolve(); int secondaryStatus = modelPtr_->secondaryStatus(); if (modelPtr_->status() == 0 && (secondaryStatus == 2 || secondaryStatus == 4)) modelPtr_->cleanup(1); //if (!isProvenOptimal()) //writeMps("yy"); if (isProvenOptimal() && quadraticModel_ && modelPtr_->numberColumns() == quadraticModel_->numberColumns()) { // see if qp can get better solution const double * solution = modelPtr_->primalColumnSolution(); int numberColumns = modelPtr_->numberColumns(); bool satisfied = true; for (int i = 0; i < numberColumns; i++) { if (isInteger(i)) { double value = solution[i]; if (fabs(value - floor(value + 0.5)) > 1.0e-6) { satisfied = false; break; } } } if (satisfied) { ClpSimplex qpTemp(*quadraticModel_); double * lower = qpTemp.columnLower(); double * upper = qpTemp.columnUpper(); double * lower2 = modelPtr_->columnLower(); double * upper2 = modelPtr_->columnUpper(); for (int i = 0; i < numberColumns; i++) { if (isInteger(i)) { double value = floor(solution[i] + 0.5); lower[i] = value; upper[i] = value; } else { lower[i] = lower2[i]; upper[i] = upper2[i]; } } //qpTemp.writeMps("bad.mps"); //modelPtr_->writeMps("bad2.mps"); //qpTemp.objectiveAsObject()->setActivated(0); //qpTemp.primal(); //qpTemp.objectiveAsObject()->setActivated(1); qpTemp.primal(); //assert (!qpTemp.problemStatus()); if (qpTemp.objectiveValue() < bestObjectiveValue_ - 1.0e-3 && !qpTemp.problemStatus()) { delete [] bestSolution_; bestSolution_ = CoinCopyOfArray(qpTemp.primalColumnSolution(), numberColumns); bestObjectiveValue_ = qpTemp.objectiveValue(); printf("better qp objective of %g\n", bestObjectiveValue_); // If model has stored then add cut (if convex) if (cbcModel_ && (specialOptions2_&4) != 0) { int numberGenerators = cbcModel_->numberCutGenerators(); int iGenerator; cbcModel_->lockThread(); for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = cbcModel_->cutGenerator(iGenerator); CglCutGenerator * gen = generator->generator(); CglStored * gen2 = dynamic_cast (gen); if (gen2) { // add OA cut double offset; double * gradient = new double [numberColumns+1]; memcpy(gradient, qpTemp.objectiveAsObject()->gradient(&qpTemp, bestSolution_, offset, true, 2), numberColumns*sizeof(double)); // assume convex double rhs = 0.0; int * column = new int[numberColumns+1]; int n = 0; for (int i = 0; i < numberColumns; i++) { double value = gradient[i]; if (fabs(value) > 1.0e-12) { gradient[n] = value; rhs += value * solution[i]; column[n++] = i; } } gradient[n] = -1.0; column[n++] = objectiveVariable_; gen2->addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient); delete [] gradient; delete [] column; break; } } cbcModel_->unlockThread(); } } } } } //#define WRITE_MATRIX #ifdef WRITE_MATRIX static int xxxxxx = 0; #endif //----------------------------------------------------------------------------- void OsiSolverLink::resolve() { if (false) { bool takeHint; OsiHintStrength strength; // Switch off printing if asked to getHintParam(OsiDoReducePrint, takeHint, strength); if (strength != OsiHintIgnore && takeHint) { printf("no printing\n"); } else { printf("printing\n"); } } specialOptions_ = 0; modelPtr_->setWhatsChanged(0); bool allFixed = numberFix_ > 0; bool feasible = true; if (numberVariables_) { CoinPackedMatrix * temp = new CoinPackedMatrix(*matrix_); //bool best=true; const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); // update all bounds before coefficients for (int i = 0; i < numberVariables_; i++ ) { info_[i].updateBounds(modelPtr_); int iColumn = info_[i].variable(); double lo = lower[iColumn]; double up = upper[iColumn]; if (up < lo) feasible = false; } int updated = updateCoefficients(modelPtr_, temp); if (updated) { temp->removeGaps(1.0e-14); ClpMatrixBase * save = modelPtr_->clpMatrix(); ClpPackedMatrix * clpMatrix = dynamic_cast (save); assert (clpMatrix); if (save->getNumRows() > temp->getNumRows()) { // add in cuts int numberRows = temp->getNumRows(); int * which = new int[numberRows]; for (int i = 0; i < numberRows; i++) which[i] = i; CoinPackedMatrix * mat = clpMatrix->matrix(); // for debug //mat = new CoinPackedMatrix(*mat); mat->deleteRows(numberRows, which); delete [] which; temp->bottomAppendPackedMatrix(*mat); temp->removeGaps(1.0e-14); } modelPtr_->replaceMatrix(temp, true); modelPtr_->setNewRowCopy(NULL); modelPtr_->setClpScaledMatrix(NULL); } else { delete temp; } } #ifdef WRITE_MATRIX { xxxxxx++; char temp[50]; sprintf(temp, "bb%d", xxxxxx); writeMps(temp); printf("wrote bb%d\n", xxxxxx); } #endif if (0) { const double * lower = getColLower(); const double * upper = getColUpper(); int n = 0; for (int i = 60; i < 64; i++) { if (lower[i]) { printf("%d bounds %g %g\n", i, lower[i], upper[i]); n++; } } if (n == 1) printf("just one?\n"); } // check feasible { const double * lower = getColLower(); const double * upper = getColUpper(); int numberColumns = getNumCols(); for (int i = 0; i < numberColumns; i++) { if (lower[i] > upper[i] + 1.0e-12) { feasible = false; break; } } } if (!feasible) allFixed = false; if ((specialOptions2_&1) == 0) allFixed = false; int returnCode = -1; // See if in strong branching int maxIts = modelPtr_->maximumIterations(); if (feasible) { if (maxIts > 10000) { // may do lots of work if ((specialOptions2_&1) != 0) { // see if fixed const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); for (int i = 0; i < numberFix_; i++ ) { int iColumn = fixVariables_[i]; double lo = lower[iColumn]; double up = upper[iColumn]; if (up > lo) { allFixed = false; break; } } returnCode = allFixed ? fathom(allFixed) : 0; } else { returnCode = 0; } } else { returnCode = 0; } } if (returnCode >= 0) { if (returnCode == 0) OsiClpSolverInterface::resolve(); int satisfied = 2; const double * solution = getColSolution(); const double * lower = getColLower(); const double * upper = getColUpper(); int numberColumns2 = coinModel_.numberColumns(); for (int i = 0; i < numberColumns2; i++) { if (isInteger(i)) { double value = solution[i]; if (fabs(value - floor(value + 0.5)) > 1.0e-6) { satisfied = 0; break; } else if (upper[i] > lower[i]) { satisfied = 1; } } } if (isProvenOptimal()) { //if (satisfied==2) //printf("satisfied %d\n",satisfied); if (satisfied && (specialOptions2_&2) != 0) { assert (quadraticModel_); // look at true objective #ifndef NDEBUG double direction = modelPtr_->optimizationDirection(); assert (direction == 1.0); #endif double value = - quadraticModel_->objectiveOffset(); const double * objective = quadraticModel_->objective(); int i; for ( i = 0; i < numberColumns2; i++) value += solution[i] * objective[i]; // and now rest for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { value += obj->xyCoefficient(solution); } } if (value < bestObjectiveValue_ - 1.0e-3) { printf("obj of %g\n", value); //modelPtr_->setDualObjectiveLimit(value); delete [] bestSolution_; bestSolution_ = CoinCopyOfArray(modelPtr_->getColSolution(), modelPtr_->getNumCols()); bestObjectiveValue_ = value; if (maxIts <= 10000 && cbcModel_) { OsiSolverLink * solver2 = dynamic_cast (cbcModel_->solver()); assert (solver2); if (solver2 != this) { // in strong branching - need to store in original solver if (value < solver2->bestObjectiveValue_ - 1.0e-3) { delete [] solver2->bestSolution_; solver2->bestSolution_ = CoinCopyOfArray(bestSolution_, modelPtr_->getNumCols()); solver2->bestObjectiveValue_ = value; } } } // If model has stored then add cut (if convex) if (cbcModel_ && (specialOptions2_&4) != 0 && quadraticModel_) { int numberGenerators = cbcModel_->numberCutGenerators(); int iGenerator; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = cbcModel_->cutGenerator(iGenerator); CglCutGenerator * gen = generator->generator(); CglStored * gen2 = dynamic_cast (gen); if (gen2) { cbcModel_->lockThread(); // add OA cut double offset = 0.0; int numberColumns = quadraticModel_->numberColumns(); double * gradient = new double [numberColumns+1]; // gradient from bilinear int i; CoinZeroN(gradient, numberColumns + 1); //const double * objective = modelPtr_->objective(); assert (objectiveRow_ >= 0); const double * element = originalRowCopy_->getElements(); const int * column2 = originalRowCopy_->getIndices(); const CoinBigIndex * rowStart = originalRowCopy_->getVectorStarts(); //const int * rowLength = originalRowCopy_->getVectorLengths(); //int numberColumns2 = coinModel_.numberColumns(); for ( i = rowStart[objectiveRow_]; i < rowStart[objectiveRow_+1]; i++) gradient[column2[i]] = element[i]; for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { int xColumn = obj->xColumn(); int yColumn = obj->yColumn(); if (xColumn != yColumn) { double coefficient = /* 2.0* */obj->coefficient(); gradient[xColumn] += coefficient * solution[yColumn]; gradient[yColumn] += coefficient * solution[xColumn]; offset += coefficient * solution[xColumn] * solution[yColumn]; } else { double coefficient = obj->coefficient(); gradient[xColumn] += 2.0 * coefficient * solution[yColumn]; offset += coefficient * solution[xColumn] * solution[yColumn]; } } } // assume convex double rhs = 0.0; int * column = new int[numberColumns+1]; int n = 0; for (int i = 0; i < numberColumns; i++) { double value = gradient[i]; if (fabs(value) > 1.0e-12) { gradient[n] = value; rhs += value * solution[i]; column[n++] = i; } } gradient[n] = -1.0; column[n++] = objectiveVariable_; gen2->addCut(-COIN_DBL_MAX, offset + 1.0e-4, n, column, gradient); delete [] gradient; delete [] column; cbcModel_->unlockThread(); break; } } } } } else if (satisfied == 2) { // is there anything left to do? int i; int numberContinuous = 0; double gap = 0.0; for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0) { numberContinuous++; int xColumn = obj->xColumn(); double gapX = upper[xColumn] - lower[xColumn]; int yColumn = obj->yColumn(); double gapY = upper[yColumn] - lower[yColumn]; gap = CoinMax(gap, CoinMax(gapX, gapY)); } } } if (numberContinuous && 0) { // iterate to get solution and fathom node int numberColumns2 = coinModel_.numberColumns(); double * lower2 = CoinCopyOfArray(getColLower(), numberColumns2); double * upper2 = CoinCopyOfArray(getColUpper(), numberColumns2); while (gap > defaultMeshSize_) { gap *= 0.9; const double * solution = getColSolution(); double newGap = 0.0; for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj && (obj->branchingStrategy()&8) == 0) { if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0) { numberContinuous++; // need to make sure new xy value in range double xB[3]; double yB[3]; double xybar[4]; obj->getCoefficients(this, xB, yB, xybar); //double xyTrue = obj->xyCoefficient(solution); double xyLambda = 0.0; int firstLambda = obj->firstLambda(); for (int j = 0; j < 4; j++) { xyLambda += solution[firstLambda+j] * xybar[j]; } //printf ("x %d, y %d - true %g lambda %g\n",obj->xColumn(),obj->yColumn(), // xyTrue,xyLambda); int xColumn = obj->xColumn(); double gapX = upper[xColumn] - lower[xColumn]; int yColumn = obj->yColumn(); if (gapX > gap) { double value = solution[xColumn]; double newLower = CoinMax(lower2[xColumn], value - 0.5 * gap); double newUpper = CoinMin(upper2[xColumn], value + 0.5 * gap); if (newUpper - newLower < 0.99*gap) { if (newLower == lower2[xColumn]) newUpper = CoinMin(upper2[xColumn], newLower + gap); else if (newUpper == upper2[xColumn]) newLower = CoinMax(lower2[xColumn], newUpper - gap); } // see if problem #ifndef NDEBUG double lambda[4]; #endif xB[0] = newLower; xB[1] = newUpper; xB[2] = value; yB[2] = solution[yColumn]; xybar[0] = xB[0] * yB[0]; xybar[1] = xB[0] * yB[1]; xybar[2] = xB[1] * yB[0]; xybar[3] = xB[1] * yB[1]; #ifndef NDEBUG double infeasibility = obj->computeLambdas(xB, yB, xybar, lambda); assert (infeasibility < 1.0e-9); #endif setColLower(xColumn, newLower); setColUpper(xColumn, newUpper); } double gapY = upper[yColumn] - lower[yColumn]; if (gapY > gap) { double value = solution[yColumn]; double newLower = CoinMax(lower2[yColumn], value - 0.5 * gap); double newUpper = CoinMin(upper2[yColumn], value + 0.5 * gap); if (newUpper - newLower < 0.99*gap) { if (newLower == lower2[yColumn]) newUpper = CoinMin(upper2[yColumn], newLower + gap); else if (newUpper == upper2[yColumn]) newLower = CoinMax(lower2[yColumn], newUpper - gap); } // see if problem #ifndef NDEBUG double lambda[4]; #endif yB[0] = newLower; yB[1] = newUpper; xybar[0] = xB[0] * yB[0]; xybar[1] = xB[0] * yB[1]; xybar[2] = xB[1] * yB[0]; xybar[3] = xB[1] * yB[1]; #ifndef NDEBUG double infeasibility = obj->computeLambdas(xB, yB, xybar, lambda); assert (infeasibility < 1.0e-9); #endif setColLower(yColumn, newLower); setColUpper(yColumn, newUpper); } newGap = CoinMax(newGap, CoinMax(gapX, gapY)); } } } printf("solving with gap of %g\n", gap); //OsiClpSolverInterface::resolve(); initialSolve(); if (!isProvenOptimal()) break; } delete [] lower2; delete [] upper2; //if (isProvenOptimal()) //writeMps("zz"); } } // ??? - try // But skip if strong branching CbcModel * cbcModel = (modelPtr_->maximumIterations() > 10000) ? cbcModel_ : NULL; if ((specialOptions2_&2) != 0) { // If model has stored then add cut (if convex) // off until I work out problem with ibell3a if (cbcModel && (specialOptions2_&4) != 0 && quadraticModel_) { int numberGenerators = cbcModel_->numberCutGenerators(); int iGenerator; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = cbcModel_->cutGenerator(iGenerator); CglCutGenerator * gen = generator->generator(); CglTemporary * gen2 = dynamic_cast (gen); if (gen2) { double * solution2 = NULL; int numberColumns = quadraticModel_->numberColumns(); int depth = cbcModel_->currentNode() ? cbcModel_->currentNode()->depth() : 0; if (depth < 5) { ClpSimplex qpTemp(*quadraticModel_); double * lower = qpTemp.columnLower(); double * upper = qpTemp.columnUpper(); double * lower2 = modelPtr_->columnLower(); double * upper2 = modelPtr_->columnUpper(); for (int i = 0; i < numberColumns; i++) { lower[i] = lower2[i]; upper[i] = upper2[i]; } qpTemp.setLogLevel(modelPtr_->logLevel()); qpTemp.primal(); assert (!qpTemp.problemStatus()); if (qpTemp.objectiveValue() < bestObjectiveValue_ - 1.0e-3 && !qpTemp.problemStatus()) { solution2 = CoinCopyOfArray(qpTemp.primalColumnSolution(), numberColumns); } else { printf("QP says expensive - kill\n"); modelPtr_->setProblemStatus(1); modelPtr_->setObjectiveValue(COIN_DBL_MAX); break; } } const double * solution = getColSolution(); // add OA cut doAOCuts(gen2, solution, solution); if (solution2) { doAOCuts(gen2, solution, solution2); delete [] solution2; } break; } } } } else if (cbcModel && (specialOptions2_&8) == 8) { // convex and nonlinear in constraints int numberGenerators = cbcModel_->numberCutGenerators(); int iGenerator; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = cbcModel_->cutGenerator(iGenerator); CglCutGenerator * gen = generator->generator(); CglTemporary * gen2 = dynamic_cast (gen); if (gen2) { const double * solution = getColSolution(); const double * rowUpper = getRowUpper(); const double * rowLower = getRowLower(); const double * element = originalRowCopy_->getElements(); const int * column2 = originalRowCopy_->getIndices(); const CoinBigIndex * rowStart = originalRowCopy_->getVectorStarts(); //const int * rowLength = originalRowCopy_->getVectorLengths(); int numberColumns2 = CoinMax(coinModel_.numberColumns(), objectiveVariable_ + 1); double * gradient = new double [numberColumns2]; int * column = new int[numberColumns2]; //const double * columnLower = modelPtr_->columnLower(); //const double * columnUpper = modelPtr_->columnUpper(); cbcModel_->lockThread(); for (int iNon = 0; iNon < numberNonLinearRows_; iNon++) { int iRow = rowNonLinear_[iNon]; bool convex = convex_[iNon] > 0; if (!convex_[iNon]) continue; // can't use this row // add OA cuts double offset = 0.0; // gradient from bilinear int i; CoinZeroN(gradient, numberColumns2); //const double * objective = modelPtr_->objective(); for ( i = rowStart[iRow]; i < rowStart[iRow+1]; i++) gradient[column2[i]] = element[i]; for ( i = startNonLinear_[iNon]; i < startNonLinear_[iNon+1]; i++) { OsiBiLinear * obj = dynamic_cast (object_[whichNonLinear_[i]]); assert (obj); int xColumn = obj->xColumn(); int yColumn = obj->yColumn(); if (xColumn != yColumn) { double coefficient = /* 2.0* */obj->coefficient(); gradient[xColumn] += coefficient * solution[yColumn]; gradient[yColumn] += coefficient * solution[xColumn]; offset += coefficient * solution[xColumn] * solution[yColumn]; } else { double coefficient = obj->coefficient(); gradient[xColumn] += 2.0 * coefficient * solution[yColumn]; offset += coefficient * solution[xColumn] * solution[yColumn]; } } // assume convex double rhs = 0.0; int n = 0; for (int i = 0; i < numberColumns2; i++) { double value = gradient[i]; if (fabs(value) > 1.0e-12) { gradient[n] = value; rhs += value * solution[i]; column[n++] = i; } } if (iRow == objectiveRow_) { gradient[n] = -1.0; assert (objectiveVariable_ >= 0); rhs -= solution[objectiveVariable_]; column[n++] = objectiveVariable_; assert (convex); } else if (convex) { offset += rowUpper[iRow]; } else if (!convex) { offset += rowLower[iRow]; } if (convex && rhs > offset + 1.0e-5) gen2->addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient); else if (!convex && rhs < offset - 1.0e-5) gen2->addCut(offset - 1.0e-7, COIN_DBL_MAX, n, column, gradient); } cbcModel_->unlockThread(); delete [] gradient; delete [] column; break; } } } } } else { modelPtr_->setProblemStatus(1); modelPtr_->setObjectiveValue(COIN_DBL_MAX); } } // Do OA cuts int OsiSolverLink::doAOCuts(CglTemporary * cutGen, const double * solution, const double * solution2) { cbcModel_->lockThread(); // add OA cut double offset = 0.0; int numberColumns = quadraticModel_->numberColumns(); double * gradient = new double [numberColumns+1]; // gradient from bilinear int i; CoinZeroN(gradient, numberColumns + 1); //const double * objective = modelPtr_->objective(); assert (objectiveRow_ >= 0); const double * element = originalRowCopy_->getElements(); const int * column2 = originalRowCopy_->getIndices(); const CoinBigIndex * rowStart = originalRowCopy_->getVectorStarts(); //const int * rowLength = originalRowCopy_->getVectorLengths(); //int numberColumns2 = coinModel_.numberColumns(); for ( i = rowStart[objectiveRow_]; i < rowStart[objectiveRow_+1]; i++) gradient[column2[i]] = element[i]; //const double * columnLower = modelPtr_->columnLower(); //const double * columnUpper = modelPtr_->columnUpper(); for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { int xColumn = obj->xColumn(); int yColumn = obj->yColumn(); if (xColumn != yColumn) { double coefficient = /* 2.0* */obj->coefficient(); gradient[xColumn] += coefficient * solution2[yColumn]; gradient[yColumn] += coefficient * solution2[xColumn]; offset += coefficient * solution2[xColumn] * solution2[yColumn]; } else { double coefficient = obj->coefficient(); gradient[xColumn] += 2.0 * coefficient * solution2[yColumn]; offset += coefficient * solution2[xColumn] * solution2[yColumn]; } } } // assume convex double rhs = 0.0; int * column = new int[numberColumns+1]; int n = 0; for (int i = 0; i < numberColumns; i++) { double value = gradient[i]; if (fabs(value) > 1.0e-12) { gradient[n] = value; rhs += value * solution[i]; column[n++] = i; } } gradient[n] = -1.0; assert (objectiveVariable_ >= 0); rhs -= solution[objectiveVariable_]; column[n++] = objectiveVariable_; int returnCode = 0; if (rhs > offset + 1.0e-5) { cutGen->addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient); //printf("added cut with %d elements\n",n); returnCode = 1; } delete [] gradient; delete [] column; cbcModel_->unlockThread(); return returnCode; } //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiSolverLink::OsiSolverLink () : CbcOsiSolver() { gutsOfDestructor(true); } #ifdef JJF_ZERO /* returns sequence of nonlinear or -1 numeric -2 not found -3 too many terms */ static int getVariable(const CoinModel & model, char * expression, int & linear) { int non = -1; linear = -1; if (strcmp(expression, "Numeric")) { // function char * first = strchr(expression, '*'); int numberColumns = model.numberColumns(); int j; if (first) { *first = '\0'; for (j = 0; j < numberColumns; j++) { if (!strcmp(expression, model.columnName(j))) { linear = j; memmove(expression, first + 1, strlen(first + 1) + 1); break; } } } // find nonlinear for (j = 0; j < numberColumns; j++) { const char * name = model.columnName(j); first = strstr(expression, name); if (first) { if (first != expression && isalnum(*(first - 1))) continue; // not real match first += strlen(name); if (!isalnum(*first)) { // match non = j; // but check no others j++; for (; j < numberColumns; j++) { const char * name = model.columnName(j); first = strstr(expression, name); if (first) { if (isalnum(*(first - 1))) continue; // not real match first += strlen(name); if (!isalnum(*first)) { // match - ouch non = -3; break; } } } break; } } } if (non == -1) non = -2; } return non; } #endif /* This creates from a coinModel object if errors.then number of sets is -1 This creates linked ordered sets information. It assumes - for product terms syntax is yy*f(zz) also just f(zz) is allowed and even a constant modelObject not const as may be changed as part of process. */ OsiSolverLink::OsiSolverLink ( CoinModel & coinModel) : CbcOsiSolver() { gutsOfDestructor(true); load(coinModel); } // need bounds static void fakeBounds(OsiSolverInterface * solver, int column, double maximumValue, CoinModel * model1, CoinModel * model2) { double lo = solver->getColLower()[column]; if (lo < -maximumValue) { solver->setColLower(column, -maximumValue); if (model1) model1->setColLower(column, -maximumValue); if (model2) model2->setColLower(column, -maximumValue); } double up = solver->getColUpper()[column]; if (up > maximumValue) { solver->setColUpper(column, maximumValue); if (model1) model1->setColUpper(column, maximumValue); if (model2) model2->setColUpper(column, maximumValue); } } void OsiSolverLink::load ( CoinModel & coinModelOriginal, bool tightenBounds, int logLevel) { // first check and set up arrays int numberColumns = coinModelOriginal.numberColumns(); int numberRows = coinModelOriginal.numberRows(); // List of nonlinear entries int * which = new int[numberColumns]; numberVariables_ = 0; //specialOptions2_=0; int iColumn; int numberErrors = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinModelLink triple = coinModelOriginal.firstInColumn(iColumn); bool linear = true; int n = 0; // See if quadratic objective const char * expr = coinModelOriginal.getColumnObjectiveAsString(iColumn); if (strcmp(expr, "Numeric")) { linear = false; } while (triple.row() >= 0) { int iRow = triple.row(); const char * expr = coinModelOriginal.getElementAsString(iRow, iColumn); if (strcmp(expr, "Numeric")) { linear = false; } triple = coinModelOriginal.next(triple); n++; } if (!linear) { which[numberVariables_++] = iColumn; } } // return if nothing if (!numberVariables_) { delete [] which; coinModel_ = coinModelOriginal; int nInt = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (coinModel_.isInteger(iColumn)) nInt++; } printf("There are %d integers\n", nInt); loadFromCoinModel(coinModelOriginal, true); OsiObject ** objects = new OsiObject * [nInt]; nInt = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (coinModel_.isInteger(iColumn)) { objects[nInt] = new OsiSimpleInteger(this, iColumn); objects[nInt]->setPriority(integerPriority_); nInt++; } } addObjects(nInt, objects); int i; for (i = 0; i < nInt; i++) delete objects[i]; delete [] objects; return; } else { coinModel_ = coinModelOriginal; // arrays for tightening bounds int * freeRow = new int [numberRows]; CoinZeroN(freeRow, numberRows); int * tryColumn = new int [numberColumns]; CoinZeroN(tryColumn, numberColumns); int nBi = 0; int numberQuadratic = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { // See if quadratic objective const char * expr = coinModel_.getColumnObjectiveAsString(iColumn); if (strcmp(expr, "Numeric")) { // check if value*x+-value*y.... assert (strlen(expr) < 20000); tryColumn[iColumn] = 1; char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; double linearTerm = 0.0; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_); // must be column unless first when may be linear term if (jColumn >= 0) { tryColumn[jColumn] = 1; numberQuadratic++; nBi++; } else if (jColumn == -2) { linearTerm = value; } else { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } coinModelOriginal.setObjective(iColumn, linearTerm); } } int iRow; int saveNBi = nBi; for (iRow = 0; iRow < numberRows; iRow++) { CoinModelLink triple = coinModel_.firstInRow(iRow); while (triple.column() >= 0) { int iColumn = triple.column(); const char * el = coinModel_.getElementAsString(iRow, iColumn); if (strcmp("Numeric", el)) { // check if value*x+-value*y.... assert (strlen(el) < 20000); char temp[20000]; strcpy(temp, el); char * pos = temp; bool ifFirst = true; double linearTerm = 0.0; tryColumn[iColumn] = 1; freeRow[iRow] = 1; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_); // must be column unless first when may be linear term if (jColumn >= 0) { tryColumn[jColumn] = 1; nBi++; } else if (jColumn == -2) { linearTerm = value; } else { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } coinModelOriginal.setElement(iRow, iColumn, linearTerm); } triple = coinModel_.next(triple); } } if (!nBi) exit(1); bool quadraticObjective = false; int nInt = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (coinModel_.isInteger(iColumn)) nInt++; } printf("There are %d bilinear and %d integers\n", nBi, nInt); loadFromCoinModel(coinModelOriginal, true); CoinModel coinModel = coinModelOriginal; if (tightenBounds && numberColumns < 100) { // first fake bounds for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (tryColumn[iColumn]) { fakeBounds(this, iColumn, defaultBound_, &coinModel, &coinModel_); } } ClpSimplex tempModel(*modelPtr_); int nDelete = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (freeRow[iRow]) freeRow[nDelete++] = iRow; } tempModel.deleteRows(nDelete, freeRow); tempModel.setOptimizationDirection(1.0); if (logLevel < 3) { tempModel.setLogLevel(0); tempModel.setSpecialOptions(32768); } double * objective = tempModel.objective(); CoinZeroN(objective, numberColumns); // now up and down double * columnLower = modelPtr_->columnLower(); double * columnUpper = modelPtr_->columnUpper(); const double * solution = tempModel.primalColumnSolution(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (tryColumn[iColumn]) { objective[iColumn] = 1.0; tempModel.primal(1); if (solution[iColumn] > columnLower[iColumn] + 1.0e-3) { double value = solution[iColumn]; if (coinModel_.isInteger(iColumn)) value = ceil(value - 0.9e-3); if (logLevel > 1) printf("lower bound on %d changed from %g to %g\n", iColumn, columnLower[iColumn], value); columnLower[iColumn] = value; coinModel_.setColumnLower(iColumn, value); coinModel.setColumnLower(iColumn, value); } objective[iColumn] = -1.0; tempModel.primal(1); if (solution[iColumn] < columnUpper[iColumn] - 1.0e-3) { double value = solution[iColumn]; if (coinModel_.isInteger(iColumn)) value = floor(value + 0.9e-3); if (logLevel > 1) printf("upper bound on %d changed from %g to %g\n", iColumn, columnUpper[iColumn], value); columnUpper[iColumn] = value; coinModel_.setColumnUpper(iColumn, value); coinModel.setColumnUpper(iColumn, value); } objective[iColumn] = 0.0; } } } delete [] freeRow; delete [] tryColumn; CoinBigIndex * startQuadratic = NULL; int * columnQuadratic = NULL; double * elementQuadratic = NULL; if ( saveNBi == nBi) { printf("all bilinearity in objective\n"); specialOptions2_ |= 2; quadraticObjective = true; // save copy as quadratic model quadraticModel_ = new ClpSimplex(*modelPtr_); startQuadratic = new CoinBigIndex [numberColumns+1]; columnQuadratic = new int [numberQuadratic]; elementQuadratic = new double [numberQuadratic]; numberQuadratic = 0; } //if (quadraticObjective||((specialOptions2_&8)!=0&&saveNBi)) { if (saveNBi) { // add in objective as constraint objectiveVariable_ = numberColumns; objectiveRow_ = coinModel.numberRows(); coinModel.addColumn(0, NULL, NULL, -COIN_DBL_MAX, COIN_DBL_MAX, 1.0); int * column = new int[numberColumns+1]; double * element = new double[numberColumns+1]; double * objective = coinModel.objectiveArray(); int n = 0; for (int i = 0; i < numberColumns; i++) { if (objective[i]) { column[n] = i; element[n++] = objective[i]; objective[i] = 0.0; } } column[n] = objectiveVariable_; element[n++] = -1.0; double offset = - coinModel.objectiveOffset(); //assert (!offset); // get sign right if happens printf("***** offset %g\n", offset); coinModel.setObjectiveOffset(0.0); double lowerBound = -COIN_DBL_MAX; coinModel.addRow(n, column, element, lowerBound, offset); delete [] column; delete [] element; } OsiObject ** objects = new OsiObject * [nBi+nInt]; char * marked = new char [numberColumns]; memset(marked, 0, numberColumns); // statistics I-I I-x x-x int stats[3] = {0, 0, 0}; double * sort = new double [nBi]; nBi = nInt; const OsiObject ** justBi = const_cast (objects + nInt); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (quadraticObjective) startQuadratic[iColumn] = numberQuadratic; // See if quadratic objective const char * expr = coinModel_.getColumnObjectiveAsString(iColumn); if (strcmp(expr, "Numeric")) { // need bounds fakeBounds(this, iColumn, defaultBound_, &coinModel, &coinModel_); // value*x*y char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_); // must be column unless first when may be linear term if (jColumn >= 0) { if (quadraticObjective) { columnQuadratic[numberQuadratic] = jColumn; if (jColumn == iColumn) elementQuadratic[numberQuadratic++] = 2.0 * value; // convention else elementQuadratic[numberQuadratic++] = 1.0 * value; // convention } // need bounds fakeBounds(this, jColumn, defaultBound_, &coinModel, &coinModel_); double meshI = coinModel_.isInteger(iColumn) ? 1.0 : 0.0; if (meshI) marked[iColumn] = 1; double meshJ = coinModel_.isInteger(jColumn) ? 1.0 : 0.0; if (meshJ) marked[jColumn] = 1; // stats etc if (meshI) { if (meshJ) stats[0]++; else stats[1]++; } else { if (meshJ) stats[1]++; else stats[2]++; } if (iColumn <= jColumn) sort[nBi-nInt] = iColumn + numberColumns * jColumn; else sort[nBi-nInt] = jColumn + numberColumns * iColumn; if (!meshJ && !meshI) { meshI = defaultMeshSize_; meshJ = 0.0; } OsiBiLinear * newObj = new OsiBiLinear(&coinModel, iColumn, jColumn, objectiveRow_, value, meshI, meshJ, nBi - nInt, justBi); newObj->setPriority(biLinearPriority_); objects[nBi++] = newObj; } else if (jColumn == -2) { } else { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } } // stats printf("There were %d I-I, %d I-x and %d x-x bilinear in objective\n", stats[0], stats[1], stats[2]); if (quadraticObjective) { startQuadratic[numberColumns] = numberQuadratic; quadraticModel_->loadQuadraticObjective(numberColumns, startQuadratic, columnQuadratic, elementQuadratic); delete [] startQuadratic; delete [] columnQuadratic; delete [] elementQuadratic; } for (iRow = 0; iRow < numberRows; iRow++) { CoinModelLink triple = coinModel_.firstInRow(iRow); while (triple.column() >= 0) { int iColumn = triple.column(); const char * el = coinModel_.getElementAsString(iRow, iColumn); if (strcmp("Numeric", el)) { // need bounds fakeBounds(this, iColumn, defaultBound_, &coinModel, &coinModel_); // value*x*y char temp[20000]; strcpy(temp, el); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_); // must be column unless first when may be linear term if (jColumn >= 0) { // need bounds fakeBounds(this, jColumn, defaultBound_, &coinModel, &coinModel_); double meshI = coinModel_.isInteger(iColumn) ? 1.0 : 0.0; if (meshI) marked[iColumn] = 1; double meshJ = coinModel_.isInteger(jColumn) ? 1.0 : 0.0; if (meshJ) marked[jColumn] = 1; // stats etc if (meshI) { if (meshJ) stats[0]++; else stats[1]++; } else { if (meshJ) stats[1]++; else stats[2]++; } if (iColumn <= jColumn) sort[nBi-nInt] = iColumn + numberColumns * jColumn; else sort[nBi-nInt] = jColumn + numberColumns * iColumn; if (!meshJ && !meshI) { meshI = defaultMeshSize_; meshJ = 0.0; } OsiBiLinear * newObj = new OsiBiLinear(&coinModel, iColumn, jColumn, iRow, value, meshI, meshJ, nBi - nInt, justBi); newObj->setPriority(biLinearPriority_); objects[nBi++] = newObj; } else if (jColumn == -2) { } else { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } triple = coinModel_.next(triple); } } { // stats std::sort(sort, sort + nBi - nInt); int nDiff = 0; double last = -1.0; for (int i = 0; i < nBi - nInt; i++) { if (sort[i] != last) nDiff++; last = sort[i]; } delete [] sort; printf("There were %d I-I, %d I-x and %d x-x bilinear in total of which %d were duplicates\n", stats[0], stats[1], stats[2], nBi - nInt - nDiff); } // reload with all bilinear stuff loadFromCoinModel(coinModel, true); //exit(77); nInt = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (coinModel_.isInteger(iColumn)) { objects[nInt] = new OsiSimpleInteger(this, iColumn); if (marked[iColumn]) objects[nInt]->setPriority(integerPriority_); else objects[nInt]->setPriority(integerPriority_); nInt++; } } nInt = nBi; delete [] marked; if (numberErrors) { // errors gutsOfDestructor(); numberVariables_ = -1; } else { addObjects(nInt, objects); int i; for (i = 0; i < nInt; i++) delete objects[i]; delete [] objects; // Now do dummy bound stuff matrix_ = new CoinPackedMatrix(*getMatrixByCol()); info_ = new OsiLinkedBound [numberVariables_]; for ( i = 0; i < numberVariables_; i++) { info_[i] = OsiLinkedBound(this, which[i], 0, NULL, NULL, NULL); } // Do row copy but just part int numberRows2 = objectiveRow_ >= 0 ? numberRows + 1 : numberRows; int * whichRows = new int [numberRows2]; int * whichColumns = new int [numberColumns]; CoinIotaN(whichRows, numberRows2, 0); CoinIotaN(whichColumns, numberColumns, 0); originalRowCopy_ = new CoinPackedMatrix(*getMatrixByRow(), numberRows2, whichRows, numberColumns, whichColumns); delete [] whichColumns; numberNonLinearRows_ = 0; CoinZeroN(whichRows, numberRows2); for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { int xyRow = obj->xyRow(); assert (xyRow >= 0 && xyRow < numberRows2); // even if obj we should move whichRows[xyRow]++; } } int * pos = new int [numberRows2]; int n = 0; for (i = 0; i < numberRows2; i++) { if (whichRows[i]) { pos[numberNonLinearRows_] = n; n += whichRows[i]; whichRows[i] = numberNonLinearRows_; numberNonLinearRows_++; } else { whichRows[i] = -1; } } startNonLinear_ = new int [numberNonLinearRows_+1]; memcpy(startNonLinear_, pos, numberNonLinearRows_*sizeof(int)); startNonLinear_[numberNonLinearRows_] = n; rowNonLinear_ = new int [numberNonLinearRows_]; convex_ = new int [numberNonLinearRows_]; // do row numbers now numberNonLinearRows_ = 0; for (i = 0; i < numberRows2; i++) { if (whichRows[i] >= 0) { rowNonLinear_[numberNonLinearRows_++] = i; } } whichNonLinear_ = new int [n]; for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { int xyRow = obj->xyRow(); int k = whichRows[xyRow]; int put = pos[k]; pos[k]++; whichNonLinear_[put] = i; } } delete [] pos; delete [] whichRows; analyzeObjects(); } } // See if there are any quadratic bounds int nQ = 0; const CoinPackedMatrix * rowCopy = getMatrixByRow(); //const double * element = rowCopy->getElements(); //const int * column = rowCopy->getIndices(); //const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const int * rowLength = rowCopy->getVectorLengths(); const double * rowLower = getRowLower(); const double * rowUpper = getRowUpper(); for (int iObject = 0; iObject < numberObjects_; iObject++) { OsiBiLinear * obj = dynamic_cast (object_[iObject]); if (obj) { int xyRow = obj->xyRow(); if (rowLength[xyRow] == 4 && false) { // we have simple bound nQ++; double coefficient = obj->coefficient(); double lo = rowLower[xyRow]; double up = rowUpper[xyRow]; if (coefficient != 1.0) { printf("*** double check code here\n"); if (coefficient < 0.0) { double temp = lo; lo = - up; up = - temp; coefficient = - coefficient; } if (lo > -1.0e20) lo /= coefficient; if (up < 1.0e20) up /= coefficient; setRowLower(xyRow, lo); setRowUpper(xyRow, up); // we also need to change elements in matrix_ } int type = 0; if (lo == up) { // good news type = 3; coefficient = lo; } else if (lo < -1.0e20) { assert (up < 1.0e20); coefficient = up; type = 1; // can we make equality? } else if (up > 1.0e20) { coefficient = lo; type = 2; // can we make equality? } else { // we would need extra code abort(); } obj->setBoundType(type); obj->setCoefficient(coefficient); // can do better if integer? assert (!isInteger(obj->xColumn())); assert (!isInteger(obj->yColumn())); } } } delete [] which; if ((specialOptions2_&16) != 0) addTighterConstraints(); } // Add reformulated bilinear constraints void OsiSolverLink::addTighterConstraints() { // This is first attempt - for now get working on trimloss int numberW = 0; int * xW = new int[numberObjects_]; int * yW = new int[numberObjects_]; // Points to firstlambda int * wW = new int[numberObjects_]; // Coefficient double * alphaW = new double[numberObjects_]; // Objects OsiBiLinear ** objW = new OsiBiLinear * [numberObjects_]; int numberColumns = getNumCols(); int firstLambda = numberColumns; // set up list (better to rethink and do properly as column ordered) int * list = new int[numberColumns]; memset(list, 0, numberColumns*sizeof(int)); int i; for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { //obj->setBranchingStrategy(4); // ***** temp objW[numberW] = obj; xW[numberW] = obj->xColumn(); yW[numberW] = obj->yColumn(); list[xW[numberW]] = 1; list[yW[numberW]] = 1; wW[numberW] = obj->firstLambda(); firstLambda = CoinMin(firstLambda, obj->firstLambda()); alphaW[numberW] = obj->coefficient(); //assert (alphaW[numberW]==1.0); // fix when occurs numberW++; } } int nList = 0; for (i = 0; i < numberColumns; i++) { if (list[i]) list[nList++] = i; } // set up mark array char * mark = new char [firstLambda*firstLambda]; memset(mark, 0, firstLambda*firstLambda); for (i = 0; i < numberW; i++) { int x = xW[i]; int y = yW[i]; mark[x*firstLambda+y] = 1; mark[y*firstLambda+x] = 1; } int numberRows2 = originalRowCopy_->getNumRows(); int * addColumn = new int [numberColumns]; double * addElement = new double [numberColumns]; int * addW = new int [numberColumns]; assert (objectiveRow_ < 0); // fix when occurs for (int iRow = 0; iRow < numberRows2; iRow++) { for (int iList = 0; iList < nList; iList++) { int kColumn = list[iList]; #ifndef NDEBUG const double * columnLower = getColLower(); #endif //const double * columnUpper = getColUpper(); const double * rowLower = getRowLower(); const double * rowUpper = getRowUpper(); const CoinPackedMatrix * rowCopy = getMatrixByRow(); const double * element = rowCopy->getElements(); const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const int * rowLength = rowCopy->getVectorLengths(); CoinBigIndex j; int numberElements = rowLength[iRow]; int n = 0; for (j = rowStart[iRow]; j < rowStart[iRow] + numberElements; j++) { int iColumn = column[j]; if (iColumn >= firstLambda) { // no good n = -1; break; } if (mark[iColumn*firstLambda+kColumn]) n++; } if (n == numberElements) { printf("can add row %d\n", iRow); assert (columnLower[kColumn] >= 0); // might be able to fix n = 0; for (j = rowStart[iRow]; j < rowStart[iRow] + numberElements; j++) { int xColumn = kColumn; int yColumn = column[j]; int k; for (k = 0; k < numberW; k++) { if ((xW[k] == yColumn && yW[k] == xColumn) || (yW[k] == yColumn && xW[k] == xColumn)) break; } assert (k < numberW); if (xW[k] != xColumn) { int temp = xColumn; xColumn = yColumn; yColumn = temp; } addW[n/4] = k; int start = wW[k]; double value = element[j]; for (int kk = 0; kk < 4; kk++) { // Dummy value addElement[n] = value; addColumn[n++] = start + kk; } } addColumn[n++] = kColumn; double lo = rowLower[iRow]; double up = rowUpper[iRow]; if (lo > -1.0e20) { // and tell object for (j = 0; j < n - 1; j += 4) { int iObject = addW[j/4]; objW[iObject]->addExtraRow(matrix_->getNumRows(), addElement[j]); } addElement[n-1] = -lo; if (lo == up) addRow(n, addColumn, addElement, 0.0, 0.0); else addRow(n, addColumn, addElement, 0.0, COIN_DBL_MAX); matrix_->appendRow(n, addColumn, addElement); } if (up<1.0e20 && up>lo) { // and tell object for (j = 0; j < n - 1; j += 4) { int iObject = addW[j/4]; objW[iObject]->addExtraRow(matrix_->getNumRows(), addElement[j]); } addElement[n-1] = -up; addRow(n, addColumn, addElement, -COIN_DBL_MAX, 0.0); matrix_->appendRow(n, addColumn, addElement); } } } } #ifdef JJF_ZERO // possibly do bounds for (int iColumn = 0; iColumn < firstLambda; iColumn++) { for (int iList = 0; iList < nList; iList++) { int kColumn = list[iList]; const double * columnLower = getColLower(); const double * columnUpper = getColUpper(); if (mark[iColumn*firstLambda+kColumn]) { printf("can add column %d\n", iColumn); assert (columnLower[kColumn] >= 0); // might be able to fix int xColumn = kColumn; int yColumn = iColumn; int k; for (k = 0; k < numberW; k++) { if ((xW[k] == yColumn && yW[k] == xColumn) || (yW[k] == yColumn && xW[k] == xColumn)) break; } assert (k < numberW); if (xW[k] != xColumn) { int temp = xColumn; xColumn = yColumn; yColumn = temp; } int start = wW[k]; int n = 0; for (int kk = 0; kk < 4; kk++) { // Dummy value addElement[n] = 1.0e-19; addColumn[n++] = start + kk; } // Tell object about this objW[k]->addExtraRow(matrix_->getNumRows(), 1.0); addColumn[n++] = kColumn; double lo = columnLower[iColumn]; double up = columnUpper[iColumn]; if (lo > -1.0e20) { addElement[n-1] = -lo; if (lo == up) addRow(n, addColumn, addElement, 0.0, 0.0); else addRow(n, addColumn, addElement, 0.0, COIN_DBL_MAX); matrix_->appendRow(n, addColumn, addElement); } if (up<1.0e20 && up>lo) { addElement[n-1] = -up; addRow(n, addColumn, addElement, -COIN_DBL_MAX, 0.0); matrix_->appendRow(n, addColumn, addElement); } } } } #endif delete [] xW; delete [] yW; delete [] wW; delete [] alphaW; delete [] addColumn; delete [] addElement; delete [] addW; delete [] mark; delete [] list; delete [] objW; } // Set all biLinear priorities on x-x variables void OsiSolverLink::setBiLinearPriorities(int value, double meshSize) { OsiObject ** newObject = new OsiObject * [numberObjects_]; int numberOdd = 0; int i; for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0) { double oldSatisfied = CoinMax(obj->xSatisfied(), obj->ySatisfied()); OsiBiLinear * objNew = new OsiBiLinear(*obj); newObject[numberOdd++] = objNew; objNew->setXSatisfied(0.5*meshSize); obj->setXOtherSatisfied(0.5*meshSize); objNew->setXOtherSatisfied(oldSatisfied); objNew->setXMeshSize(meshSize); objNew->setYSatisfied(0.5*meshSize); obj->setYOtherSatisfied(0.5*meshSize); objNew->setYOtherSatisfied(oldSatisfied); objNew->setYMeshSize(meshSize); objNew->setXYSatisfied(0.25*meshSize); objNew->setPriority(value); objNew->setBranchingStrategy(8); } } } addObjects(numberOdd, newObject); for (i = 0; i < numberOdd; i++) delete newObject[i]; delete [] newObject; } /* Set options and priority on all or some biLinear variables 1 - on I-I 2 - on I-x 4 - on x-x or combinations. -1 means leave (for priority value and strategy value) */ void OsiSolverLink::setBranchingStrategyOnVariables(int strategyValue, int priorityValue, int mode) { int i; for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { bool change = false; if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0 && (mode&4) != 0) change = true; else if (((obj->xMeshSize() == 1.0 && obj->yMeshSize() < 1.0) || (obj->xMeshSize() < 1.0 && obj->yMeshSize() == 1.0)) && (mode&2) != 0) change = true; else if (obj->xMeshSize() == 1.0 && obj->yMeshSize() == 1.0 && (mode&1) != 0) change = true; else if (obj->xMeshSize() > 1.0 || obj->yMeshSize() > 1.0) abort(); if (change) { if (strategyValue >= 0) obj->setBranchingStrategy(strategyValue); if (priorityValue >= 0) obj->setPriority(priorityValue); } } } } // Say convex (should work it out) void OsiSolverLink::sayConvex(bool convex) { specialOptions2_ |= 4; if (convex_) { for (int iNon = 0; iNon < numberNonLinearRows_; iNon++) { convex_[iNon] = convex ? 1 : -1; } } } // Set all mesh sizes on x-x variables void OsiSolverLink::setMeshSizes(double value) { int i; for ( i = 0; i < numberObjects_; i++) { OsiBiLinear * obj = dynamic_cast (object_[i]); if (obj) { if (obj->xMeshSize() < 1.0 && obj->yMeshSize() < 1.0) { #ifdef JJF_ZERO numberContinuous++; int xColumn = obj->xColumn(); double gapX = upper[xColumn] - lower[xColumn]; int yColumn = obj->yColumn(); double gapY = upper[yColumn] - lower[yColumn]; gap = CoinMax(gap, CoinMax(gapX, gapY)); #endif obj->setMeshSizes(this, value, value); } } } } /* Solves nonlinear problem from CoinModel using SLP - may be used as crash for other algorithms when number of iterations small. Also exits if all problematical variables are changing less than deltaTolerance Returns solution array */ double * OsiSolverLink::nonlinearSLP(int numberPasses, double deltaTolerance) { if (!coinModel_.numberRows()) { printf("Model not set up or nonlinear arrays not created!\n"); return NULL; } // first check and set up arrays int numberColumns = coinModel_.numberColumns(); int numberRows = coinModel_.numberRows(); char * markNonlinear = new char [numberColumns+numberRows]; CoinZeroN(markNonlinear, numberColumns + numberRows); // List of nonlinear entries int * listNonLinearColumn = new int[numberColumns]; // List of nonlinear constraints int * whichRow = new int [numberRows]; CoinZeroN(whichRow, numberRows); int numberNonLinearColumns = 0; int iColumn; CoinModel coinModel = coinModel_; //const CoinModelHash * stringArray = coinModel.stringArray(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinModelLink triple = coinModel.firstInColumn(iColumn); bool linear = true; int n = 0; // See if nonlinear objective const char * expr = coinModel.getColumnObjectiveAsString(iColumn); if (strcmp(expr, "Numeric")) { linear = false; // try and see which columns assert (strlen(expr) < 20000); char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_); // must be column unless first when may be linear term if (jColumn >= 0) { markNonlinear[jColumn] = 1; } else if (jColumn != -2) { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } while (triple.row() >= 0) { int iRow = triple.row(); const char * expr = coinModel.getElementAsString(iRow, iColumn); if (strcmp(expr, "Numeric")) { linear = false; whichRow[iRow]++; // try and see which columns assert (strlen(expr) < 20000); char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_); // must be column unless first when may be linear term if (jColumn >= 0) { markNonlinear[jColumn] = 1; } else if (jColumn != -2) { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } triple = coinModel.next(triple); n++; } if (!linear) { markNonlinear[iColumn] = 1; } } //int xxxx[]={3,2,0,4,3,0}; //double initialSolution[6]; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (markNonlinear[iColumn]) { // put in something double lower = coinModel.columnLower(iColumn); double upper = CoinMin(coinModel.columnUpper(iColumn), lower + 1000.0); coinModel.associateElement(coinModel.columnName(iColumn), 0.5*(lower + upper)); //coinModel.associateElement(coinModel.columnName(iColumn),xxxx[iColumn]); listNonLinearColumn[numberNonLinearColumns++] = iColumn; //initialSolution[iColumn]=xxxx[iColumn]; } } // if nothing just solve if (!numberNonLinearColumns) { delete [] listNonLinearColumn; delete [] whichRow; delete [] markNonlinear; ClpSimplex tempModel; tempModel.loadProblem(coinModel, true); tempModel.initialSolve(); double * solution = CoinCopyOfArray(tempModel.getColSolution(), numberColumns); return solution; } // Create artificials ClpSimplex tempModel; tempModel.loadProblem(coinModel, true); const double * rowLower = tempModel.rowLower(); const double * rowUpper = tempModel.rowUpper(); bool takeAll = false; int iRow; int numberArtificials = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (whichRow[iRow] || takeAll) { if (rowLower[iRow] > -1.0e30) numberArtificials++; if (rowUpper[iRow] < 1.0e30) numberArtificials++; } } CoinBigIndex * startArtificial = new CoinBigIndex [numberArtificials+1]; int * rowArtificial = new int [numberArtificials]; double * elementArtificial = new double [numberArtificials]; double * objectiveArtificial = new double [numberArtificials]; numberArtificials = 0; startArtificial[0] = 0; double artificialCost = 1.0e9; for (iRow = 0; iRow < numberRows; iRow++) { if (whichRow[iRow] || takeAll) { if (rowLower[iRow] > -1.0e30) { rowArtificial[numberArtificials] = iRow; elementArtificial[numberArtificials] = 1.0; objectiveArtificial[numberArtificials] = artificialCost; numberArtificials++; startArtificial[numberArtificials] = numberArtificials; } if (rowUpper[iRow] < 1.0e30) { rowArtificial[numberArtificials] = iRow; elementArtificial[numberArtificials] = -1.0; objectiveArtificial[numberArtificials] = artificialCost; numberArtificials++; startArtificial[numberArtificials] = numberArtificials; } } } // Get first solution int numberColumnsSmall = numberColumns; ClpSimplex model; model.loadProblem(coinModel, true); model.addColumns(numberArtificials, NULL, NULL, objectiveArtificial, startArtificial, rowArtificial, elementArtificial); double * columnLower = model.columnLower(); double * columnUpper = model.columnUpper(); double * trueLower = new double[numberNonLinearColumns]; double * trueUpper = new double[numberNonLinearColumns]; int jNon; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; trueLower[jNon] = columnLower[iColumn]; trueUpper[jNon] = columnUpper[iColumn]; //columnLower[iColumn]=initialSolution[iColumn]; //columnUpper[iColumn]=initialSolution[iColumn]; } model.initialSolve(); //model.writeMps("bad.mps"); // redo number of columns numberColumns = model.numberColumns(); int * last[3]; double * solution = model.primalColumnSolution(); double * trust = new double[numberNonLinearColumns]; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; trust[jNon] = 0.5; if (solution[iColumn] < trueLower[jNon]) solution[iColumn] = trueLower[jNon]; else if (solution[iColumn] > trueUpper[jNon]) solution[iColumn] = trueUpper[jNon]; } int iPass; double lastObjective = 1.0e31; double * saveSolution = new double [numberColumns]; double * saveRowSolution = new double [numberRows]; memset(saveRowSolution, 0, numberRows*sizeof(double)); double * savePi = new double [numberRows]; double * safeSolution = new double [numberColumns]; unsigned char * saveStatus = new unsigned char[numberRows+numberColumns]; double targetDrop = 1.0e31; //double objectiveOffset; //model.getDblParam(ClpObjOffset,objectiveOffset); // 1 bound up, 2 up, -1 bound down, -2 down, 0 no change for (iPass = 0; iPass < 3; iPass++) { last[iPass] = new int[numberNonLinearColumns]; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) last[iPass][jNon] = 0; } // goodMove +1 yes, 0 no, -1 last was bad - just halve gaps, -2 do nothing int goodMove = -2; char * statusCheck = new char[numberColumns]; double * changeRegion = new double [numberColumns]; int logLevel = 63; double dualTolerance = model.dualTolerance(); double primalTolerance = model.primalTolerance(); int lastGoodMove = 1; for (iPass = 0; iPass < numberPasses; iPass++) { lastGoodMove = goodMove; columnLower = model.columnLower(); columnUpper = model.columnUpper(); solution = model.primalColumnSolution(); double * rowActivity = model.primalRowSolution(); // redo objective ClpSimplex tempModel; // load new values for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; coinModel.associateElement(coinModel.columnName(iColumn), solution[iColumn]); } tempModel.loadProblem(coinModel); double objectiveOffset; tempModel.getDblParam(ClpObjOffset, objectiveOffset); double objValue = -objectiveOffset; const double * objective = tempModel.objective(); for (iColumn = 0; iColumn < numberColumnsSmall; iColumn++) objValue += solution[iColumn] * objective[iColumn]; double * rowActivity2 = tempModel.primalRowSolution(); const double * rowLower2 = tempModel.rowLower(); const double * rowUpper2 = tempModel.rowUpper(); memset(rowActivity2, 0, numberRows*sizeof(double)); tempModel.times(1.0, solution, rowActivity2); for (iRow = 0; iRow < numberRows; iRow++) { if (rowActivity2[iRow] < rowLower2[iRow] - primalTolerance) objValue += (rowLower2[iRow] - rowActivity2[iRow] - primalTolerance) * artificialCost; else if (rowActivity2[iRow] > rowUpper2[iRow] + primalTolerance) objValue -= (rowUpper2[iRow] - rowActivity2[iRow] + primalTolerance) * artificialCost; } double theta = -1.0; double maxTheta = COIN_DBL_MAX; if (objValue <= lastObjective + 1.0e-15*fabs(lastObjective) || !iPass) goodMove = 1; else goodMove = -1; //maxTheta=1.0; if (iPass) { int jNon = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { changeRegion[iColumn] = solution[iColumn] - saveSolution[iColumn]; double alpha = changeRegion[iColumn]; double oldValue = saveSolution[iColumn]; if (markNonlinear[iColumn] == 0) { // linear if (alpha < -1.0e-15) { // variable going towards lower bound double bound = columnLower[iColumn]; oldValue -= bound; if (oldValue + maxTheta*alpha < 0.0) { maxTheta = CoinMax(0.0, oldValue / (-alpha)); } } else if (alpha > 1.0e-15) { // variable going towards upper bound double bound = columnUpper[iColumn]; oldValue = bound - oldValue; if (oldValue - maxTheta*alpha < 0.0) { maxTheta = CoinMax(0.0, oldValue / alpha); } } } else { // nonlinear if (alpha < -1.0e-15) { // variable going towards lower bound double bound = trueLower[jNon]; oldValue -= bound; if (oldValue + maxTheta*alpha < 0.0) { maxTheta = CoinMax(0.0, oldValue / (-alpha)); } } else if (alpha > 1.0e-15) { // variable going towards upper bound double bound = trueUpper[jNon]; oldValue = bound - oldValue; if (oldValue - maxTheta*alpha < 0.0) { maxTheta = CoinMax(0.0, oldValue / alpha); } } jNon++; } } // make sure both accurate memset(rowActivity, 0, numberRows*sizeof(double)); model.times(1.0, solution, rowActivity); memset(saveRowSolution, 0, numberRows*sizeof(double)); model.times(1.0, saveSolution, saveRowSolution); for (int iRow = 0; iRow < numberRows; iRow++) { double alpha = rowActivity[iRow] - saveRowSolution[iRow]; double oldValue = saveRowSolution[iRow]; if (alpha < -1.0e-15) { // variable going towards lower bound double bound = rowLower[iRow]; oldValue -= bound; if (oldValue + maxTheta*alpha < 0.0) { maxTheta = CoinMax(0.0, oldValue / (-alpha)); } } else if (alpha > 1.0e-15) { // variable going towards upper bound double bound = rowUpper[iRow]; oldValue = bound - oldValue; if (oldValue - maxTheta*alpha < 0.0) { maxTheta = CoinMax(0.0, oldValue / alpha); } } } } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) { changeRegion[iColumn] = 0.0; saveSolution[iColumn] = solution[iColumn]; } memcpy(saveRowSolution, rowActivity, numberRows*sizeof(double)); } if (goodMove >= 0) { //theta = CoinMin(theta2,maxTheta); theta = maxTheta; if (theta > 0.0 && theta <= 1.0) { // update solution double lambda = 1.0 - theta; for (iColumn = 0; iColumn < numberColumns; iColumn++) solution[iColumn] = lambda * saveSolution[iColumn] + theta * solution[iColumn]; memset(rowActivity, 0, numberRows*sizeof(double)); model.times(1.0, solution, rowActivity); if (lambda > 0.999) { memcpy(model.dualRowSolution(), savePi, numberRows*sizeof(double)); memcpy(model.statusArray(), saveStatus, numberRows + numberColumns); } // redo rowActivity memset(rowActivity, 0, numberRows*sizeof(double)); model.times(1.0, solution, rowActivity); } } // load new values for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; coinModel.associateElement(coinModel.columnName(iColumn), solution[iColumn]); } double * sol2 = CoinCopyOfArray(model.primalColumnSolution(), numberColumns); unsigned char * status2 = CoinCopyOfArray(model.statusArray(), numberColumns); model.loadProblem(coinModel); model.addColumns(numberArtificials, NULL, NULL, objectiveArtificial, startArtificial, rowArtificial, elementArtificial); memcpy(model.primalColumnSolution(), sol2, numberColumns*sizeof(double)); memcpy(model.statusArray(), status2, numberColumns); delete [] sol2; delete [] status2; columnLower = model.columnLower(); columnUpper = model.columnUpper(); solution = model.primalColumnSolution(); rowActivity = model.primalRowSolution(); int * temp = last[2]; last[2] = last[1]; last[1] = last[0]; last[0] = temp; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; double change = solution[iColumn] - saveSolution[iColumn]; if (change < -1.0e-5) { if (fabs(change + trust[jNon]) < 1.0e-5) temp[jNon] = -1; else temp[jNon] = -2; } else if (change > 1.0e-5) { if (fabs(change - trust[jNon]) < 1.0e-5) temp[jNon] = 1; else temp[jNon] = 2; } else { temp[jNon] = 0; } } // goodMove +1 yes, 0 no, -1 last was bad - just halve gaps, -2 do nothing double maxDelta = 0.0; if (goodMove >= 0) { if (objValue <= lastObjective + 1.0e-15*fabs(lastObjective)) goodMove = 1; else goodMove = 0; } else { maxDelta = 1.0e10; } double maxGap = 0.0; int numberSmaller = 0; int numberSmaller2 = 0; int numberLarger = 0; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; maxDelta = CoinMax(maxDelta, fabs(solution[iColumn] - saveSolution[iColumn])); if (goodMove > 0) { if (last[0][jNon]*last[1][jNon] < 0) { // halve trust[jNon] *= 0.5; numberSmaller2++; } else { if (last[0][jNon] == last[1][jNon] && last[0][jNon] == last[2][jNon]) trust[jNon] = CoinMin(1.5 * trust[jNon], 1.0e6); numberLarger++; } } else if (goodMove != -2 && trust[jNon] > 10.0*deltaTolerance) { trust[jNon] *= 0.2; numberSmaller++; } maxGap = CoinMax(maxGap, trust[jNon]); } #ifdef CLP_DEBUG if (logLevel&32) std::cout << "largest gap is " << maxGap << " " << numberSmaller + numberSmaller2 << " reduced (" << numberSmaller << " badMove ), " << numberLarger << " increased" << std::endl; #endif if (iPass > 10000) { for (jNon = 0; jNon < numberNonLinearColumns; jNon++) trust[jNon] *= 0.0001; } printf("last good %d goodMove %d\n", lastGoodMove, goodMove); if (goodMove > 0) { double drop = lastObjective - objValue; printf("Pass %d, objective %g - drop %g maxDelta %g\n", iPass, objValue, drop, maxDelta); if (iPass > 20 && drop < 1.0e-12*fabs(objValue) && lastGoodMove > 0) drop = 0.999e-4; // so will exit if (maxDelta < deltaTolerance && drop < 1.0e-4 && goodMove && theta<0.99999 && lastGoodMove>0) { if (logLevel > 1) std::cout << "Exiting as maxDelta < tolerance and small drop" << std::endl; break; } } else if (!numberSmaller && iPass > 1) { if (logLevel > 1) std::cout << "Exiting as all gaps small" << std::endl; break; } if (!iPass) goodMove = 1; targetDrop = 0.0; double * r = model.dualColumnSolution(); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; columnLower[iColumn] = CoinMax(solution[iColumn] - trust[jNon], trueLower[jNon]); columnUpper[iColumn] = CoinMin(solution[iColumn] + trust[jNon], trueUpper[jNon]); } if (iPass) { // get reduced costs model.matrix()->transposeTimes(savePi, model.dualColumnSolution()); const double * objective = model.objective(); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; double dj = objective[iColumn] - r[iColumn]; r[iColumn] = dj; if (dj < -dualTolerance) targetDrop -= dj * (columnUpper[iColumn] - solution[iColumn]); else if (dj > dualTolerance) targetDrop -= dj * (columnLower[iColumn] - solution[iColumn]); } } else { memset(r, 0, numberColumns*sizeof(double)); } #ifdef JJF_ZERO for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; if (statusCheck[iColumn] == 'L' && r[iColumn] < -1.0e-4) { columnLower[iColumn] = CoinMax(solution[iColumn], trueLower[jNon]); columnUpper[iColumn] = CoinMin(solution[iColumn] + trust[jNon], trueUpper[jNon]); } else if (statusCheck[iColumn] == 'U' && r[iColumn] > 1.0e-4) { columnLower[iColumn] = CoinMax(solution[iColumn] - trust[jNon], trueLower[jNon]); columnUpper[iColumn] = CoinMin(solution[iColumn], trueUpper[jNon]); } else { columnLower[iColumn] = CoinMax(solution[iColumn] - trust[jNon], trueLower[jNon]); columnUpper[iColumn] = CoinMin(solution[iColumn] + trust[jNon], trueUpper[jNon]); } } #endif if (goodMove > 0) { memcpy(saveSolution, solution, numberColumns*sizeof(double)); memcpy(saveRowSolution, rowActivity, numberRows*sizeof(double)); memcpy(savePi, model.dualRowSolution(), numberRows*sizeof(double)); memcpy(saveStatus, model.statusArray(), numberRows + numberColumns); #ifdef CLP_DEBUG if (logLevel&32) std::cout << "Pass - " << iPass << ", target drop is " << targetDrop << std::endl; #endif lastObjective = objValue; if (targetDrop < CoinMax(1.0e-8, CoinMin(1.0e-6, 1.0e-6*fabs(objValue))) && lastGoodMove && iPass > 3) { if (logLevel > 1) printf("Exiting on target drop %g\n", targetDrop); break; } #ifdef CLP_DEBUG { double * r = model.dualColumnSolution(); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; if (logLevel&32) printf("Trust %d %g - solution %d %g obj %g dj %g state %c - bounds %g %g\n", jNon, trust[jNon], iColumn, solution[iColumn], objective[iColumn], r[iColumn], statusCheck[iColumn], columnLower[iColumn], columnUpper[iColumn]); } } #endif model.scaling(false); model.primal(1); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; printf("%d bounds etc %g %g %g\n", iColumn, columnLower[iColumn], solution[iColumn], columnUpper[iColumn]); } char temp[20]; sprintf(temp, "pass%d.mps", iPass); //model.writeMps(temp); #ifdef CLP_DEBUG if (model.status()) { model.writeMps("xx.mps"); } #endif if (model.status() == 1) { // not feasible ! - backtrack and exit // use safe solution memcpy(solution, safeSolution, numberColumns*sizeof(double)); memcpy(saveSolution, solution, numberColumns*sizeof(double)); memset(rowActivity, 0, numberRows*sizeof(double)); model.times(1.0, solution, rowActivity); memcpy(saveRowSolution, rowActivity, numberRows*sizeof(double)); memcpy(model.dualRowSolution(), savePi, numberRows*sizeof(double)); memcpy(model.statusArray(), saveStatus, numberRows + numberColumns); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; columnLower[iColumn] = CoinMax(solution[iColumn] - trust[jNon], trueLower[jNon]); columnUpper[iColumn] = CoinMin(solution[iColumn] + trust[jNon], trueUpper[jNon]); } break; } else { // save in case problems memcpy(safeSolution, solution, numberColumns*sizeof(double)); } goodMove = 1; } else { // bad pass - restore solution #ifdef CLP_DEBUG if (logLevel&32) printf("Backtracking\n"); #endif // load old values for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; coinModel.associateElement(coinModel.columnName(iColumn), saveSolution[iColumn]); } model.loadProblem(coinModel); model.addColumns(numberArtificials, NULL, NULL, objectiveArtificial, startArtificial, rowArtificial, elementArtificial); solution = model.primalColumnSolution(); rowActivity = model.primalRowSolution(); memcpy(solution, saveSolution, numberColumns*sizeof(double)); memcpy(rowActivity, saveRowSolution, numberRows*sizeof(double)); memcpy(model.dualRowSolution(), savePi, numberRows*sizeof(double)); memcpy(model.statusArray(), saveStatus, numberRows + numberColumns); columnLower = model.columnLower(); columnUpper = model.columnUpper(); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; columnLower[iColumn] = solution[iColumn]; columnUpper[iColumn] = solution[iColumn]; } model.primal(1); //model.writeMps("xx.mps"); iPass--; goodMove = -1; } } // restore solution memcpy(solution, saveSolution, numberColumns*sizeof(double)); delete [] statusCheck; delete [] savePi; delete [] saveStatus; // load new values for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; coinModel.associateElement(coinModel.columnName(iColumn), solution[iColumn]); } double * sol2 = CoinCopyOfArray(model.primalColumnSolution(), numberColumns); unsigned char * status2 = CoinCopyOfArray(model.statusArray(), numberColumns); model.loadProblem(coinModel); model.addColumns(numberArtificials, NULL, NULL, objectiveArtificial, startArtificial, rowArtificial, elementArtificial); memcpy(model.primalColumnSolution(), sol2, numberColumns*sizeof(double)); memcpy(model.statusArray(), status2, numberColumns); delete [] sol2; delete [] status2; columnLower = model.columnLower(); columnUpper = model.columnUpper(); solution = model.primalColumnSolution(); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; columnLower[iColumn] = CoinMax(solution[iColumn], trueLower[jNon]); columnUpper[iColumn] = CoinMin(solution[iColumn], trueUpper[jNon]); } model.primal(1); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; columnLower[iColumn] = trueLower[jNon]; columnUpper[iColumn] = trueUpper[jNon]; } delete [] saveSolution; delete [] safeSolution; delete [] saveRowSolution; for (iPass = 0; iPass < 3; iPass++) delete [] last[iPass]; delete [] trust; delete [] trueUpper; delete [] trueLower; delete [] changeRegion; delete [] startArtificial; delete [] rowArtificial; delete [] elementArtificial; delete [] objectiveArtificial; delete [] listNonLinearColumn; delete [] whichRow; delete [] markNonlinear; return CoinCopyOfArray(solution, coinModel.numberColumns()); } /* Solve linearized quadratic objective branch and bound. Return cutoff and OA cut */ double OsiSolverLink::linearizedBAB(CglStored * cut) { double bestObjectiveValue = COIN_DBL_MAX; if (quadraticModel_) { ClpSimplex * qp = new ClpSimplex(*quadraticModel_); // bounds int numberColumns = qp->numberColumns(); double * lower = qp->columnLower(); double * upper = qp->columnUpper(); const double * lower2 = getColLower(); const double * upper2 = getColUpper(); for (int i = 0; i < numberColumns; i++) { lower[i] = CoinMax(lower[i], lower2[i]); upper[i] = CoinMin(upper[i], upper2[i]); } qp->nonlinearSLP(20, 1.0e-5); qp->primal(); OsiSolverLinearizedQuadratic solver2(qp); const double * solution = NULL; // Reduce printout solver2.setHintParam(OsiDoReducePrint, true, OsiHintTry); CbcModel model2(solver2); // Now do requested saves and modifications CbcModel * cbcModel = & model2; OsiSolverInterface * osiModel = model2.solver(); OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (osiModel); ClpSimplex * clpModel = osiclpModel->getModelPtr(); // Set changed values CglProbing probing; probing.setMaxProbe(10); probing.setMaxLook(10); probing.setMaxElements(200); probing.setMaxProbeRoot(50); probing.setMaxLookRoot(10); probing.setRowCuts(3); probing.setUsingObjective(true); cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1); cbcModel->cutGenerator(0)->setTiming(true); CglGomory gomory; gomory.setLimitAtRoot(512); cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1); cbcModel->cutGenerator(1)->setTiming(true); CglKnapsackCover knapsackCover; cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1); cbcModel->cutGenerator(2)->setTiming(true); CglClique clique; clique.setStarCliqueReport(false); clique.setRowCliqueReport(false); clique.setMinViolation(0.1); cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1); cbcModel->cutGenerator(3)->setTiming(true); CglMixedIntegerRounding2 mixedIntegerRounding2; cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1); cbcModel->cutGenerator(4)->setTiming(true); CglFlowCover flowCover; cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1); cbcModel->cutGenerator(5)->setTiming(true); CglTwomir twomir; twomir.setMaxElements(250); cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1); cbcModel->cutGenerator(6)->setTiming(true); // For now - switch off most heuristics (because CglPreProcess is bad with QP) #ifndef JJF_ONE CbcHeuristicFPump heuristicFPump(*cbcModel); heuristicFPump.setWhen(13); heuristicFPump.setMaximumPasses(20); heuristicFPump.setMaximumRetries(7); heuristicFPump.setAbsoluteIncrement(4332.64); cbcModel->addHeuristic(&heuristicFPump); heuristicFPump.setInitialWeight(1); CbcHeuristicLocal heuristicLocal(*cbcModel); heuristicLocal.setSearchType(1); cbcModel->addHeuristic(&heuristicLocal); CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel); cbcModel->addHeuristic(&heuristicGreedyCover); CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel); cbcModel->addHeuristic(&heuristicGreedyEquality); #endif CbcRounding rounding(*cbcModel); rounding.setHeuristicName("rounding"); cbcModel->addHeuristic(&rounding); cbcModel->setNumberBeforeTrust(5); cbcModel->setSpecialOptions(2); cbcModel->messageHandler()->setLogLevel(1); cbcModel->setMaximumCutPassesAtRoot(-100); cbcModel->setMaximumCutPasses(1); cbcModel->setMinimumDrop(0.05); // For branchAndBound this may help clpModel->defaultFactorizationFrequency(); clpModel->setDualBound(1.0001e+08); clpModel->setPerturbation(50); osiclpModel->setSpecialOptions(193); osiclpModel->messageHandler()->setLogLevel(0); osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100); osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry); // You can save some time by switching off message building // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL); // Solve cbcModel->initialSolve(); if (clpModel->tightenPrimalBounds() != 0) { std::cout << "Problem is infeasible - tightenPrimalBounds!" << std::endl; delete qp; return COIN_DBL_MAX; } clpModel->dual(); // clean up cbcModel->initialSolve(); cbcModel->branchAndBound(); OsiSolverLinearizedQuadratic * solver3 = dynamic_cast (model2.solver()); assert (solver3); solution = solver3->bestSolution(); bestObjectiveValue = solver3->bestObjectiveValue(); setBestObjectiveValue(bestObjectiveValue); setBestSolution(solution, solver3->getNumCols()); // if convex if ((specialOptions2()&4) != 0) { if (cbcModel_) cbcModel_->lockThread(); // add OA cut double offset; double * gradient = new double [numberColumns+1]; memcpy(gradient, qp->objectiveAsObject()->gradient(qp, solution, offset, true, 2), numberColumns*sizeof(double)); double rhs = 0.0; int * column = new int[numberColumns+1]; int n = 0; for (int i = 0; i < numberColumns; i++) { double value = gradient[i]; if (fabs(value) > 1.0e-12) { gradient[n] = value; rhs += value * solution[i]; column[n++] = i; } } gradient[n] = -1.0; column[n++] = numberColumns; cut->addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient); delete [] gradient; delete [] column; if (cbcModel_) cbcModel_->unlockThread(); } delete qp; printf("obj %g\n", bestObjectiveValue); } return bestObjectiveValue; } /* Solves nonlinear problem from CoinModel using SLP - and then tries to get heuristic solution Returns solution array */ double * OsiSolverLink::heuristicSolution(int numberPasses, double deltaTolerance, int mode) { // get a solution CoinModel tempModel = coinModel_; ClpSimplex * temp = approximateSolution(tempModel, numberPasses, deltaTolerance); int numberColumns = coinModel_.numberColumns(); double * solution = CoinCopyOfArray(temp->primalColumnSolution(), numberColumns); delete temp; if (mode == 0) { return solution; } else if (mode == 2) { const double * lower = getColLower(); const double * upper = getColUpper(); for (int iObject = 0; iObject < numberObjects_; iObject++) { OsiSimpleInteger * obj = dynamic_cast (object_[iObject]); if (obj && (obj->priority() < biLinearPriority_ || biLinearPriority_ <= 0)) { int iColumn = obj->columnNumber(); double value = solution[iColumn]; value = floor(value + 0.5); if (fabs(value - solution[iColumn]) > 0.01) { setColLower(iColumn, CoinMax(lower[iColumn], value - CoinMax(defaultBound_, 0.0))); setColUpper(iColumn, CoinMin(upper[iColumn], value + CoinMax(defaultBound_, 1.0))); } else { // could fix to integer setColLower(iColumn, CoinMax(lower[iColumn], value - CoinMax(defaultBound_, 0.0))); setColUpper(iColumn, CoinMin(upper[iColumn], value + CoinMax(defaultBound_, 0.0))); } } } return solution; } OsiClpSolverInterface newSolver; if (mode == 1) { // round all with priority < biLinearPriority_ setFixedPriority(biLinearPriority_); // ? should we save and restore coin model tempModel = coinModel_; // solve modified problem char * mark = new char[numberColumns]; memset(mark, 0, numberColumns); for (int iObject = 0; iObject < numberObjects_; iObject++) { OsiSimpleInteger * obj = dynamic_cast (object_[iObject]); if (obj && obj->priority() < biLinearPriority_) { int iColumn = obj->columnNumber(); double value = solution[iColumn]; value = ceil(value - 1.0e-7); tempModel.associateElement(coinModel_.columnName(iColumn), value); mark[iColumn] = 1; } OsiBiLinear * objB = dynamic_cast (object_[iObject]); if (objB) { // if one or both continuous then fix one if (objB->xMeshSize() < 1.0) { int xColumn = objB->xColumn(); double value = solution[xColumn]; tempModel.associateElement(coinModel_.columnName(xColumn), value); mark[xColumn] = 1; } else if (objB->yMeshSize() < 1.0) { int yColumn = objB->yColumn(); double value = solution[yColumn]; tempModel.associateElement(coinModel_.columnName(yColumn), value); mark[yColumn] = 1; } } } CoinModel * reOrdered = tempModel.reorder(mark); assert (reOrdered); tempModel = *reOrdered; delete reOrdered; delete [] mark; newSolver.loadFromCoinModel(tempModel, true); for (int iObject = 0; iObject < numberObjects_; iObject++) { OsiSimpleInteger * obj = dynamic_cast (object_[iObject]); if (obj && obj->priority() < biLinearPriority_) { int iColumn = obj->columnNumber(); double value = solution[iColumn]; value = ceil(value - 1.0e-7); newSolver.setColLower(iColumn, value); newSolver.setColUpper(iColumn, value); } OsiBiLinear * objB = dynamic_cast (object_[iObject]); if (objB) { // if one or both continuous then fix one if (objB->xMeshSize() < 1.0) { int xColumn = objB->xColumn(); double value = solution[xColumn]; newSolver.setColLower(xColumn, value); newSolver.setColUpper(xColumn, value); } else if (objB->yMeshSize() < 1.0) { int yColumn = objB->yColumn(); double value = solution[yColumn]; newSolver.setColLower(yColumn, value); newSolver.setColUpper(yColumn, value); } } } } CbcModel model(newSolver); // Now do requested saves and modifications CbcModel * cbcModel = & model; OsiSolverInterface * osiModel = model.solver(); OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (osiModel); ClpSimplex * clpModel = osiclpModel->getModelPtr(); CglProbing probing; probing.setMaxProbe(10); probing.setMaxLook(10); probing.setMaxElements(200); probing.setMaxProbeRoot(50); probing.setMaxLookRoot(10); probing.setRowCuts(3); probing.setRowCuts(0); probing.setUsingObjective(true); cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1); CglGomory gomory; gomory.setLimitAtRoot(512); cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1); CglKnapsackCover knapsackCover; cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1); CglClique clique; clique.setStarCliqueReport(false); clique.setRowCliqueReport(false); clique.setMinViolation(0.1); cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1); CglMixedIntegerRounding2 mixedIntegerRounding2; cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1); CglFlowCover flowCover; cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1); CglTwomir twomir; twomir.setMaxElements(250); cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1); cbcModel->cutGenerator(6)->setTiming(true); CbcHeuristicFPump heuristicFPump(*cbcModel); heuristicFPump.setWhen(1); heuristicFPump.setMaximumPasses(20); heuristicFPump.setDefaultRounding(0.5); cbcModel->addHeuristic(&heuristicFPump); CbcRounding rounding(*cbcModel); cbcModel->addHeuristic(&rounding); CbcHeuristicLocal heuristicLocal(*cbcModel); heuristicLocal.setSearchType(1); cbcModel->addHeuristic(&heuristicLocal); CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel); cbcModel->addHeuristic(&heuristicGreedyCover); CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel); cbcModel->addHeuristic(&heuristicGreedyEquality); CbcCompareDefault compare; cbcModel->setNodeComparison(compare); cbcModel->setNumberBeforeTrust(5); cbcModel->setSpecialOptions(2); cbcModel->messageHandler()->setLogLevel(1); cbcModel->setMaximumCutPassesAtRoot(-100); cbcModel->setMaximumCutPasses(1); cbcModel->setMinimumDrop(0.05); clpModel->setNumberIterations(1); // For branchAndBound this may help clpModel->defaultFactorizationFrequency(); clpModel->setDualBound(6.71523e+07); clpModel->setPerturbation(50); osiclpModel->setSpecialOptions(193); osiclpModel->messageHandler()->setLogLevel(0); osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100); osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry); // You can save some time by switching off message building // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL); // Solve cbcModel->initialSolve(); //double cutoff = model_->getCutoff(); if (!cbcModel_) cbcModel->setCutoff(1.0e50); else cbcModel->setCutoff(cbcModel_->getCutoff()); int saveLogLevel = clpModel->logLevel(); clpModel->setLogLevel(0); #ifndef NDEBUG int returnCode = 0; #endif if (clpModel->tightenPrimalBounds() != 0) { clpModel->setLogLevel(saveLogLevel); #ifndef NDEBUG returnCode = -1; // infeasible//std::cout<<"Problem is infeasible - tightenPrimalBounds!"<writeMps("infeas2.mps"); } else { clpModel->setLogLevel(saveLogLevel); clpModel->dual(); // clean up // compute some things using problem size cbcModel->setMinimumDrop(CoinMin(5.0e-2, fabs(cbcModel->getMinimizationObjValue())*1.0e-3 + 1.0e-4)); if (cbcModel->getNumCols() < 500) cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (cbcModel->getNumCols() < 5000) cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop else cbcModel->setMaximumCutPassesAtRoot(20); cbcModel->setMaximumCutPasses(1); // Hand coded preprocessing CglPreProcess process; OsiSolverInterface * saveSolver = cbcModel->solver()->clone(); // Tell solver we are in Branch and Cut saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ; // Default set of cut generators CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); generator1.setMaxProbeRoot(saveSolver->getNumCols()); generator1.setMaxElements(100); generator1.setMaxLookRoot(50); generator1.setRowCuts(3); // Add in generators process.addCutGenerator(&generator1); process.messageHandler()->setLogLevel(cbcModel->logLevel()); OsiSolverInterface * solver2 = process.preProcessNonDefault(*saveSolver, 0, 10); // Tell solver we are not in Branch and Cut saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (solver2) solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (!solver2) { std::cout << "Pre-processing says infeasible!" << std::endl; delete saveSolver; #ifndef NDEBUG returnCode = -1; #endif } else { std::cout << "processed model has " << solver2->getNumRows() << " rows, " << solver2->getNumCols() << " and " << solver2->getNumElements() << std::endl; // we have to keep solver2 so pass clone solver2 = solver2->clone(); //solver2->writeMps("intmodel"); cbcModel->assignSolver(solver2); cbcModel->initialSolve(); cbcModel->branchAndBound(); // For best solution int numberColumns = newSolver.getNumCols(); if (cbcModel->getMinimizationObjValue() < 1.0e50) { // post process process.postProcess(*cbcModel->solver()); // Solution now back in saveSolver cbcModel->assignSolver(saveSolver); memcpy(cbcModel->bestSolution(), cbcModel->solver()->getColSolution(), numberColumns*sizeof(double)); // put back in original solver newSolver.setColSolution(cbcModel->bestSolution()); } else { delete saveSolver; } } } assert (!returnCode); abort(); return solution; } // Analyze constraints to see which are convex (quadratic) void OsiSolverLink::analyzeObjects() { // space for starts int numberColumns = coinModel_.numberColumns(); int * start = new int [numberColumns+1]; const double * rowLower = getRowLower(); const double * rowUpper = getRowUpper(); for (int iNon = 0; iNon < numberNonLinearRows_; iNon++) { int iRow = rowNonLinear_[iNon]; int numberElements = startNonLinear_[iNon+1] - startNonLinear_[iNon]; // triplet arrays int * iColumn = new int [2*numberElements+1]; int * jColumn = new int [2*numberElements]; double * element = new double [2*numberElements]; int i; int n = 0; for ( i = startNonLinear_[iNon]; i < startNonLinear_[iNon+1]; i++) { OsiBiLinear * obj = dynamic_cast (object_[whichNonLinear_[i]]); assert (obj); int xColumn = obj->xColumn(); int yColumn = obj->yColumn(); double coefficient = obj->coefficient(); if (xColumn != yColumn) { iColumn[n] = xColumn; jColumn[n] = yColumn; element[n++] = coefficient; iColumn[n] = yColumn; jColumn[n] = xColumn; element[n++] = coefficient; } else { iColumn[n] = xColumn; jColumn[n] = xColumn; element[n++] = coefficient; } } // First sort in column order CoinSort_3(iColumn, iColumn + n, jColumn, element); // marker at end iColumn[n] = numberColumns; int lastI = iColumn[0]; // compute starts start[0] = 0; for (i = 1; i < n + 1; i++) { if (iColumn[i] != lastI) { while (lastI < iColumn[i]) { start[lastI+1] = i; lastI++; } lastI = iColumn[i]; } } // -1 unknown, 0 convex, 1 nonconvex int status = -1; int statusNegative = -1; int numberLong = 0; // number with >2 elements for (int k = 0; k < numberColumns; k++) { int first = start[k]; int last = start[k+1]; if (last > first) { int j; double diagonal = 0.0; int whichK = -1; for (j = first; j < last; j++) { if (jColumn[j] == k) { diagonal = element[j]; status = diagonal > 0 ? 0 : 1; statusNegative = diagonal < 0 ? 0 : 1; whichK = (j == first) ? j + 1 : j - 1; break; } } if (last == first + 1) { // just one entry if (!diagonal) { // one off diagonal - not positive semi definite status = 1; statusNegative = 1; } } else if (diagonal) { if (last == first + 2) { // other column and element double otherElement = element[whichK];; int otherColumn = jColumn[whichK]; double otherDiagonal = 0.0; // check 2x2 determinant - unless past and 2 long if (otherColumn > i || start[otherColumn+1] > start[otherColumn] + 2) { for (j = start[otherColumn]; j < start[otherColumn+1]; j++) { if (jColumn[j] == otherColumn) { otherDiagonal = element[j]; break; } } // determinant double determinant = diagonal * otherDiagonal - otherElement * otherElement; if (determinant < -1.0e-12) { // not positive semi definite status = 1; statusNegative = 1; } else if (start[otherColumn+1] > start[otherColumn] + 2 && determinant < 1.0e-12) { // not positive semi definite status = 1; statusNegative = 1; } } } else { numberLong++; } } } } if ((status == 0 || statusNegative == 0) && numberLong) { // need to do more work //printf("Needs more work\n"); } assert (status > 0 || statusNegative > 0); if (!status) { convex_[iNon] = 1; // equality may be ok if (rowUpper[iRow] < 1.0e20) specialOptions2_ |= 8; else convex_[iNon] = 0; } else if (!statusNegative) { convex_[iNon] = -1; // equality may be ok if (rowLower[iRow] > -1.0e20) specialOptions2_ |= 8; else convex_[iNon] = 0; } else { convex_[iNon] = 0; } //printf("Convexity of row %d is %d\n",iRow,convex_[iNon]); delete [] iColumn; delete [] jColumn; delete [] element; } delete [] start; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * OsiSolverLink::clone(bool /*copyData*/) const { //assert (copyData); OsiSolverLink * newModel = new OsiSolverLink(*this); return newModel; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiSolverLink::OsiSolverLink ( const OsiSolverLink & rhs) : OsiSolverInterface(rhs), CbcOsiSolver(rhs) { gutsOfDestructor(true); gutsOfCopy(rhs); // something odd happens - try this OsiSolverInterface::operator=(rhs); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiSolverLink::~OsiSolverLink () { gutsOfDestructor(); } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiSolverLink & OsiSolverLink::operator=(const OsiSolverLink & rhs) { if (this != &rhs) { gutsOfDestructor(); CbcOsiSolver::operator=(rhs); gutsOfCopy(rhs); } return *this; } void OsiSolverLink::gutsOfDestructor(bool justNullify) { if (!justNullify) { delete matrix_; delete originalRowCopy_; delete [] info_; delete [] bestSolution_; delete quadraticModel_; delete [] startNonLinear_; delete [] rowNonLinear_; delete [] convex_; delete [] whichNonLinear_; delete [] fixVariables_; } matrix_ = NULL; originalRowCopy_ = NULL; quadraticModel_ = NULL; numberNonLinearRows_ = 0; startNonLinear_ = NULL; rowNonLinear_ = NULL; convex_ = NULL; whichNonLinear_ = NULL; info_ = NULL; fixVariables_ = NULL; numberVariables_ = 0; specialOptions2_ = 0; objectiveRow_ = -1; objectiveVariable_ = -1; bestSolution_ = NULL; bestObjectiveValue_ = 1.0e100; defaultMeshSize_ = 1.0e-4; defaultBound_ = 1.0e5; integerPriority_ = 1000; biLinearPriority_ = 10000; numberFix_ = 0; } void OsiSolverLink::gutsOfCopy(const OsiSolverLink & rhs) { coinModel_ = rhs.coinModel_; numberVariables_ = rhs.numberVariables_; numberNonLinearRows_ = rhs.numberNonLinearRows_; specialOptions2_ = rhs.specialOptions2_; objectiveRow_ = rhs.objectiveRow_; objectiveVariable_ = rhs.objectiveVariable_; bestObjectiveValue_ = rhs.bestObjectiveValue_; defaultMeshSize_ = rhs.defaultMeshSize_; defaultBound_ = rhs.defaultBound_; integerPriority_ = rhs.integerPriority_; biLinearPriority_ = rhs.biLinearPriority_; numberFix_ = rhs.numberFix_; if (numberVariables_) { if (rhs.matrix_) matrix_ = new CoinPackedMatrix(*rhs.matrix_); else matrix_ = NULL; if (rhs.originalRowCopy_) originalRowCopy_ = new CoinPackedMatrix(*rhs.originalRowCopy_); else originalRowCopy_ = NULL; info_ = new OsiLinkedBound [numberVariables_]; for (int i = 0; i < numberVariables_; i++) { info_[i] = OsiLinkedBound(rhs.info_[i]); } if (rhs.bestSolution_) { bestSolution_ = CoinCopyOfArray(rhs.bestSolution_, modelPtr_->getNumCols()); } else { bestSolution_ = NULL; } } if (numberNonLinearRows_) { startNonLinear_ = CoinCopyOfArray(rhs.startNonLinear_, numberNonLinearRows_ + 1); rowNonLinear_ = CoinCopyOfArray(rhs.rowNonLinear_, numberNonLinearRows_); convex_ = CoinCopyOfArray(rhs.convex_, numberNonLinearRows_); int numberEntries = startNonLinear_[numberNonLinearRows_]; whichNonLinear_ = CoinCopyOfArray(rhs.whichNonLinear_, numberEntries); } if (rhs.quadraticModel_) { quadraticModel_ = new ClpSimplex(*rhs.quadraticModel_); } else { quadraticModel_ = NULL; } fixVariables_ = CoinCopyOfArray(rhs.fixVariables_, numberFix_); } // Add a bound modifier void OsiSolverLink::addBoundModifier(bool upperBoundAffected, bool useUpperBound, int whichVariable, int whichVariableAffected, double multiplier) { bool found = false; int i; for ( i = 0; i < numberVariables_; i++) { if (info_[i].variable() == whichVariable) { found = true; break; } } if (!found) { // add in OsiLinkedBound * temp = new OsiLinkedBound [numberVariables_+1]; for (int i = 0; i < numberVariables_; i++) temp[i] = info_[i]; delete [] info_; info_ = temp; info_[numberVariables_++] = OsiLinkedBound(this, whichVariable, 0, NULL, NULL, NULL); } info_[i].addBoundModifier(upperBoundAffected, useUpperBound, whichVariableAffected, multiplier); } // Update coefficients int OsiSolverLink::updateCoefficients(ClpSimplex * solver, CoinPackedMatrix * matrix) { double * lower = solver->columnLower(); double * upper = solver->columnUpper(); double * objective = solver->objective(); int numberChanged = 0; for (int iObject = 0; iObject < numberObjects_; iObject++) { OsiBiLinear * obj = dynamic_cast (object_[iObject]); if (obj) { numberChanged += obj->updateCoefficients(lower, upper, objective, matrix, &basis_); } } return numberChanged; } // Set best solution found internally void OsiSolverLink::setBestSolution(const double * solution, int numberColumns) { delete [] bestSolution_; int numberColumnsThis = modelPtr_->numberColumns(); bestSolution_ = new double [numberColumnsThis]; CoinZeroN(bestSolution_, numberColumnsThis); memcpy(bestSolution_, solution, CoinMin(numberColumns, numberColumnsThis)*sizeof(double)); } /* Two tier integer problem where when set of variables with priority less than this are fixed the problem becomes an easier integer problem */ void OsiSolverLink::setFixedPriority(int priorityValue) { delete [] fixVariables_; fixVariables_ = NULL; numberFix_ = 0; int i; for ( i = 0; i < numberObjects_; i++) { OsiSimpleInteger * obj = dynamic_cast (object_[i]); if (obj) { #ifndef NDEBUG int iColumn = obj->columnNumber(); assert (iColumn >= 0); #endif if (obj->priority() < priorityValue) numberFix_++; } } if (numberFix_) { specialOptions2_ |= 1; fixVariables_ = new int [numberFix_]; numberFix_ = 0; // need to make sure coinModel_ is correct int numberColumns = coinModel_.numberColumns(); char * highPriority = new char [numberColumns]; CoinZeroN(highPriority, numberColumns); for ( i = 0; i < numberObjects_; i++) { OsiSimpleInteger * obj = dynamic_cast (object_[i]); if (obj) { int iColumn = obj->columnNumber(); assert (iColumn >= 0); if (iColumn < numberColumns) { if (obj->priority() < priorityValue) { object_[i] = new OsiSimpleFixedInteger(*obj); delete obj; fixVariables_[numberFix_++] = iColumn; highPriority[iColumn] = 1; } } } } CoinModel * newModel = coinModel_.reorder(highPriority); if (newModel) { coinModel_ = * newModel; } else { printf("Unable to use priorities\n"); delete [] fixVariables_; fixVariables_ = NULL; numberFix_ = 0; } delete newModel; delete [] highPriority; } } // Gets correct form for a quadratic row - user to delete CoinPackedMatrix * OsiSolverLink::quadraticRow(int rowNumber, double * linearRow) const { int numberColumns = coinModel_.numberColumns(); CoinZeroN(linearRow, numberColumns); int numberElements = 0; #ifndef NDEBUG int numberRows = coinModel_.numberRows(); assert (rowNumber >= 0 && rowNumber < numberRows); #endif CoinModelLink triple = coinModel_.firstInRow(rowNumber); while (triple.column() >= 0) { int iColumn = triple.column(); const char * expr = coinModel_.getElementAsString(rowNumber, iColumn); if (strcmp(expr, "Numeric")) { // try and see which columns assert (strlen(expr) < 20000); char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_); // must be column unless first when may be linear term if (jColumn >= 0) { numberElements++; } else if (jColumn == -2) { linearRow[iColumn] = value; } else { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } else { linearRow[iColumn] = coinModel_.getElement(rowNumber, iColumn); } triple = coinModel_.next(triple); } if (!numberElements) { return NULL; } else { int * column = new int[numberElements]; int * column2 = new int[numberElements]; double * element = new double[numberElements]; numberElements = 0; CoinModelLink triple = coinModel_.firstInRow(rowNumber); while (triple.column() >= 0) { int iColumn = triple.column(); const char * expr = coinModel_.getElementAsString(rowNumber, iColumn); if (strcmp(expr, "Numeric")) { // try and see which columns assert (strlen(expr) < 20000); char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel_); // must be column unless first when may be linear term if (jColumn >= 0) { column[numberElements] = iColumn; column2[numberElements] = jColumn; element[numberElements++] = value; } else if (jColumn != -2) { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } triple = coinModel_.next(triple); } return new CoinPackedMatrix(true, column2, column, element, numberElements); } } /* Problem specific Returns -1 if node fathomed and no solution 0 if did nothing 1 if node fathomed and solution allFixed is true if all LinkedBound variables are fixed */ int OsiSolverLink::fathom(bool allFixed) { int returnCode = 0; if (allFixed) { // solve anyway OsiClpSolverInterface::resolve(); if (!isProvenOptimal()) { printf("cutoff before fathoming\n"); return -1; } // all fixed so we can reformulate OsiClpSolverInterface newSolver; // set values const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); int i; for (i = 0; i < numberFix_; i++ ) { int iColumn = fixVariables_[i]; double lo = lower[iColumn]; #ifndef NDEBUG double up = upper[iColumn]; assert (lo == up); #endif //printf("column %d fixed to %g\n",iColumn,lo); coinModel_.associateElement(coinModel_.columnName(iColumn), lo); } newSolver.loadFromCoinModel(coinModel_, true); for (i = 0; i < numberFix_; i++ ) { int iColumn = fixVariables_[i]; newSolver.setColLower(iColumn, lower[iColumn]); newSolver.setColUpper(iColumn, lower[iColumn]); } // see if everything with objective fixed const double * objective = modelPtr_->objective(); int numberColumns = newSolver.getNumCols(); bool zeroObjective = true; double sum = 0.0; for (i = 0; i < numberColumns; i++) { if (upper[i] > lower[i] && objective[i]) { zeroObjective = false; break; } else { sum += lower[i] * objective[i]; } } int fake[] = {5, 4, 3, 2, 0, 0, 0}; bool onOptimalPath = true; for (i = 0; i < 7; i++) { if (static_cast (upper[i]) != fake[i]) onOptimalPath = false; } if (onOptimalPath) printf("possible\n"); if (zeroObjective) { // randomize objective ClpSimplex * clpModel = newSolver.getModelPtr(); const double * element = clpModel->matrix()->getMutableElements(); //const int * row = clpModel->matrix()->getIndices(); const CoinBigIndex * columnStart = clpModel->matrix()->getVectorStarts(); const int * columnLength = clpModel->matrix()->getVectorLengths(); double * objective = clpModel->objective(); for (i = 0; i < numberColumns; i++) { if (clpModel->isInteger(i)) { double value = 0.0; for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { value += fabs(element[j]); } objective[i] = value; } } } //newSolver.writeMps("xx"); CbcModel model(newSolver); // Now do requested saves and modifications CbcModel * cbcModel = & model; OsiSolverInterface * osiModel = model.solver(); OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (osiModel); ClpSimplex * clpModel = osiclpModel->getModelPtr(); CglProbing probing; probing.setMaxProbe(10); probing.setMaxLook(10); probing.setMaxElements(200); probing.setMaxProbeRoot(50); probing.setMaxLookRoot(10); probing.setRowCuts(3); probing.setRowCuts(0); probing.setUsingObjective(true); cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1); CglGomory gomory; gomory.setLimitAtRoot(512); cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1); CglKnapsackCover knapsackCover; cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1); CglClique clique; clique.setStarCliqueReport(false); clique.setRowCliqueReport(false); clique.setMinViolation(0.1); cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1); CglMixedIntegerRounding2 mixedIntegerRounding2; cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1); CglFlowCover flowCover; cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1); CglTwomir twomir; twomir.setMaxElements(250); cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1); cbcModel->cutGenerator(6)->setTiming(true); CbcHeuristicFPump heuristicFPump(*cbcModel); heuristicFPump.setWhen(1); heuristicFPump.setMaximumPasses(20); heuristicFPump.setDefaultRounding(0.5); cbcModel->addHeuristic(&heuristicFPump); CbcRounding rounding(*cbcModel); cbcModel->addHeuristic(&rounding); CbcHeuristicLocal heuristicLocal(*cbcModel); heuristicLocal.setSearchType(1); cbcModel->addHeuristic(&heuristicLocal); CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel); cbcModel->addHeuristic(&heuristicGreedyCover); CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel); cbcModel->addHeuristic(&heuristicGreedyEquality); CbcCompareDefault compare; cbcModel->setNodeComparison(compare); cbcModel->setNumberBeforeTrust(5); cbcModel->setSpecialOptions(2); cbcModel->messageHandler()->setLogLevel(1); cbcModel->setMaximumCutPassesAtRoot(-100); cbcModel->setMaximumCutPasses(1); cbcModel->setMinimumDrop(0.05); clpModel->setNumberIterations(1); // For branchAndBound this may help clpModel->defaultFactorizationFrequency(); clpModel->setDualBound(6.71523e+07); clpModel->setPerturbation(50); osiclpModel->setSpecialOptions(193); osiclpModel->messageHandler()->setLogLevel(0); osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100); osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry); // You can save some time by switching off message building // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL); // Solve cbcModel->initialSolve(); //double cutoff = model_->getCutoff(); if (zeroObjective || !cbcModel_) cbcModel->setCutoff(1.0e50); else cbcModel->setCutoff(cbcModel_->getCutoff()); // to change exits bool isFeasible = false; int saveLogLevel = clpModel->logLevel(); clpModel->setLogLevel(0); if (clpModel->tightenPrimalBounds() != 0) { clpModel->setLogLevel(saveLogLevel); returnCode = -1; // infeasible//std::cout<<"Problem is infeasible - tightenPrimalBounds!"<setLogLevel(saveLogLevel); clpModel->dual(); // clean up // compute some things using problem size cbcModel->setMinimumDrop(CoinMin(5.0e-2, fabs(cbcModel->getMinimizationObjValue())*1.0e-3 + 1.0e-4)); if (cbcModel->getNumCols() < 500) cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (cbcModel->getNumCols() < 5000) cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop else cbcModel->setMaximumCutPassesAtRoot(20); cbcModel->setMaximumCutPasses(1); // Hand coded preprocessing CglPreProcess process; OsiSolverInterface * saveSolver = cbcModel->solver()->clone(); // Tell solver we are in Branch and Cut saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ; // Default set of cut generators CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); generator1.setMaxProbeRoot(saveSolver->getNumCols()); generator1.setMaxElements(100); generator1.setMaxLookRoot(50); generator1.setRowCuts(3); // Add in generators process.addCutGenerator(&generator1); process.messageHandler()->setLogLevel(cbcModel->logLevel()); OsiSolverInterface * solver2 = process.preProcessNonDefault(*saveSolver, 0, 10); // Tell solver we are not in Branch and Cut saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (solver2) solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (!solver2) { std::cout << "Pre-processing says infeasible!" << std::endl; delete saveSolver; returnCode = -1; } else { std::cout << "processed model has " << solver2->getNumRows() << " rows, " << solver2->getNumCols() << " and " << solver2->getNumElements() << std::endl; // we have to keep solver2 so pass clone solver2 = solver2->clone(); //solver2->writeMps("intmodel"); cbcModel->assignSolver(solver2); cbcModel->initialSolve(); if (zeroObjective) { cbcModel->setMaximumSolutions(1); // just getting a solution #ifdef JJF_ZERO OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (cbcModel->solver()); ClpSimplex * clpModel = osiclpModel->getModelPtr(); const double * element = clpModel->matrix()->getMutableElements(); //const int * row = clpModel->matrix()->getIndices(); const CoinBigIndex * columnStart = clpModel->matrix()->getVectorStarts(); const int * columnLength = clpModel->matrix()->getVectorLengths(); int n = clpModel->numberColumns(); int * sort2 = new int[n]; int * pri = new int[n]; double * sort = new double[n]; int i; int nint = 0; for (i = 0; i < n; i++) { if (clpModel->isInteger(i)) { double largest = 0.0; for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { largest = CoinMax(largest, fabs(element[j])); } sort2[nint] = nint; sort[nint++] = -largest; } } CoinSort_2(sort, sort + nint, sort2); int kpri = 1; double last = sort[0]; for (i = 0; i < nint; i++) { if (sort[i] != last) { kpri++; last = sort[i]; } pri[sort2[i]] = kpri; } cbcModel->passInPriorities(pri, false); delete [] sort; delete [] sort2; delete [] pri; #endif } cbcModel->branchAndBound(); // For best solution int numberColumns = newSolver.getNumCols(); if (cbcModel->getMinimizationObjValue() < 1.0e50) { // post process process.postProcess(*cbcModel->solver()); // Solution now back in saveSolver cbcModel->assignSolver(saveSolver); memcpy(cbcModel->bestSolution(), cbcModel->solver()->getColSolution(), numberColumns*sizeof(double)); // put back in original solver newSolver.setColSolution(cbcModel->bestSolution()); isFeasible = true; } else { delete saveSolver; } } //const double * solution = newSolver.getColSolution(); if (isFeasible && cbcModel->getMinimizationObjValue() < 1.0e50) { int numberColumns = this->getNumCols(); int i; const double * solution = cbcModel->bestSolution(); int numberColumns2 = newSolver.getNumCols(); for (i = 0; i < numberColumns2; i++) { double value = solution[i]; assert (fabs(value - floor(value + 0.5)) < 0.0001); value = floor(value + 0.5); this->setColLower(i, value); this->setColUpper(i, value); } for (; i < numberColumns; i++) { this->setColLower(i, 0.0); this->setColUpper(i, 1.1); } // but take off cuts int numberRows = getNumRows(); int numberRows2 = cbcModel_->continuousSolver()->getNumRows(); for (i = numberRows2; i < numberRows; i++) setRowBounds(i, -COIN_DBL_MAX, COIN_DBL_MAX); initialSolve(); //if (!isProvenOptimal()) //getModelPtr()->writeMps("bad.mps"); if (isProvenOptimal()) { delete [] bestSolution_; bestSolution_ = CoinCopyOfArray(modelPtr_->getColSolution(), modelPtr_->getNumCols()); bestObjectiveValue_ = modelPtr_->objectiveValue(); printf("BB best value %g\n", bestObjectiveValue_); returnCode = 1; } else { printf("*** WHY BAD SOL\n"); returnCode = -1; } } else { modelPtr_->setProblemStatus(1); modelPtr_->setObjectiveValue(COIN_DBL_MAX); returnCode = -1; } } } return returnCode; } //############################################################################# // Constructors, destructors and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiLinkedBound::OsiLinkedBound () { model_ = NULL; variable_ = -1; numberAffected_ = 0; maximumAffected_ = numberAffected_; affected_ = NULL; } // Useful Constructor OsiLinkedBound::OsiLinkedBound(OsiSolverInterface * model, int variable, int numberAffected, const int * positionL, const int * positionU, const double * multiplier) { model_ = model; variable_ = variable; numberAffected_ = 2 * numberAffected; maximumAffected_ = numberAffected_; if (numberAffected_) { affected_ = new boundElementAction[numberAffected_]; int n = 0; for (int i = 0; i < numberAffected; i++) { // LB boundElementAction action; action.affect = 2; action.ubUsed = 0; action.type = 0; action.affected = positionL[i]; action.multiplier = multiplier[i]; affected_[n++] = action; // UB action.affect = 2; action.ubUsed = 1; action.type = 0; action.affected = positionU[i]; action.multiplier = multiplier[i]; affected_[n++] = action; } } else { affected_ = NULL; } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiLinkedBound::OsiLinkedBound ( const OsiLinkedBound & rhs) { model_ = rhs.model_; variable_ = rhs.variable_; numberAffected_ = rhs.numberAffected_; maximumAffected_ = rhs.maximumAffected_; if (numberAffected_) { affected_ = new boundElementAction[maximumAffected_]; memcpy(affected_, rhs.affected_, numberAffected_*sizeof(boundElementAction)); } else { affected_ = NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiLinkedBound::~OsiLinkedBound () { delete [] affected_; } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiLinkedBound & OsiLinkedBound::operator=(const OsiLinkedBound & rhs) { if (this != &rhs) { delete [] affected_; model_ = rhs.model_; variable_ = rhs.variable_; numberAffected_ = rhs.numberAffected_; maximumAffected_ = rhs.maximumAffected_; if (numberAffected_) { affected_ = new boundElementAction[maximumAffected_]; memcpy(affected_, rhs.affected_, numberAffected_*sizeof(boundElementAction)); } else { affected_ = NULL; } } return *this; } // Add a bound modifier void OsiLinkedBound::addBoundModifier(bool upperBoundAffected, bool useUpperBound, int whichVariable, double multiplier) { if (numberAffected_ == maximumAffected_) { maximumAffected_ = maximumAffected_ + 10 + maximumAffected_ / 4; boundElementAction * temp = new boundElementAction[maximumAffected_]; memcpy(temp, affected_, numberAffected_*sizeof(boundElementAction)); delete [] affected_; affected_ = temp; } boundElementAction action; action.affect = static_cast(upperBoundAffected ? 1 : 0); action.ubUsed = static_cast(useUpperBound ? 1 : 0); action.type = 2; action.affected = static_cast(whichVariable); action.multiplier = multiplier; affected_[numberAffected_++] = action; } // Update other bounds void OsiLinkedBound::updateBounds(ClpSimplex * solver) { double * lower = solver->columnLower(); double * upper = solver->columnUpper(); double lo = lower[variable_]; double up = upper[variable_]; // printf("bounds for %d are %g and %g\n",variable_,lo,up); for (int j = 0; j < numberAffected_; j++) { if (affected_[j].affect < 2) { double multiplier = affected_[j].multiplier; assert (affected_[j].type == 2); int iColumn = affected_[j].affected; double useValue = (affected_[j].ubUsed) ? up : lo; if (affected_[j].affect == 0) lower[iColumn] = CoinMin(upper[iColumn], CoinMax(lower[iColumn], multiplier * useValue)); else upper[iColumn] = CoinMax(lower[iColumn], CoinMin(upper[iColumn], multiplier * useValue)); } } } #ifdef JJF_ZERO // Add an element modifier void OsiLinkedBound::addCoefficientModifier(bool useUpperBound, int position, double multiplier) { if (numberAffected_ == maximumAffected_) { maximumAffected_ = maximumAffected_ + 10 + maximumAffected_ / 4; boundElementAction * temp = new boundElementAction[maximumAffected_]; memcpy(temp, affected_, numberAffected_*sizeof(boundElementAction)); delete [] affected_; affected_ = temp; } boundElementAction action; action.affect = 2; action.ubUsed = useUpperBound ? 1 : 0; action.type = 0; action.affected = position; action.multiplier = multiplier; affected_[numberAffected_++] = action; } // Update coefficients void OsiLinkedBound::updateCoefficients(ClpSimplex * solver, CoinPackedMatrix * matrix) { double * lower = solver->columnLower(); double * upper = solver->columnUpper(); double * element = matrix->getMutableElements(); double lo = lower[variable_]; double up = upper[variable_]; // printf("bounds for %d are %g and %g\n",variable_,lo,up); for (int j = 0; j < numberAffected_; j++) { if (affected_[j].affect == 2) { double multiplier = affected_[j].multiplier; assert (affected_[j].type == 0); int position = affected_[j].affected; //double old = element[position]; if (affected_[j].ubUsed) element[position] = multiplier * up; else element[position] = multiplier * lo; //if ( old != element[position]) //printf("change at %d from %g to %g\n",position,old,element[position]); } } } #endif // Default Constructor CbcHeuristicDynamic3::CbcHeuristicDynamic3() : CbcHeuristic() { } // Constructor from model CbcHeuristicDynamic3::CbcHeuristicDynamic3(CbcModel & model) : CbcHeuristic(model) { } // Destructor CbcHeuristicDynamic3::~CbcHeuristicDynamic3 () { } // Clone CbcHeuristic * CbcHeuristicDynamic3::clone() const { return new CbcHeuristicDynamic3(*this); } // Copy constructor CbcHeuristicDynamic3::CbcHeuristicDynamic3(const CbcHeuristicDynamic3 & rhs) : CbcHeuristic(rhs) { } // Returns 1 if solution, 0 if not int CbcHeuristicDynamic3::solution(double & solutionValue, double * betterSolution) { if (!model_) return 0; OsiSolverLink * clpSolver = dynamic_cast (model_->solver()); assert (clpSolver); double newSolutionValue = clpSolver->bestObjectiveValue(); const double * solution = clpSolver->bestSolution(); if (newSolutionValue < solutionValue && solution) { int numberColumns = clpSolver->getNumCols(); // new solution memcpy(betterSolution, solution, numberColumns*sizeof(double)); solutionValue = newSolutionValue; return 1; } else { return 0; } } // update model void CbcHeuristicDynamic3::setModel(CbcModel * model) { model_ = model; } // Resets stuff if model changes void CbcHeuristicDynamic3::resetModel(CbcModel * model) { model_ = model; } #include #include #include //#define CBC_DEBUG #include "OsiSolverInterface.hpp" //#include "OsiBranchLink.hpp" #include "CoinError.hpp" #include "CoinHelperFunctions.hpp" #include "CoinPackedMatrix.hpp" #include "CoinWarmStartBasis.hpp" // Default Constructor OsiOldLink::OsiOldLink () : OsiSOS(), numberLinks_(0) { } // Useful constructor (which are indices) OsiOldLink::OsiOldLink (const OsiSolverInterface * /*solver*/, int numberMembers, int numberLinks, int first , const double * weights, int /*identifier*/) : OsiSOS(), numberLinks_(numberLinks) { numberMembers_ = numberMembers; members_ = NULL; sosType_ = 1; if (numberMembers_) { weights_ = new double[numberMembers_]; members_ = new int[numberMembers_*numberLinks_]; if (weights) { memcpy(weights_, weights, numberMembers_*sizeof(double)); } else { for (int i = 0; i < numberMembers_; i++) weights_[i] = i; } // weights must be increasing int i; #ifndef NDEBUG for (i = 1; i < numberMembers_; i++) assert (weights_[i] > weights_[i-1] + 1.0e-12); #endif for (i = 0; i < numberMembers_*numberLinks_; i++) { members_[i] = first + i; } } else { weights_ = NULL; } } // Useful constructor (which are indices) OsiOldLink::OsiOldLink (const OsiSolverInterface * /*solver*/, int numberMembers, int numberLinks, int /*sosType*/, const int * which , const double * weights, int /*identifier*/) : OsiSOS(), numberLinks_(numberLinks) { numberMembers_ = numberMembers; members_ = NULL; sosType_ = 1; if (numberMembers_) { weights_ = new double[numberMembers_]; members_ = new int[numberMembers_*numberLinks_]; if (weights) { memcpy(weights_, weights, numberMembers_*sizeof(double)); } else { for (int i = 0; i < numberMembers_; i++) weights_[i] = i; } // weights must be increasing int i; #ifndef NDEBUG for (i = 1; i < numberMembers_; i++) assert (weights_[i] > weights_[i-1] + 1.0e-12); #endif for (i = 0; i < numberMembers_*numberLinks_; i++) { members_[i] = which[i]; } } else { weights_ = NULL; } } // Copy constructor OsiOldLink::OsiOldLink ( const OsiOldLink & rhs) : OsiSOS(rhs) { numberLinks_ = rhs.numberLinks_; if (numberMembers_) { delete [] members_; members_ = CoinCopyOfArray(rhs.members_, numberMembers_ * numberLinks_); } } // Clone OsiObject * OsiOldLink::clone() const { return new OsiOldLink(*this); } // Assignment operator OsiOldLink & OsiOldLink::operator=( const OsiOldLink & rhs) { if (this != &rhs) { OsiSOS::operator=(rhs); delete [] members_; numberLinks_ = rhs.numberLinks_; if (numberMembers_) { members_ = CoinCopyOfArray(rhs.members_, numberMembers_ * numberLinks_); } else { members_ = NULL; } } return *this; } // Destructor OsiOldLink::~OsiOldLink () { } // Infeasibility - large is 0.5 double OsiOldLink::infeasibility(const OsiBranchingInformation * info, int & whichWay) const { int j; int firstNonZero = -1; int lastNonZero = -1; const double * solution = info->solution_; //const double * lower = info->lower_; const double * upper = info->upper_; double integerTolerance = info->integerTolerance_; double weight = 0.0; double sum = 0.0; // check bounds etc double lastWeight = -1.0e100; int base = 0; for (j = 0; j < numberMembers_; j++) { for (int k = 0; k < numberLinks_; k++) { int iColumn = members_[base+k]; if (lastWeight >= weights_[j] - 1.0e-7) throw CoinError("Weights too close together in OsiLink", "infeasibility", "OsiLink"); lastWeight = weights_[j]; double value = CoinMax(0.0, solution[iColumn]); sum += value; if (value > integerTolerance && upper[iColumn]) { // Possibly due to scaling a fixed variable might slip through if (value > upper[iColumn] + 1.0e-8) { #ifdef OSI_DEBUG printf("** Variable %d (%d) has value %g and upper bound of %g\n", iColumn, j, value, upper[iColumn]); #endif } value = CoinMin(value, upper[iColumn]); weight += weights_[j] * value; if (firstNonZero < 0) firstNonZero = j; lastNonZero = j; } } base += numberLinks_; } double valueInfeasibility; whichWay = 1; whichWay_ = 1; if (lastNonZero - firstNonZero >= sosType_) { // find where to branch assert (sum > 0.0); weight /= sum; valueInfeasibility = lastNonZero - firstNonZero + 1; valueInfeasibility *= 0.5 / static_cast (numberMembers_); //#define DISTANCE #ifdef DISTANCE assert (sosType_ == 1); // code up /* may still be satisfied. For LOS type 2 we might wish to move coding around and keep initial info in model_ for speed */ int iWhere; bool possible = false; for (iWhere = firstNonZero; iWhere <= lastNonZero; iWhere++) { if (fabs(weight - weights_[iWhere]) < 1.0e-8) { possible = true; break; } } if (possible) { // One could move some of this (+ arrays) into model_ const CoinPackedMatrix * matrix = solver->getMatrixByCol(); const double * element = matrix->getMutableElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * rowSolution = solver->getRowActivity(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = matrix->getNumRows(); double * array = new double [numberRows]; CoinZeroN(array, numberRows); int * which = new int [numberRows]; int n = 0; int base = numberLinks_ * firstNonZero; for (j = firstNonZero; j <= lastNonZero; j++) { for (int k = 0; k < numberLinks_; k++) { int iColumn = members_[base+k]; double value = CoinMax(0.0, solution[iColumn]); if (value > integerTolerance && upper[iColumn]) { value = CoinMin(value, upper[iColumn]); for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double a = array[iRow]; if (a) { a += value * element[j]; if (!a) a = 1.0e-100; } else { which[n++] = iRow; a = value * element[j]; assert (a); } array[iRow] = a; } } } base += numberLinks_; } base = numberLinks_ * iWhere; for (int k = 0; k < numberLinks_; k++) { int iColumn = members_[base+k]; const double value = 1.0; for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double a = array[iRow]; if (a) { a -= value * element[j]; if (!a) a = 1.0e-100; } else { which[n++] = iRow; a = -value * element[j]; assert (a); } array[iRow] = a; } } for (j = 0; j < n; j++) { int iRow = which[j]; // moving to point will increase row solution by this double distance = array[iRow]; if (distance > 1.0e-8) { if (distance + rowSolution[iRow] > rowUpper[iRow] + 1.0e-8) { possible = false; break; } } else if (distance < -1.0e-8) { if (distance + rowSolution[iRow] < rowLower[iRow] - 1.0e-8) { possible = false; break; } } } for (j = 0; j < n; j++) array[which[j]] = 0.0; delete [] array; delete [] which; if (possible) { valueInfeasibility = 0.0; printf("possible %d %d %d\n", firstNonZero, lastNonZero, iWhere); } } #endif } else { valueInfeasibility = 0.0; // satisfied } infeasibility_ = valueInfeasibility; otherInfeasibility_ = 1.0 - valueInfeasibility; return valueInfeasibility; } // This looks at solution and sets bounds to contain solution double OsiOldLink::feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const { int j; int firstNonZero = -1; int lastNonZero = -1; const double * solution = info->solution_; const double * upper = info->upper_; double integerTolerance = info->integerTolerance_; double weight = 0.0; double sum = 0.0; int base = 0; for (j = 0; j < numberMembers_; j++) { for (int k = 0; k < numberLinks_; k++) { int iColumn = members_[base+k]; double value = CoinMax(0.0, solution[iColumn]); sum += value; if (value > integerTolerance && upper[iColumn]) { weight += weights_[j] * value; if (firstNonZero < 0) firstNonZero = j; lastNonZero = j; } } base += numberLinks_; } #ifdef DISTANCE if (lastNonZero - firstNonZero > sosType_ - 1) { /* may still be satisfied. For LOS type 2 we might wish to move coding around and keep initial info in model_ for speed */ int iWhere; bool possible = false; for (iWhere = firstNonZero; iWhere <= lastNonZero; iWhere++) { if (fabs(weight - weights_[iWhere]) < 1.0e-8) { possible = true; break; } } if (possible) { // One could move some of this (+ arrays) into model_ const CoinPackedMatrix * matrix = solver->getMatrixByCol(); const double * element = matrix->getMutableElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * rowSolution = solver->getRowActivity(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = matrix->getNumRows(); double * array = new double [numberRows]; CoinZeroN(array, numberRows); int * which = new int [numberRows]; int n = 0; int base = numberLinks_ * firstNonZero; for (j = firstNonZero; j <= lastNonZero; j++) { for (int k = 0; k < numberLinks_; k++) { int iColumn = members_[base+k]; double value = CoinMax(0.0, solution[iColumn]); if (value > integerTolerance && upper[iColumn]) { value = CoinMin(value, upper[iColumn]); for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double a = array[iRow]; if (a) { a += value * element[j]; if (!a) a = 1.0e-100; } else { which[n++] = iRow; a = value * element[j]; assert (a); } array[iRow] = a; } } } base += numberLinks_; } base = numberLinks_ * iWhere; for (int k = 0; k < numberLinks_; k++) { int iColumn = members_[base+k]; const double value = 1.0; for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double a = array[iRow]; if (a) { a -= value * element[j]; if (!a) a = 1.0e-100; } else { which[n++] = iRow; a = -value * element[j]; assert (a); } array[iRow] = a; } } for (j = 0; j < n; j++) { int iRow = which[j]; // moving to point will increase row solution by this double distance = array[iRow]; if (distance > 1.0e-8) { if (distance + rowSolution[iRow] > rowUpper[iRow] + 1.0e-8) { possible = false; break; } } else if (distance < -1.0e-8) { if (distance + rowSolution[iRow] < rowLower[iRow] - 1.0e-8) { possible = false; break; } } } for (j = 0; j < n; j++) array[which[j]] = 0.0; delete [] array; delete [] which; if (possible) { printf("possible feas region %d %d %d\n", firstNonZero, lastNonZero, iWhere); firstNonZero = iWhere; lastNonZero = iWhere; } } } #else assert (lastNonZero - firstNonZero < sosType_) ; #endif base = 0; for (j = 0; j < firstNonZero; j++) { for (int k = 0; k < numberLinks_; k++) { int iColumn = members_[base+k]; solver->setColUpper(iColumn, 0.0); } base += numberLinks_; } // skip base += numberLinks_; for (j = lastNonZero + 1; j < numberMembers_; j++) { for (int k = 0; k < numberLinks_; k++) { int iColumn = members_[base+k]; solver->setColUpper(iColumn, 0.0); } base += numberLinks_; } // go to coding as in OsiSOS abort(); return -1.0; } // Redoes data when sequence numbers change void OsiOldLink::resetSequenceEtc(int numberColumns, const int * originalColumns) { int n2 = 0; for (int j = 0; j < numberMembers_*numberLinks_; j++) { int iColumn = members_[j]; int i; #ifdef JJF_ZERO for (i = 0; i < numberColumns; i++) { if (originalColumns[i] == iColumn) break; } #else i = originalColumns[iColumn]; #endif if (i >= 0 && i < numberColumns) { members_[n2] = i; weights_[n2++] = weights_[j]; } } if (n2 < numberMembers_) { printf("** SOS number of members reduced from %d to %d!\n", numberMembers_, n2 / numberLinks_); numberMembers_ = n2 / numberLinks_; } } // Creates a branching object OsiBranchingObject * OsiOldLink::createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const { int j; const double * solution = info->solution_; double tolerance = info->primalTolerance_; const double * upper = info->upper_; int firstNonFixed = -1; int lastNonFixed = -1; int firstNonZero = -1; int lastNonZero = -1; double weight = 0.0; double sum = 0.0; int base = 0; for (j = 0; j < numberMembers_; j++) { for (int k = 0; k < numberLinks_; k++) { int iColumn = members_[base+k]; if (upper[iColumn]) { double value = CoinMax(0.0, solution[iColumn]); sum += value; if (firstNonFixed < 0) firstNonFixed = j; lastNonFixed = j; if (value > tolerance) { weight += weights_[j] * value; if (firstNonZero < 0) firstNonZero = j; lastNonZero = j; } } } base += numberLinks_; } assert (lastNonZero - firstNonZero >= sosType_) ; // find where to branch assert (sum > 0.0); weight /= sum; int iWhere; double separator = 0.0; for (iWhere = firstNonZero; iWhere < lastNonZero; iWhere++) if (weight < weights_[iWhere+1]) break; if (sosType_ == 1) { // SOS 1 separator = 0.5 * (weights_[iWhere] + weights_[iWhere+1]); } else { // SOS 2 if (iWhere == firstNonFixed) iWhere++;; if (iWhere == lastNonFixed - 1) iWhere = lastNonFixed - 2; separator = weights_[iWhere+1]; } // create object OsiBranchingObject * branch; branch = new OsiOldLinkBranchingObject(solver, this, way, separator); return branch; } OsiOldLinkBranchingObject::OsiOldLinkBranchingObject() : OsiSOSBranchingObject() { } // Useful constructor OsiOldLinkBranchingObject::OsiOldLinkBranchingObject (OsiSolverInterface * solver, const OsiOldLink * set, int way , double separator) : OsiSOSBranchingObject(solver, set, way, separator) { } // Copy constructor OsiOldLinkBranchingObject::OsiOldLinkBranchingObject ( const OsiOldLinkBranchingObject & rhs) : OsiSOSBranchingObject(rhs) { } // Assignment operator OsiOldLinkBranchingObject & OsiOldLinkBranchingObject::operator=( const OsiOldLinkBranchingObject & rhs) { if (this != &rhs) { OsiSOSBranchingObject::operator=(rhs); } return *this; } OsiBranchingObject * OsiOldLinkBranchingObject::clone() const { return (new OsiOldLinkBranchingObject(*this)); } // Destructor OsiOldLinkBranchingObject::~OsiOldLinkBranchingObject () { } double OsiOldLinkBranchingObject::branch(OsiSolverInterface * solver) { const OsiOldLink * set = dynamic_cast (originalObject_) ; assert (set); int way = (!branchIndex_) ? (2 * firstBranch_ - 1) : -(2 * firstBranch_ - 1); branchIndex_++; int numberMembers = set->numberMembers(); const int * which = set->members(); const double * weights = set->weights(); int numberLinks = set->numberLinks(); //const double * lower = info->lower_; //const double * upper = solver->getColUpper(); // *** for way - up means fix all those in down section if (way < 0) { int i; for ( i = 0; i < numberMembers; i++) { if (weights[i] > value_) break; } assert (i < numberMembers); int base = i * numberLinks;; for (; i < numberMembers; i++) { for (int k = 0; k < numberLinks; k++) { int iColumn = which[base+k]; solver->setColUpper(iColumn, 0.0); } base += numberLinks; } } else { int i; int base = 0; for ( i = 0; i < numberMembers; i++) { if (weights[i] >= value_) { break; } else { for (int k = 0; k < numberLinks; k++) { int iColumn = which[base+k]; solver->setColUpper(iColumn, 0.0); } base += numberLinks; } } assert (i < numberMembers); } return 0.0; } // Print what would happen void OsiOldLinkBranchingObject::print(const OsiSolverInterface * solver) { const OsiOldLink * set = dynamic_cast (originalObject_) ; assert (set); int way = (!branchIndex_) ? (2 * firstBranch_ - 1) : -(2 * firstBranch_ - 1); int numberMembers = set->numberMembers(); int numberLinks = set->numberLinks(); const double * weights = set->weights(); const int * which = set->members(); const double * upper = solver->getColUpper(); int first = numberMembers; int last = -1; int numberFixed = 0; int numberOther = 0; int i; int base = 0; for ( i = 0; i < numberMembers; i++) { for (int k = 0; k < numberLinks; k++) { int iColumn = which[base+k]; double bound = upper[iColumn]; if (bound) { first = CoinMin(first, i); last = CoinMax(last, i); } } base += numberLinks; } // *** for way - up means fix all those in down section base = 0; if (way < 0) { printf("SOS Down"); for ( i = 0; i < numberMembers; i++) { if (weights[i] > value_) break; for (int k = 0; k < numberLinks; k++) { int iColumn = which[base+k]; double bound = upper[iColumn]; if (bound) numberOther++; } base += numberLinks; } assert (i < numberMembers); for (; i < numberMembers; i++) { for (int k = 0; k < numberLinks; k++) { int iColumn = which[base+k]; double bound = upper[iColumn]; if (bound) numberFixed++; } base += numberLinks; } } else { printf("SOS Up"); for ( i = 0; i < numberMembers; i++) { if (weights[i] >= value_) break; for (int k = 0; k < numberLinks; k++) { int iColumn = which[base+k]; double bound = upper[iColumn]; if (bound) numberFixed++; } base += numberLinks; } assert (i < numberMembers); for (; i < numberMembers; i++) { for (int k = 0; k < numberLinks; k++) { int iColumn = which[base+k]; double bound = upper[iColumn]; if (bound) numberOther++; } base += numberLinks; } } assert ((numberFixed % numberLinks) == 0); assert ((numberOther % numberLinks) == 0); printf(" - at %g, free range %d (%g) => %d (%g), %d would be fixed, %d other way\n", value_, first, weights[first], last, weights[last], numberFixed / numberLinks, numberOther / numberLinks); } // Default Constructor OsiBiLinear::OsiBiLinear () : OsiObject2(), coefficient_(0.0), xMeshSize_(0.0), yMeshSize_(0.0), xSatisfied_(1.0e-6), ySatisfied_(1.0e-6), xOtherSatisfied_(0.0), yOtherSatisfied_(0.0), xySatisfied_(1.0e-6), xyBranchValue_(0.0), xColumn_(-1), yColumn_(-1), firstLambda_(-1), branchingStrategy_(0), boundType_(0), xRow_(-1), yRow_(-1), xyRow_(-1), convexity_(-1), numberExtraRows_(0), multiplier_(NULL), extraRow_(NULL), chosen_(-1) { } // Useful constructor OsiBiLinear::OsiBiLinear (OsiSolverInterface * solver, int xColumn, int yColumn, int xyRow, double coefficient, double xMesh, double yMesh, int numberExistingObjects, const OsiObject ** objects ) : OsiObject2(), coefficient_(coefficient), xMeshSize_(xMesh), yMeshSize_(yMesh), xSatisfied_(1.0e-6), ySatisfied_(1.0e-6), xOtherSatisfied_(0.0), yOtherSatisfied_(0.0), xySatisfied_(1.0e-6), xyBranchValue_(0.0), xColumn_(xColumn), yColumn_(yColumn), firstLambda_(-1), branchingStrategy_(0), boundType_(0), xRow_(-1), yRow_(-1), xyRow_(xyRow), convexity_(-1), numberExtraRows_(0), multiplier_(NULL), extraRow_(NULL), chosen_(-1) { double columnLower[4]; double columnUpper[4]; double objective[4]; double rowLower[3]; double rowUpper[3]; CoinBigIndex starts[5]; int index[16]; double element[16]; int i; starts[0] = 0; // rows int numberRows = solver->getNumRows(); // convexity rowLower[0] = 1.0; rowUpper[0] = 1.0; convexity_ = numberRows; starts[1] = 0; // x rowLower[1] = 0.0; rowUpper[1] = 0.0; index[0] = xColumn_; element[0] = -1.0; xRow_ = numberRows + 1; starts[2] = 1; int nAdd = 2; if (xColumn_ != yColumn_) { rowLower[2] = 0.0; rowUpper[2] = 0.0; index[1] = yColumn; element[1] = -1.0; nAdd = 3; yRow_ = numberRows + 2; starts[3] = 2; } else { yRow_ = -1; branchingStrategy_ = 1; } // may be objective assert (xyRow_ >= -1); solver->addRows(nAdd, starts, index, element, rowLower, rowUpper); int n = 0; // order is LxLy, LxUy, UxLy and UxUy firstLambda_ = solver->getNumCols(); // bit sloppy as theoretically could be infeasible but otherwise need to do more work double xB[2]; double yB[2]; const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); xB[0] = lower[xColumn_]; xB[1] = upper[xColumn_]; yB[0] = lower[yColumn_]; yB[1] = upper[yColumn_]; if (xMeshSize_ != floor(xMeshSize_)) { // not integral xSatisfied_ = CoinMax(xSatisfied_, 0.51 * xMeshSize_); if (!yMeshSize_) { xySatisfied_ = CoinMax(xySatisfied_, xSatisfied_ * CoinMax(fabs(yB[0]), fabs(yB[1]))); } } if (yMeshSize_ != floor(yMeshSize_)) { // not integral ySatisfied_ = CoinMax(ySatisfied_, 0.51 * yMeshSize_); if (!xMeshSize_) { xySatisfied_ = CoinMax(xySatisfied_, ySatisfied_ * CoinMax(fabs(xB[0]), fabs(xB[1]))); } } // adjust double distance; double steps; if (xMeshSize_) { distance = xB[1] - xB[0]; steps = floor ((distance + 0.5 * xMeshSize_) / xMeshSize_); distance = xB[0] + xMeshSize_ * steps; if (fabs(xB[1] - distance) > xSatisfied_) { printf("bad x mesh %g %g %g -> %g\n", xB[0], xMeshSize_, xB[1], distance); //double newValue = CoinMax(fabs(xB[1]-distance),xMeshSize_); //printf("xSatisfied increased to %g\n",newValue); //xSatisfied_ = newValue; //xB[1]=distance; //solver->setColUpper(xColumn_,distance); } } if (yMeshSize_) { distance = yB[1] - yB[0]; steps = floor ((distance + 0.5 * yMeshSize_) / yMeshSize_); distance = yB[0] + yMeshSize_ * steps; if (fabs(yB[1] - distance) > ySatisfied_) { printf("bad y mesh %g %g %g -> %g\n", yB[0], yMeshSize_, yB[1], distance); //double newValue = CoinMax(fabs(yB[1]-distance),yMeshSize_); //printf("ySatisfied increased to %g\n",newValue); //ySatisfied_ = newValue; //yB[1]=distance; //solver->setColUpper(yColumn_,distance); } } for (i = 0; i < 4; i++) { double x = (i < 2) ? xB[0] : xB[1]; double y = ((i & 1) == 0) ? yB[0] : yB[1]; columnLower[i] = 0.0; columnUpper[i] = 2.0; objective[i] = 0.0; double value; // xy value = coefficient_ * x * y; if (xyRow_ >= 0) { if (fabs(value) < 1.0e-19) value = 1.0e-19; element[n] = value; index[n++] = xyRow_; } else { objective[i] = value; } // convexity value = 1.0; element[n] = value; index[n++] = 0 + numberRows; // x value = x; if (fabs(value) < 1.0e-19) value = 1.0e-19; element[n] = value; index[n++] = 1 + numberRows; if (xColumn_ != yColumn_) { // y value = y; if (fabs(value) < 1.0e-19) value = 1.0e-19; element[n] = value; index[n++] = 2 + numberRows; } starts[i+1] = n; } solver->addCols(4, starts, index, element, columnLower, columnUpper, objective); // At least one has to have a mesh if (!xMeshSize_ && (!yMeshSize_ || yRow_ < 0)) { printf("one of x and y must have a mesh size\n"); abort(); } else if (yRow_ >= 0) { if (!xMeshSize_) branchingStrategy_ = 2; else if (!yMeshSize_) branchingStrategy_ = 1; } // Now add constraints to link in x and or y to existing ones. bool xDone = false; bool yDone = false; // order is LxLy, LxUy, UxLy and UxUy for (i = numberExistingObjects - 1; i >= 0; i--) { const OsiObject * obj = objects[i]; const OsiBiLinear * obj2 = dynamic_cast (obj) ; if (obj2) { if (xColumn_ == obj2->xColumn_ && !xDone) { // make sure y equal double rhs = 0.0; CoinBigIndex starts[2]; int index[4]; double element[4] = {1.0, 1.0, -1.0, -1.0}; starts[0] = 0; starts[1] = 4; index[0] = firstLambda_ + 0; index[1] = firstLambda_ + 1; index[2] = obj2->firstLambda_ + 0; index[3] = obj2->firstLambda_ + 1; solver->addRows(1, starts, index, element, &rhs, &rhs); xDone = true; } if (yColumn_ == obj2->yColumn_ && yRow_ >= 0 && !yDone) { // make sure x equal double rhs = 0.0; CoinBigIndex starts[2]; int index[4]; double element[4] = {1.0, 1.0, -1.0, -1.0}; starts[0] = 0; starts[1] = 4; index[0] = firstLambda_ + 0; index[1] = firstLambda_ + 2; index[2] = obj2->firstLambda_ + 0; index[3] = obj2->firstLambda_ + 2; solver->addRows(1, starts, index, element, &rhs, &rhs); yDone = true; } } } } // Set sizes and other stuff void OsiBiLinear::setMeshSizes(const OsiSolverInterface * solver, double x, double y) { xMeshSize_ = x; yMeshSize_ = y; double xB[2]; double yB[2]; const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); xB[0] = lower[xColumn_]; xB[1] = upper[xColumn_]; yB[0] = lower[yColumn_]; yB[1] = upper[yColumn_]; if (xMeshSize_ != floor(xMeshSize_)) { // not integral xSatisfied_ = CoinMax(xSatisfied_, 0.51 * xMeshSize_); if (!yMeshSize_) { xySatisfied_ = CoinMax(xySatisfied_, xSatisfied_ * CoinMax(fabs(yB[0]), fabs(yB[1]))); } } if (yMeshSize_ != floor(yMeshSize_)) { // not integral ySatisfied_ = CoinMax(ySatisfied_, 0.51 * yMeshSize_); if (!xMeshSize_) { xySatisfied_ = CoinMax(xySatisfied_, ySatisfied_ * CoinMax(fabs(xB[0]), fabs(xB[1]))); } } } // Useful constructor OsiBiLinear::OsiBiLinear (CoinModel * coinModel, int xColumn, int yColumn, int xyRow, double coefficient, double xMesh, double yMesh, int numberExistingObjects, const OsiObject ** objects ) : OsiObject2(), coefficient_(coefficient), xMeshSize_(xMesh), yMeshSize_(yMesh), xSatisfied_(1.0e-6), ySatisfied_(1.0e-6), xOtherSatisfied_(0.0), yOtherSatisfied_(0.0), xySatisfied_(1.0e-6), xyBranchValue_(0.0), xColumn_(xColumn), yColumn_(yColumn), firstLambda_(-1), branchingStrategy_(0), boundType_(0), xRow_(-1), yRow_(-1), xyRow_(xyRow), convexity_(-1), numberExtraRows_(0), multiplier_(NULL), extraRow_(NULL), chosen_(-1) { double columnLower[4]; double columnUpper[4]; double objective[4]; double rowLower[3]; double rowUpper[3]; CoinBigIndex starts[5]; int index[16]; double element[16]; int i; starts[0] = 0; // rows int numberRows = coinModel->numberRows(); // convexity rowLower[0] = 1.0; rowUpper[0] = 1.0; convexity_ = numberRows; starts[1] = 0; // x rowLower[1] = 0.0; rowUpper[1] = 0.0; index[0] = xColumn_; element[0] = -1.0; xRow_ = numberRows + 1; starts[2] = 1; int nAdd = 2; if (xColumn_ != yColumn_) { rowLower[2] = 0.0; rowUpper[2] = 0.0; index[1] = yColumn; element[1] = -1.0; nAdd = 3; yRow_ = numberRows + 2; starts[3] = 2; } else { yRow_ = -1; branchingStrategy_ = 1; } // may be objective assert (xyRow_ >= -1); for (i = 0; i < nAdd; i++) { CoinBigIndex iStart = starts[i]; coinModel->addRow(starts[i+1] - iStart, index + iStart, element + iStart, rowLower[i], rowUpper[i]); } int n = 0; // order is LxLy, LxUy, UxLy and UxUy firstLambda_ = coinModel->numberColumns(); // bit sloppy as theoretically could be infeasible but otherwise need to do more work double xB[2]; double yB[2]; const double * lower = coinModel->columnLowerArray(); const double * upper = coinModel->columnUpperArray(); xB[0] = lower[xColumn_]; xB[1] = upper[xColumn_]; yB[0] = lower[yColumn_]; yB[1] = upper[yColumn_]; if (xMeshSize_ != floor(xMeshSize_)) { // not integral xSatisfied_ = CoinMax(xSatisfied_, 0.51 * xMeshSize_); if (!yMeshSize_) { xySatisfied_ = CoinMax(xySatisfied_, xSatisfied_ * CoinMax(fabs(yB[0]), fabs(yB[1]))); } } if (yMeshSize_ != floor(yMeshSize_)) { // not integral ySatisfied_ = CoinMax(ySatisfied_, 0.51 * yMeshSize_); if (!xMeshSize_) { xySatisfied_ = CoinMax(xySatisfied_, ySatisfied_ * CoinMax(fabs(xB[0]), fabs(xB[1]))); } } // adjust double distance; double steps; if (xMeshSize_) { distance = xB[1] - xB[0]; steps = floor ((distance + 0.5 * xMeshSize_) / xMeshSize_); distance = xB[0] + xMeshSize_ * steps; if (fabs(xB[1] - distance) > xSatisfied_) { printf("bad x mesh %g %g %g -> %g\n", xB[0], xMeshSize_, xB[1], distance); //double newValue = CoinMax(fabs(xB[1]-distance),xMeshSize_); //printf("xSatisfied increased to %g\n",newValue); //xSatisfied_ = newValue; //xB[1]=distance; //coinModel->setColUpper(xColumn_,distance); } } if (yMeshSize_) { distance = yB[1] - yB[0]; steps = floor ((distance + 0.5 * yMeshSize_) / yMeshSize_); distance = yB[0] + yMeshSize_ * steps; if (fabs(yB[1] - distance) > ySatisfied_) { printf("bad y mesh %g %g %g -> %g\n", yB[0], yMeshSize_, yB[1], distance); //double newValue = CoinMax(fabs(yB[1]-distance),yMeshSize_); //printf("ySatisfied increased to %g\n",newValue); //ySatisfied_ = newValue; //yB[1]=distance; //coinModel->setColUpper(yColumn_,distance); } } for (i = 0; i < 4; i++) { double x = (i < 2) ? xB[0] : xB[1]; double y = ((i & 1) == 0) ? yB[0] : yB[1]; columnLower[i] = 0.0; columnUpper[i] = 2.0; objective[i] = 0.0; double value; // xy value = coefficient_ * x * y; if (xyRow_ >= 0) { if (fabs(value) < 1.0e-19) value = 1.0e-19; element[n] = value; index[n++] = xyRow_; } else { objective[i] = value; } // convexity value = 1.0; element[n] = value; index[n++] = 0 + numberRows; // x value = x; if (fabs(value) < 1.0e-19) value = 1.0e-19; element[n] = value; index[n++] = 1 + numberRows; if (xColumn_ != yColumn_) { // y value = y; if (fabs(value) < 1.0e-19) value = 1.0e-19; element[n] = value; index[n++] = 2 + numberRows; } starts[i+1] = n; } for (i = 0; i < 4; i++) { CoinBigIndex iStart = starts[i]; coinModel->addColumn(starts[i+1] - iStart, index + iStart, element + iStart, columnLower[i], columnUpper[i], objective[i]); } // At least one has to have a mesh if (!xMeshSize_ && (!yMeshSize_ || yRow_ < 0)) { printf("one of x and y must have a mesh size\n"); abort(); } else if (yRow_ >= 0) { if (!xMeshSize_) branchingStrategy_ = 2; else if (!yMeshSize_) branchingStrategy_ = 1; } // Now add constraints to link in x and or y to existing ones. bool xDone = false; bool yDone = false; // order is LxLy, LxUy, UxLy and UxUy for (i = numberExistingObjects - 1; i >= 0; i--) { const OsiObject * obj = objects[i]; const OsiBiLinear * obj2 = dynamic_cast (obj) ; if (obj2) { if (xColumn_ == obj2->xColumn_ && !xDone) { // make sure y equal double rhs = 0.0; int index[4]; double element[4] = {1.0, 1.0, -1.0, -1.0}; index[0] = firstLambda_ + 0; index[1] = firstLambda_ + 1; index[2] = obj2->firstLambda_ + 0; index[3] = obj2->firstLambda_ + 1; coinModel->addRow(4, index, element, rhs, rhs); xDone = true; } if (yColumn_ == obj2->yColumn_ && yRow_ >= 0 && !yDone) { // make sure x equal double rhs = 0.0; int index[4]; double element[4] = {1.0, 1.0, -1.0, -1.0}; index[0] = firstLambda_ + 0; index[1] = firstLambda_ + 2; index[2] = obj2->firstLambda_ + 0; index[3] = obj2->firstLambda_ + 2; coinModel->addRow(4, index, element, rhs, rhs); yDone = true; } } } } // Copy constructor OsiBiLinear::OsiBiLinear ( const OsiBiLinear & rhs) : OsiObject2(rhs), coefficient_(rhs.coefficient_), xMeshSize_(rhs.xMeshSize_), yMeshSize_(rhs.yMeshSize_), xSatisfied_(rhs.xSatisfied_), ySatisfied_(rhs.ySatisfied_), xOtherSatisfied_(rhs.xOtherSatisfied_), yOtherSatisfied_(rhs.yOtherSatisfied_), xySatisfied_(rhs.xySatisfied_), xyBranchValue_(rhs.xyBranchValue_), xColumn_(rhs.xColumn_), yColumn_(rhs.yColumn_), firstLambda_(rhs.firstLambda_), branchingStrategy_(rhs.branchingStrategy_), boundType_(rhs.boundType_), xRow_(rhs.xRow_), yRow_(rhs.yRow_), xyRow_(rhs.xyRow_), convexity_(rhs.convexity_), numberExtraRows_(rhs.numberExtraRows_), multiplier_(NULL), extraRow_(NULL), chosen_(rhs.chosen_) { if (numberExtraRows_) { multiplier_ = CoinCopyOfArray(rhs.multiplier_, numberExtraRows_); extraRow_ = CoinCopyOfArray(rhs.extraRow_, numberExtraRows_); } } // Clone OsiObject * OsiBiLinear::clone() const { return new OsiBiLinear(*this); } // Assignment operator OsiBiLinear & OsiBiLinear::operator=( const OsiBiLinear & rhs) { if (this != &rhs) { OsiObject2::operator=(rhs); coefficient_ = rhs.coefficient_; xMeshSize_ = rhs.xMeshSize_; yMeshSize_ = rhs.yMeshSize_; xSatisfied_ = rhs.xSatisfied_; ySatisfied_ = rhs.ySatisfied_; xOtherSatisfied_ = rhs.xOtherSatisfied_; yOtherSatisfied_ = rhs.yOtherSatisfied_; xySatisfied_ = rhs.xySatisfied_; xyBranchValue_ = rhs.xyBranchValue_; xColumn_ = rhs.xColumn_; yColumn_ = rhs.yColumn_; firstLambda_ = rhs.firstLambda_; branchingStrategy_ = rhs.branchingStrategy_; boundType_ = rhs.boundType_; xRow_ = rhs.xRow_; yRow_ = rhs.yRow_; xyRow_ = rhs.xyRow_; convexity_ = rhs.convexity_; numberExtraRows_ = rhs.numberExtraRows_; delete [] multiplier_; delete [] extraRow_; if (numberExtraRows_) { multiplier_ = CoinCopyOfArray(rhs.multiplier_, numberExtraRows_); extraRow_ = CoinCopyOfArray(rhs.extraRow_, numberExtraRows_); } else { multiplier_ = NULL; extraRow_ = NULL; } chosen_ = rhs.chosen_; } return *this; } // Destructor OsiBiLinear::~OsiBiLinear () { delete [] multiplier_; delete [] extraRow_; } // Adds in data for extra row with variable coefficients void OsiBiLinear::addExtraRow(int row, double multiplier) { int * tempI = new int [numberExtraRows_+1]; double * tempD = new double [numberExtraRows_+1]; memcpy(tempI, extraRow_, numberExtraRows_*sizeof(int)); memcpy(tempD, multiplier_, numberExtraRows_*sizeof(double)); tempI[numberExtraRows_] = row; tempD[numberExtraRows_] = multiplier; if (numberExtraRows_) assert (row > tempI[numberExtraRows_-1]); numberExtraRows_++; delete [] extraRow_; extraRow_ = tempI; delete [] multiplier_; multiplier_ = tempD; } static bool testCoarse = true; // Infeasibility - large is 0.5 double OsiBiLinear::infeasibility(const OsiBranchingInformation * info, int & whichWay) const { // order is LxLy, LxUy, UxLy and UxUy double xB[2]; double yB[2]; xB[0] = info->lower_[xColumn_]; xB[1] = info->upper_[xColumn_]; yB[0] = info->lower_[yColumn_]; yB[1] = info->upper_[yColumn_]; #ifdef JJF_ZERO if (info->lower_[1] <= 43.0 && info->upper_[1] >= 43.0) { if (info->lower_[4] <= 49.0 && info->upper_[4] >= 49.0) { if (info->lower_[2] <= 16.0 && info->upper_[2] >= 16.0) { if (info->lower_[3] <= 19.0 && info->upper_[3] >= 19.0) { printf("feas %g %g %g %g p %g t %g\n", info->solution_[1], info->solution_[2], info->solution_[3], info->solution_[4], info->solution_[0], info->solution_[5]); } } } } #endif double x = info->solution_[xColumn_]; x = CoinMax(x, xB[0]); x = CoinMin(x, xB[1]); double y = info->solution_[yColumn_]; y = CoinMax(y, yB[0]); y = CoinMin(y, yB[1]); int j; #ifndef NDEBUG double xLambda = 0.0; double yLambda = 0.0; if ((branchingStrategy_&4) == 0) { for (j = 0; j < 4; j++) { int iX = j >> 1; int iY = j & 1; xLambda += xB[iX] * info->solution_[firstLambda_+j]; if (yRow_ >= 0) yLambda += yB[iY] * info->solution_[firstLambda_+j]; } } else { const double * element = info->elementByColumn_; const int * row = info->row_; const CoinBigIndex * columnStart = info->columnStart_; const int * columnLength = info->columnLength_; for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; int iStart = columnStart[iColumn]; int iEnd = iStart + columnLength[iColumn]; int k = iStart; double sol = info->solution_[iColumn]; for (; k < iEnd; k++) { if (xRow_ == row[k]) xLambda += element[k] * sol; if (yRow_ == row[k]) yLambda += element[k] * sol; } } } assert (fabs(x - xLambda) < 1.0e-1); if (yRow_ >= 0) assert (fabs(y - yLambda) < 1.0e-1); #endif // If x or y not satisfied then branch on that double distance; double steps; bool xSatisfied; double xNew = xB[0]; if (xMeshSize_) { if (x < 0.5*(xB[0] + xB[1])) { distance = x - xB[0]; steps = floor ((distance + 0.5 * xMeshSize_) / xMeshSize_); xNew = xB[0] + steps * xMeshSize_; assert (xNew <= xB[1] + xSatisfied_); xSatisfied = (fabs(xNew - x) < xSatisfied_); } else { distance = xB[1] - x; steps = floor ((distance + 0.5 * xMeshSize_) / xMeshSize_); xNew = xB[1] - steps * xMeshSize_; assert (xNew >= xB[0] - xSatisfied_); xSatisfied = (fabs(xNew - x) < xSatisfied_); } // but if first coarse grid then only if gap small if (testCoarse && (branchingStrategy_&8) != 0 && xSatisfied && xB[1] - xB[0] >= xMeshSize_) { // but allow if fine grid would allow if (fabs(xNew - x) >= xOtherSatisfied_ && fabs(yB[0] - y) > yOtherSatisfied_ && fabs(yB[1] - y) > yOtherSatisfied_) { xNew = 0.5 * (xB[0] + xB[1]); x = xNew; xSatisfied = false; } } } else { xSatisfied = true; } bool ySatisfied; double yNew = yB[0]; if (yMeshSize_) { if (y < 0.5*(yB[0] + yB[1])) { distance = y - yB[0]; steps = floor ((distance + 0.5 * yMeshSize_) / yMeshSize_); yNew = yB[0] + steps * yMeshSize_; assert (yNew <= yB[1] + ySatisfied_); ySatisfied = (fabs(yNew - y) < ySatisfied_); } else { distance = yB[1] - y; steps = floor ((distance + 0.5 * yMeshSize_) / yMeshSize_); yNew = yB[1] - steps * yMeshSize_; assert (yNew >= yB[0] - ySatisfied_); ySatisfied = (fabs(yNew - y) < ySatisfied_); } // but if first coarse grid then only if gap small if (testCoarse && (branchingStrategy_&8) != 0 && ySatisfied && yB[1] - yB[0] >= yMeshSize_) { // but allow if fine grid would allow if (fabs(yNew - y) >= yOtherSatisfied_ && fabs(xB[0] - x) > xOtherSatisfied_ && fabs(xB[1] - x) > xOtherSatisfied_) { yNew = 0.5 * (yB[0] + yB[1]); y = yNew; ySatisfied = false; } } } else { ySatisfied = true; } /* There are several possibilities 1 - one or both are unsatisfied and branching strategy tells us what to do 2 - both are unsatisfied and branching strategy is 0 3 - both are satisfied but xy is not 3a one has bounds within satisfied_ - other does not (or neither have but branching strategy tells us what to do) 3b neither do - and branching strategy does not tell us 3c both do - treat as feasible knowing another copy of object will fix 4 - both are satisfied and xy is satisfied - as 3c */ chosen_ = -1; xyBranchValue_ = COIN_DBL_MAX; whichWay_ = 0; double xyTrue = x * y; double xyLambda = 0.0; if ((branchingStrategy_&4) == 0) { for (j = 0; j < 4; j++) { int iX = j >> 1; int iY = j & 1; xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda_+j]; } } else { if (xyRow_ >= 0) { const double * element = info->elementByColumn_; const int * row = info->row_; const CoinBigIndex * columnStart = info->columnStart_; const int * columnLength = info->columnLength_; for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; int iStart = columnStart[iColumn]; int iEnd = iStart + columnLength[iColumn]; int k = iStart; double sol = info->solution_[iColumn]; for (; k < iEnd; k++) { if (xyRow_ == row[k]) xyLambda += element[k] * sol; } } } else { // objective const double * objective = info->objective_; for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; double sol = info->solution_[iColumn]; xyLambda += objective[iColumn] * sol; } } xyLambda /= coefficient_; } if (0) { // only true with positive values // see if all convexification constraints OK with true assert (xyTrue + 1.0e-5 > xB[0]*y + yB[0]*x - xB[0]*yB[0]); assert (xyTrue + 1.0e-5 > xB[1]*y + yB[1]*x - xB[1]*yB[1]); assert (xyTrue - 1.0e-5 < xB[1]*y + yB[0]*x - xB[1]*yB[0]); assert (xyTrue - 1.0e-5 < xB[0]*y + yB[1]*x - xB[0]*yB[1]); // see if all convexification constraints OK with lambda version #ifndef JJF_ONE assert (xyLambda + 1.0e-5 > xB[0]*y + yB[0]*x - xB[0]*yB[0]); assert (xyLambda + 1.0e-5 > xB[1]*y + yB[1]*x - xB[1]*yB[1]); assert (xyLambda - 1.0e-5 < xB[1]*y + yB[0]*x - xB[1]*yB[0]); assert (xyLambda - 1.0e-5 < xB[0]*y + yB[1]*x - xB[0]*yB[1]); #endif // see if other bound stuff true assert (xyLambda + 1.0e-5 > xB[0]*y); assert (xyLambda + 1.0e-5 > yB[0]*x); assert (xyLambda - 1.0e-5 < xB[1]*y); assert (xyLambda - 1.0e-5 < yB[1]*x); #define SIZE 2 if (yColumn_ == xColumn_ + SIZE) { #if SIZE==6 double bMax = 2200.0; double bMin = bMax - 100.0; double b[] = {330.0, 360.0, 380.0, 430.0, 490.0, 530.0}; #elif SIZE==2 double bMax = 1900.0; double bMin = bMax - 200.0; double b[] = {460.0, 570.0}; #else abort(); #endif double sum = 0.0; double sum2 = 0.0; int m = xColumn_; double x = info->solution_[m]; double xB[2]; double yB[2]; xB[0] = info->lower_[m]; xB[1] = info->upper_[m]; for (int i = 0; i < SIZE*SIZE; i += SIZE) { int n = i + SIZE + m; double y = info->solution_[n]; yB[0] = info->lower_[n]; yB[1] = info->upper_[n]; int firstLambda = SIZE * SIZE + 2 * SIZE + 4 * i + 4 * m; double xyLambda = 0.0; for (int j = 0; j < 4; j++) { int iX = j >> 1; int iY = j & 1; xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda+j]; } sum += xyLambda * b[i/SIZE]; double xyTrue = x * y; sum2 += xyTrue * b[i/SIZE]; } if (sum > bMax*x + 1.0e-5 || sum < bMin*x - 1.0e-5) { //if (sumbMin*x-1.0e-5) { printf("bmin*x %g b*w %g bmax*x %g (true) %g\n", bMin*x, sum, bMax*x, sum2); printf("m %d lb %g value %g up %g\n", m, xB[0], x, xB[1]); sum = 0.0; for (int i = 0; i < SIZE*SIZE; i += SIZE) { int n = i + SIZE + m; double y = info->solution_[n]; yB[0] = info->lower_[n]; yB[1] = info->upper_[n]; printf("n %d lb %g value %g up %g\n", n, yB[0], y, yB[1]); int firstLambda = SIZE * SIZE + 2 * SIZE + 4 * i + m * 4; double xyLambda = 0.0; for (int j = 0; j < 4; j++) { int iX = j >> 1; int iY = j & 1; xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda+j]; printf("j %d l %d new xylambda %g ", j, firstLambda + j, xyLambda); } sum += xyLambda * b[i/SIZE]; printf(" - sum now %g\n", sum); } } if (sum2 > bMax*x + 1.0e-5 || sum2 < bMin*x - 1.0e-5) { printf("bmin*x %g b*x*y %g bmax*x %g (estimate) %g\n", bMin*x, sum2, bMax*x, sum); printf("m %d lb %g value %g up %g\n", m, xB[0], x, xB[1]); sum2 = 0.0; for (int i = 0; i < SIZE*SIZE; i += SIZE) { int n = i + SIZE + m; double y = info->solution_[n]; yB[0] = info->lower_[n]; yB[1] = info->upper_[n]; printf("n %d lb %g value %g up %g\n", n, yB[0], y, yB[1]); double xyTrue = x * y; sum2 += xyTrue * b[i/SIZE]; printf("xyTrue %g - sum now %g\n", xyTrue, sum2); } } } } // If pseudo shadow prices then see what would happen //double pseudoEstimate = 0.0; if (info->defaultDual_ >= 0.0) { // If we move to xy then we move by coefficient * (xyTrue-xyLambda) on row xyRow_ double move = xyTrue - xyLambda; assert (xyRow_ >= 0); if (boundType_ == 0) { move *= coefficient_; move *= info->pi_[xyRow_]; move = CoinMax(move, 0.0); } else if (boundType_ == 1) { // if OK then say satisfied } else if (boundType_ == 2) { } else { // == row so move x and y not xy } } if ((branchingStrategy_&16) != 0) { // always treat as satisfied!! xSatisfied = true; ySatisfied = true; xyTrue = xyLambda; } if ( !xSatisfied) { if (!ySatisfied) { if ((branchingStrategy_&3) == 0) { // If pseudo shadow prices then see what would happen if (info->defaultDual_ >= 0.0) { // need coding here if (fabs(x - xNew) > fabs(y - yNew)) { chosen_ = 0; xyBranchValue_ = x; } else { chosen_ = 1; xyBranchValue_ = y; } } else { if (fabs(x - xNew) > fabs(y - yNew)) { chosen_ = 0; xyBranchValue_ = x; } else { chosen_ = 1; xyBranchValue_ = y; } } } else if ((branchingStrategy_&3) == 1) { chosen_ = 0; xyBranchValue_ = x; } else { chosen_ = 1; xyBranchValue_ = y; } } else { // y satisfied chosen_ = 0; xyBranchValue_ = x; } } else { // x satisfied if (!ySatisfied) { chosen_ = 1; xyBranchValue_ = y; } else { /* 3 - both are satisfied but xy is not 3a one has bounds within satisfied_ - other does not (or neither have but branching strategy tells us what to do) 3b neither do - and branching strategy does not tell us 3c both do - treat as feasible knowing another copy of object will fix 4 - both are satisfied and xy is satisfied - as 3c */ if (fabs(xyLambda - xyTrue) < xySatisfied_ || (xB[0] == xB[1] && yB[0] == yB[1])) { // satisfied #ifdef JJF_ZERO printf("all satisfied true %g lambda %g\n", xyTrue, xyLambda); printf("x %d (%g,%g,%g) y %d (%g,%g,%g)\n", xColumn_, xB[0], x, xB[1], yColumn_, yB[0], y, yB[1]); #endif } else { // May be infeasible - check bool feasible = true; if (xB[0] == xB[1] && yB[0] == yB[1]) { double lambda[4]; computeLambdas(info->solver_, lambda); for (int j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; if (info->lower_[iColumn] > lambda[j] + 1.0e-5 || info->upper_[iColumn] < lambda[j] - 1.0e-5) feasible = false; } } if (testCoarse && (branchingStrategy_&8) != 0 && xB[1] - xB[0] < 1.0001*xSatisfied_ && yB[1] - yB[0] < 1.0001*ySatisfied_) feasible = true; if (feasible) { if (xB[1] - xB[0] >= xSatisfied_ && xMeshSize_) { if (yB[1] - yB[0] >= ySatisfied_ && yMeshSize_) { if ((branchingStrategy_&3) == 0) { // If pseudo shadow prices then see what would happen if (info->defaultDual_ >= 0.0) { // need coding here if (xB[1] - xB[0] > yB[1] - yB[0]) { chosen_ = 0; xyBranchValue_ = 0.5 * (xB[0] + xB[1]); } else { chosen_ = 1; xyBranchValue_ = 0.5 * (yB[0] + yB[1]); } } else { if (xB[1] - xB[0] > yB[1] - yB[0]) { chosen_ = 0; xyBranchValue_ = 0.5 * (xB[0] + xB[1]); } else { chosen_ = 1; xyBranchValue_ = 0.5 * (yB[0] + yB[1]); } } } else if ((branchingStrategy_&3) == 1) { chosen_ = 0; xyBranchValue_ = 0.5 * (xB[0] + xB[1]); } else { chosen_ = 1; xyBranchValue_ = 0.5 * (yB[0] + yB[1]); } } else { // y satisfied chosen_ = 0; xyBranchValue_ = 0.5 * (xB[0] + xB[1]); } } else if (yB[1] - yB[0] >= ySatisfied_ && yMeshSize_) { chosen_ = 1; xyBranchValue_ = 0.5 * (yB[0] + yB[1]); } else { // treat as satisfied unless no coefficient tightening if ((branchingStrategy_&4) != 0) { chosen_ = 0; // fix up in branch xyBranchValue_ = x; } } } else { // node not feasible!!! chosen_ = 0; infeasibility_ = COIN_DBL_MAX; otherInfeasibility_ = COIN_DBL_MAX; whichWay = whichWay_; return infeasibility_; } } } } if (chosen_ == -1) { infeasibility_ = 0.0; } else if (chosen_ == 0) { infeasibility_ = CoinMax(fabs(xyBranchValue_ - x), 1.0e-12); //assert (xyBranchValue_>=info->lower_[xColumn_]&&xyBranchValue_<=info->upper_[xColumn_]); } else { infeasibility_ = CoinMax(fabs(xyBranchValue_ - y), 1.0e-12); //assert (xyBranchValue_>=info->lower_[yColumn_]&&xyBranchValue_<=info->upper_[yColumn_]); } if (info->defaultDual_ < 0.0) { // not using pseudo shadow prices otherInfeasibility_ = 1.0 - infeasibility_; } else { abort(); } if (infeasibility_) { bool fixed = true; for (int j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; //if (info->lower_[iColumn]) printf("lower of %g on %d\n",info->lower_[iColumn],iColumn); if (info->lower_[iColumn] < info->upper_[iColumn]) fixed = false; } if (fixed) { //printf("must be tolerance problem - xy true %g lambda %g\n",xyTrue,xyLambda); chosen_ = -1; infeasibility_ = 0.0; } } whichWay = whichWay_; //if (infeasibility_&&priority_==10) //printf("x %d %g %g %g, y %d %g %g %g\n",xColumn_,xB[0],x,xB[1],yColumn_,yB[0],y,yB[1]); return infeasibility_; } // Sets infeasibility and other when pseudo shadow prices void OsiBiLinear::getPseudoShadow(const OsiBranchingInformation * info) { // order is LxLy, LxUy, UxLy and UxUy double xB[2]; double yB[2]; xB[0] = info->lower_[xColumn_]; xB[1] = info->upper_[xColumn_]; yB[0] = info->lower_[yColumn_]; yB[1] = info->upper_[yColumn_]; double x = info->solution_[xColumn_]; x = CoinMax(x, xB[0]); x = CoinMin(x, xB[1]); double y = info->solution_[yColumn_]; y = CoinMax(y, yB[0]); y = CoinMin(y, yB[1]); int j; double xyTrue = x * y; double xyLambda = 0.0; if ((branchingStrategy_&4) == 0) { for (j = 0; j < 4; j++) { int iX = j >> 1; int iY = j & 1; xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda_+j]; } } else { if (xyRow_ >= 0) { const double * element = info->elementByColumn_; const int * row = info->row_; const CoinBigIndex * columnStart = info->columnStart_; const int * columnLength = info->columnLength_; for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; int iStart = columnStart[iColumn]; int iEnd = iStart + columnLength[iColumn]; int k = iStart; double sol = info->solution_[iColumn]; for (; k < iEnd; k++) { if (xyRow_ == row[k]) xyLambda += element[k] * sol; } } } else { // objective const double * objective = info->objective_; for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; double sol = info->solution_[iColumn]; xyLambda += objective[iColumn] * sol; } } xyLambda /= coefficient_; } assert (info->defaultDual_ >= 0.0); // If we move to xy then we move by coefficient * (xyTrue-xyLambda) on row xyRow_ double movement = xyTrue - xyLambda; infeasibility_ = 0.0; const double * pi = info->pi_; const double * activity = info->rowActivity_; const double * lower = info->rowLower_; const double * upper = info->rowUpper_; double tolerance = info->primalTolerance_; double direction = info->direction_; bool infeasible = false; if (xyRow_ >= 0) { assert (!boundType_); if (lower[xyRow_] < -1.0e20) assert (pi[xyRow_] <= 1.0e-3); if (upper[xyRow_] > 1.0e20) assert (pi[xyRow_] >= -1.0e-3); double valueP = pi[xyRow_] * direction; // if move makes infeasible then make at least default double newValue = activity[xyRow_] + movement * coefficient_; if (newValue > upper[xyRow_] + tolerance || newValue < lower[xyRow_] - tolerance) { infeasibility_ += fabs(movement * coefficient_) * CoinMax(fabs(valueP), info->defaultDual_); infeasible = true; } } else { // objective assert (movement > -1.0e-7); infeasibility_ += movement; } for (int i = 0; i < numberExtraRows_; i++) { int iRow = extraRow_[i]; if (lower[iRow] < -1.0e20) assert (pi[iRow] <= 1.0e-3); if (upper[iRow] > 1.0e20) assert (pi[iRow] >= -1.0e-3); double valueP = pi[iRow] * direction; // if move makes infeasible then make at least default double newValue = activity[iRow] + movement * multiplier_[i]; if (newValue > upper[iRow] + tolerance || newValue < lower[iRow] - tolerance) { infeasibility_ += fabs(movement * multiplier_[i]) * CoinMax(fabs(valueP), info->defaultDual_); infeasible = true; } } if (infeasibility_ < info->integerTolerance_) { if (!infeasible) infeasibility_ = 0.0; else infeasibility_ = info->integerTolerance_; } otherInfeasibility_ = CoinMax(1.0e-12, infeasibility_ * 10.0); } // Gets sum of movements to correct value double OsiBiLinear::getMovement(const OsiBranchingInformation * info) { // order is LxLy, LxUy, UxLy and UxUy double xB[2]; double yB[2]; xB[0] = info->lower_[xColumn_]; xB[1] = info->upper_[xColumn_]; yB[0] = info->lower_[yColumn_]; yB[1] = info->upper_[yColumn_]; double x = info->solution_[xColumn_]; x = CoinMax(x, xB[0]); x = CoinMin(x, xB[1]); double y = info->solution_[yColumn_]; y = CoinMax(y, yB[0]); y = CoinMin(y, yB[1]); int j; double xyTrue = x * y; double xyLambda = 0.0; if ((branchingStrategy_&4) == 0) { for (j = 0; j < 4; j++) { int iX = j >> 1; int iY = j & 1; xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda_+j]; } } else { if (xyRow_ >= 0) { const double * element = info->elementByColumn_; const int * row = info->row_; const CoinBigIndex * columnStart = info->columnStart_; const int * columnLength = info->columnLength_; for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; int iStart = columnStart[iColumn]; int iEnd = iStart + columnLength[iColumn]; int k = iStart; double sol = info->solution_[iColumn]; for (; k < iEnd; k++) { if (xyRow_ == row[k]) xyLambda += element[k] * sol; } } } else { // objective const double * objective = info->objective_; for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; double sol = info->solution_[iColumn]; xyLambda += objective[iColumn] * sol; } } xyLambda /= coefficient_; } // If we move to xy then we move by coefficient * (xyTrue-xyLambda) on row xyRow_ double movement = xyTrue - xyLambda; double mesh = CoinMax(xMeshSize_, yMeshSize_); if (fabs(movement) < xySatisfied_ && (xB[1] - xB[0] < mesh || yB[1] - yB[0] < mesh)) return 0.0; // say feasible const double * activity = info->rowActivity_; const double * lower = info->rowLower_; const double * upper = info->rowUpper_; double tolerance = info->primalTolerance_; double infeasibility = 0.0; if (xyRow_ >= 0) { assert (!boundType_); // if move makes infeasible double newValue = activity[xyRow_] + movement * coefficient_; if (newValue > upper[xyRow_] + tolerance) infeasibility += newValue - upper[xyRow_]; else if (newValue < lower[xyRow_] - tolerance) infeasibility += lower[xyRow_] - newValue; } else { // objective assert (movement > -1.0e-7); infeasibility += movement; } for (int i = 0; i < numberExtraRows_; i++) { int iRow = extraRow_[i]; // if move makes infeasible double newValue = activity[iRow] + movement * multiplier_[i]; if (newValue > upper[iRow] + tolerance) infeasibility += newValue - upper[iRow]; else if (newValue < lower[iRow] - tolerance) infeasibility += lower[iRow] - newValue; } return infeasibility; } // This looks at solution and sets bounds to contain solution double OsiBiLinear::feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const { // If another object has finer mesh ignore this if ((branchingStrategy_&8) != 0) return 0.0; // order is LxLy, LxUy, UxLy and UxUy double xB[2]; double yB[2]; xB[0] = info->lower_[xColumn_]; xB[1] = info->upper_[xColumn_]; yB[0] = info->lower_[yColumn_]; yB[1] = info->upper_[yColumn_]; double x = info->solution_[xColumn_]; double y = info->solution_[yColumn_]; int j; #ifndef NDEBUG double xLambda = 0.0; double yLambda = 0.0; if ((branchingStrategy_&4) == 0) { for (j = 0; j < 4; j++) { int iX = j >> 1; int iY = j & 1; xLambda += xB[iX] * info->solution_[firstLambda_+j]; if (yRow_ >= 0) yLambda += yB[iY] * info->solution_[firstLambda_+j]; } } else { const double * element = info->elementByColumn_; const int * row = info->row_; const CoinBigIndex * columnStart = info->columnStart_; const int * columnLength = info->columnLength_; for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; int iStart = columnStart[iColumn]; int iEnd = iStart + columnLength[iColumn]; int k = iStart; double sol = info->solution_[iColumn]; for (; k < iEnd; k++) { if (xRow_ == row[k]) xLambda += element[k] * sol; if (yRow_ == row[k]) yLambda += element[k] * sol; } } } if (yRow_ < 0) yLambda = xLambda; #ifdef JJF_ZERO if (fabs(x - xLambda) > 1.0e-4 || fabs(y - yLambda) > 1.0e-4) printf("feasibleregion x %d given %g lambda %g y %d given %g lambda %g\n", xColumn_, x, xLambda, yColumn_, y, yLambda); #endif #endif double infeasibility = 0.0; double distance; double steps; double xNew = x; if (xMeshSize_) { distance = x - xB[0]; if (x < 0.5*(xB[0] + xB[1])) { distance = x - xB[0]; steps = floor ((distance + 0.5 * xMeshSize_) / xMeshSize_); xNew = xB[0] + steps * xMeshSize_; assert (xNew <= xB[1] + xSatisfied_); } else { distance = xB[1] - x; steps = floor ((distance + 0.5 * xMeshSize_) / xMeshSize_); xNew = xB[1] - steps * xMeshSize_; assert (xNew >= xB[0] - xSatisfied_); } if (xMeshSize_ < 1.0 && fabs(xNew - x) <= xSatisfied_) { double lo = CoinMax(xB[0], x - 0.5 * xSatisfied_); double up = CoinMin(xB[1], x + 0.5 * xSatisfied_); solver->setColLower(xColumn_, lo); solver->setColUpper(xColumn_, up); } else { infeasibility += fabs(xNew - x); solver->setColLower(xColumn_, xNew); solver->setColUpper(xColumn_, xNew); } } double yNew = y; if (yMeshSize_) { distance = y - yB[0]; if (y < 0.5*(yB[0] + yB[1])) { distance = y - yB[0]; steps = floor ((distance + 0.5 * yMeshSize_) / yMeshSize_); yNew = yB[0] + steps * yMeshSize_; assert (yNew <= yB[1] + ySatisfied_); } else { distance = yB[1] - y; steps = floor ((distance + 0.5 * yMeshSize_) / yMeshSize_); yNew = yB[1] - steps * yMeshSize_; assert (yNew >= yB[0] - ySatisfied_); } if (yMeshSize_ < 1.0 && fabs(yNew - y) <= ySatisfied_) { double lo = CoinMax(yB[0], y - 0.5 * ySatisfied_); double up = CoinMin(yB[1], y + 0.5 * ySatisfied_); solver->setColLower(yColumn_, lo); solver->setColUpper(yColumn_, up); } else { infeasibility += fabs(yNew - y); solver->setColLower(yColumn_, yNew); solver->setColUpper(yColumn_, yNew); } } if (0) { // temp solver->setColLower(xColumn_, x); solver->setColUpper(xColumn_, x); solver->setColLower(yColumn_, y); solver->setColUpper(yColumn_, y); } if ((branchingStrategy_&4)) { // fake to make correct double lambda[4]; computeLambdas(solver, lambda); for (int j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; double value = lambda[j]; solver->setColLower(iColumn, value); solver->setColUpper(iColumn, value); } } double xyTrue = xNew * yNew; double xyLambda = 0.0; for (j = 0; j < 4; j++) { int iX = j >> 1; int iY = j & 1; xyLambda += xB[iX] * yB[iY] * info->solution_[firstLambda_+j]; } infeasibility += fabs(xyTrue - xyLambda); return infeasibility; } // Returns true value of single xyRow coefficient double OsiBiLinear::xyCoefficient(const double * solution) const { // If another object has finer mesh ignore this if ((branchingStrategy_&8) != 0) return 0.0; double x = solution[xColumn_]; double y = solution[yColumn_]; //printf("x (%d,%g) y (%d,%g) x*y*coefficient %g\n", // xColumn_,x,yColumn_,y,x*y*coefficient_); return x*y*coefficient_; } // Redoes data when sequence numbers change void OsiBiLinear::resetSequenceEtc(int numberColumns, const int * originalColumns) { int i; #ifdef JJF_ZERO for (i = 0; i < numberColumns; i++) { if (originalColumns[i] == firstLambda_) break; } #else i = originalColumns[firstLambda_]; #endif if (i >= 0 && i < numberColumns) { firstLambda_ = i; for (int j = 0; j < 4; j++) { assert (originalColumns[j+i] - firstLambda_ == j); } } else { printf("lost set\n"); abort(); } // rows will be out anyway abort(); } // Creates a branching object OsiBranchingObject * OsiBiLinear::createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int way) const { // create object OsiBranchingObject * branch; assert (chosen_ == 0 || chosen_ == 1); //if (chosen_==0) //assert (xyBranchValue_>=info->lower_[xColumn_]&&xyBranchValue_<=info->upper_[xColumn_]); //else //assert (xyBranchValue_>=info->lower_[yColumn_]&&xyBranchValue_<=info->upper_[yColumn_]); branch = new OsiBiLinearBranchingObject(solver, this, way, xyBranchValue_, chosen_); return branch; } // Does work of branching void OsiBiLinear::newBounds(OsiSolverInterface * solver, int way, short xOrY, double separator) const { int iColumn; double mesh; double satisfied; if (xOrY == 0) { iColumn = xColumn_; mesh = xMeshSize_; satisfied = xSatisfied_; } else { iColumn = yColumn_; mesh = yMeshSize_; satisfied = ySatisfied_; } const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); double lower = columnLower[iColumn]; double distance; double steps; double zNew = separator; distance = separator - lower; assert (mesh); steps = floor ((distance + 0.5 * mesh) / mesh); if (mesh < 1.0) zNew = lower + steps * mesh; if (zNew > columnUpper[iColumn] - satisfied) zNew = 0.5 * (columnUpper[iColumn] - lower); double oldUpper = columnUpper[iColumn] ; double oldLower = columnLower[iColumn] ; #ifndef NDEBUG int nullChange = 0; #endif if (way < 0) { if (zNew > separator && mesh < 1.0) zNew -= mesh; double oldUpper = columnUpper[iColumn] ; if (zNew + satisfied >= oldUpper) zNew = 0.5 * (oldUpper + oldLower); if (mesh == 1.0) zNew = floor(separator); #ifndef NDEBUG if (oldUpper < zNew + 1.0e-8) nullChange = -1; #endif solver->setColUpper(iColumn, zNew); } else { if (zNew < separator && mesh < 1.0) zNew += mesh; if (zNew - satisfied <= oldLower) zNew = 0.5 * (oldUpper + oldLower); if (mesh == 1.0) zNew = ceil(separator); #ifndef NDEBUG if (oldLower > zNew - 1.0e-8) nullChange = 1; #endif solver->setColLower(iColumn, zNew); } if ((branchingStrategy_&4) != 0 && columnLower[xColumn_] == columnUpper[xColumn_] && columnLower[yColumn_] == columnUpper[yColumn_]) { // fake to make correct double lambda[4]; computeLambdas(solver, lambda); for (int j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; double value = lambda[j]; #ifndef NDEBUG if (fabs(value - columnLower[iColumn]) > 1.0e-5 || fabs(value - columnUpper[iColumn]) > 1.0e-5) nullChange = 0; #endif solver->setColLower(iColumn, value); solver->setColUpper(iColumn, value); } } #ifndef NDEBUG if (nullChange) printf("null change on column%s %d - bounds %g,%g\n", nullChange > 0 ? "Lower" : "Upper", iColumn, oldLower, oldUpper); #endif #ifdef JJF_ZERO // always free up lambda for (int i = firstLambda_; i < firstLambda_ + 4; i++) { solver->setColLower(i, 0.0); solver->setColUpper(i, 2.0); } #endif double xB[3]; xB[0] = columnLower[xColumn_]; xB[1] = columnUpper[xColumn_]; double yB[3]; yB[0] = columnLower[yColumn_]; yB[1] = columnUpper[yColumn_]; if (false && (branchingStrategy_&4) != 0 && yRow_ >= 0 && xMeshSize_ == 1.0 && yMeshSize_ == 1.0) { if ((xB[1] - xB[0])*(yB[1] - yB[0]) < 40) { // try looking at all solutions double lower[4]; double upper[4]; double lambda[4]; int i; double lowerLambda[4]; double upperLambda[4]; for (i = 0; i < 4; i++) { lower[i] = CoinMax(0.0, columnLower[firstLambda_+i]); upper[i] = CoinMin(1.0, columnUpper[firstLambda_+i]); lowerLambda[i] = 1.0; upperLambda[i] = 0.0; } // get coefficients double xybar[4]; getCoefficients(solver, xB, yB, xybar); double x, y; for (x = xB[0]; x <= xB[1]; x++) { xB[2] = x; for (y = yB[0]; y <= yB[1]; y++) { yB[2] = y; computeLambdas(xB, yB, xybar, lambda); for (i = 0; i < 4; i++) { lowerLambda[i] = CoinMin(lowerLambda[i], lambda[i]); upperLambda[i] = CoinMax(upperLambda[i], lambda[i]); } } } double change = 0.0;; for (i = 0; i < 4; i++) { if (lowerLambda[i] > lower[i] + 1.0e-12) { solver->setColLower(firstLambda_ + i, lowerLambda[i]); change += lowerLambda[i] - lower[i]; } if (upperLambda[i] < upper[i] - 1.0e-12) { solver->setColUpper(firstLambda_ + i, upperLambda[i]); change -= upperLambda[i] - upper[i]; } } if (change > 1.0e-5) printf("change of %g\n", change); } } if (boundType_) { assert (!xMeshSize_ || !yMeshSize_); if (xMeshSize_) { // can tighten bounds on y if ((boundType_&1) != 0) { if (xB[0]*yB[1] > coefficient_) { // tighten upper bound on y solver->setColUpper(yColumn_, coefficient_ / xB[0]); } } if ((boundType_&2) != 0) { if (xB[1]*yB[0] < coefficient_) { // tighten lower bound on y solver->setColLower(yColumn_, coefficient_ / xB[1]); } } } else { // can tighten bounds on x if ((boundType_&1) != 0) { if (yB[0]*xB[1] > coefficient_) { // tighten upper bound on x solver->setColUpper(xColumn_, coefficient_ / yB[0]); } } if ((boundType_&2) != 0) { if (yB[1]*xB[0] < coefficient_) { // tighten lower bound on x solver->setColLower(xColumn_, coefficient_ / yB[1]); } } } } } // Compute lambdas if coefficients not changing void OsiBiLinear::computeLambdas(const OsiSolverInterface * solver, double lambda[4]) const { // fix so correct double xB[3], yB[3]; double xybar[4]; getCoefficients(solver, xB, yB, xybar); double x, y; x = solver->getColLower()[xColumn_]; assert(x == solver->getColUpper()[xColumn_]); xB[2] = x; y = solver->getColLower()[yColumn_]; assert(y == solver->getColUpper()[yColumn_]); yB[2] = y; computeLambdas(xB, yB, xybar, lambda); assert (xyRow_ >= 0); } // Get LU coefficients from matrix void OsiBiLinear::getCoefficients(const OsiSolverInterface * solver, double xB[2], double yB[2], double xybar[4]) const { const CoinPackedMatrix * matrix = solver->getMatrixByCol(); const double * element = matrix->getElements(); const double * objective = solver->getObjCoefficients(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); // order is LxLy, LxUy, UxLy and UxUy int j; double multiplier = (boundType_ == 0) ? 1.0 / coefficient_ : 1.0; if (yRow_ >= 0) { for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; int iStart = columnStart[iColumn]; int iEnd = iStart + columnLength[iColumn]; int k = iStart; double x = 0.0; double y = 0.0; xybar[j] = 0.0; for (; k < iEnd; k++) { if (xRow_ == row[k]) x = element[k]; if (yRow_ == row[k]) y = element[k]; if (xyRow_ == row[k]) xybar[j] = element[k] * multiplier; } if (xyRow_ < 0) xybar[j] = objective[iColumn] * multiplier; if (j == 0) xB[0] = x; else if (j == 1) yB[1] = y; else if (j == 2) yB[0] = y; else if (j == 3) xB[1] = x; assert (fabs(xybar[j] - x*y) < 1.0e-4); } } else { // x==y for (j = 0; j < 4; j++) { int iColumn = firstLambda_ + j; int iStart = columnStart[iColumn]; int iEnd = iStart + columnLength[iColumn]; int k = iStart; double x = 0.0; xybar[j] = 0.0; for (; k < iEnd; k++) { if (xRow_ == row[k]) x = element[k]; if (xyRow_ == row[k]) xybar[j] = element[k] * multiplier; } if (xyRow_ < 0) xybar[j] = objective[iColumn] * multiplier; if (j == 0) { xB[0] = x; yB[0] = x; } else if (j == 2) { xB[1] = x; yB[1] = x; } } assert (fabs(xybar[0] - xB[0]*yB[0]) < 1.0e-4); assert (fabs(xybar[1] - xB[0]*yB[1]) < 1.0e-4); assert (fabs(xybar[2] - xB[1]*yB[0]) < 1.0e-4); assert (fabs(xybar[3] - xB[1]*yB[1]) < 1.0e-4); } } // Compute lambdas (third entry in each .B is current value) double OsiBiLinear::computeLambdas(const double xB[3], const double yB[3], const double xybar[4], double lambda[4]) const { // fake to make correct double x = xB[2]; double y = yB[2]; // order is LxLy, LxUy, UxLy and UxUy // l0 + l1 = this double rhs1 = (xB[1] - x) / (xB[1] - xB[0]); // l0 + l2 = this double rhs2 = (yB[1] - y) / (yB[1] - yB[0]); // For xy (taking out l3) double rhs3 = xB[1] * yB[1] - x * y; double a0 = xB[1] * yB[1] - xB[0] * yB[0]; double a1 = xB[1] * yB[1] - xB[0] * yB[1]; double a2 = xB[1] * yB[1] - xB[1] * yB[0]; // divide through to get l0 coefficient rhs3 /= a0; a1 /= a0; a2 /= a0; // subtract out l0 double b[2][2]; double rhs[2]; // first for l1 and l2 b[0][0] = 1.0 - a1; b[0][1] = -a2; rhs[0] = rhs1 - rhs3; // second b[1][0] = -a1; b[1][1] = 1.0 - a2; rhs[1] = rhs2 - rhs3; if (fabs(b[0][0]) > fabs(b[0][1])) { double sub = b[1][0] / b[0][0]; b[1][1] -= sub * b[0][1]; rhs[1] -= sub * rhs[0]; assert (fabs(b[1][1]) > 1.0e-12); lambda[2] = rhs[1] / b[1][1]; lambda[0] = rhs2 - lambda[2]; lambda[1] = rhs1 - lambda[0]; } else { double sub = b[1][1] / b[0][1]; b[1][0] -= sub * b[0][0]; rhs[1] -= sub * rhs[0]; assert (fabs(b[1][0]) > 1.0e-12); lambda[1] = rhs[1] / b[1][0]; lambda[0] = rhs1 - lambda[1]; lambda[2] = rhs2 - lambda[0]; } lambda[3] = 1.0 - (lambda[0] + lambda[1] + lambda[2]); double infeasibility = 0.0; double xy = 0.0; for (int j = 0; j < 4; j++) { double value = lambda[j]; if (value > 1.0) { infeasibility += value - 1.0; value = 1.0; } if (value < 0.0) { infeasibility -= value; value = 0.0; } lambda[j] = value; xy += xybar[j] * value; } assert (fabs(xy - x*y) < 1.0e-4); return infeasibility; } // Updates coefficients int OsiBiLinear::updateCoefficients(const double * lower, const double * upper, double * objective, CoinPackedMatrix * matrix, CoinWarmStartBasis * basis) const { // Return if no updates if ((branchingStrategy_&4) != 0) return 0; int numberUpdated = 0; double * element = matrix->getMutableElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); // order is LxLy, LxUy, UxLy and UxUy double xB[2]; double yB[2]; xB[0] = lower[xColumn_]; xB[1] = upper[xColumn_]; yB[0] = lower[yColumn_]; yB[1] = upper[yColumn_]; //printf("x %d (%g,%g) y %d (%g,%g)\n", // xColumn_,xB[0],xB[1], // yColumn_,yB[0],yB[1]); CoinWarmStartBasis::Status status[4]; int numStruct = basis ? basis->getNumStructural() - firstLambda_ : 0; double coefficient = (boundType_ == 0) ? coefficient_ : 1.0; for (int j = 0; j < 4; j++) { status[j] = (j < numStruct) ? basis->getStructStatus(j + firstLambda_) : CoinWarmStartBasis::atLowerBound; int iX = j >> 1; double x = xB[iX]; int iY = j & 1; double y = yB[iY]; CoinBigIndex k = columnStart[j+firstLambda_]; CoinBigIndex last = k + columnLength[j+firstLambda_]; double value; // xy value = coefficient * x * y; if (xyRow_ >= 0) { assert (row[k] == xyRow_); #if BI_PRINT > 1 printf("j %d xy (%d,%d) coeff from %g to %g\n", j, xColumn_, yColumn_, element[k], value); #endif element[k++] = value; } else { // objective objective[j+firstLambda_] = value; } numberUpdated++; // convexity assert (row[k] == convexity_); k++; // x value = x; #if BI_PRINT > 1 printf("j %d x (%d) coeff from %g to %g\n", j, xColumn_, element[k], value); #endif assert (row[k] == xRow_); element[k++] = value; numberUpdated++; if (yRow_ >= 0) { // y value = y; #if BI_PRINT > 1 printf("j %d y (%d) coeff from %g to %g\n", j, yColumn_, element[k], value); #endif assert (row[k] == yRow_); element[k++] = value; numberUpdated++; } // Do extra rows for (int i = 0; i < numberExtraRows_; i++) { int iRow = extraRow_[i]; for (; k < last; k++) { if (row[k] == iRow) break; } assert (k < last); element[k++] = x * y * multiplier_[i]; } } if (xB[0] == xB[1]) { if (yB[0] == yB[1]) { // only one basic bool first = true; for (int j = 0; j < 4; j++) { if (status[j] == CoinWarmStartBasis::basic) { if (first) { first = false; } else { basis->setStructStatus(j + firstLambda_, CoinWarmStartBasis::atLowerBound); #if BI_PRINT printf("zapping %d (x=%d,y=%d)\n", j, xColumn_, yColumn_); #endif } } } } else { if (status[0] == CoinWarmStartBasis::basic && status[2] == CoinWarmStartBasis::basic) { basis->setStructStatus(2 + firstLambda_, CoinWarmStartBasis::atLowerBound); #if BI_PRINT printf("zapping %d (x=%d,y=%d)\n", 2, xColumn_, yColumn_); #endif } if (status[1] == CoinWarmStartBasis::basic && status[3] == CoinWarmStartBasis::basic) { basis->setStructStatus(3 + firstLambda_, CoinWarmStartBasis::atLowerBound); #if BI_PRINT printf("zapping %d (x=%d,y=%d)\n", 3, xColumn_, yColumn_); #endif } } } else if (yB[0] == yB[1]) { if (status[0] == CoinWarmStartBasis::basic && status[1] == CoinWarmStartBasis::basic) { basis->setStructStatus(1 + firstLambda_, CoinWarmStartBasis::atLowerBound); #if BI_PRINT printf("zapping %d (x=%d,y=%d)\n", 1, xColumn_, yColumn_); #endif } if (status[2] == CoinWarmStartBasis::basic && status[3] == CoinWarmStartBasis::basic) { basis->setStructStatus(3 + firstLambda_, CoinWarmStartBasis::atLowerBound); #if BI_PRINT printf("zapping %d (x=%d,y=%d)\n", 3, xColumn_, yColumn_); #endif } } return numberUpdated; } // This does NOT set mutable stuff double OsiBiLinear::checkInfeasibility(const OsiBranchingInformation * info) const { // If another object has finer mesh ignore this if ((branchingStrategy_&8) != 0) return 0.0; int way; double saveInfeasibility = infeasibility_; short int saveWhichWay = whichWay_; double saveXyBranchValue = xyBranchValue_; short saveChosen = chosen_; double value = infeasibility(info, way); infeasibility_ = saveInfeasibility; whichWay_ = saveWhichWay; xyBranchValue_ = saveXyBranchValue; chosen_ = saveChosen; return value; } OsiBiLinearBranchingObject::OsiBiLinearBranchingObject() : OsiTwoWayBranchingObject(), chosen_(0) { } // Useful constructor OsiBiLinearBranchingObject::OsiBiLinearBranchingObject (OsiSolverInterface * solver, const OsiBiLinear * set, int way , double separator, int chosen) : OsiTwoWayBranchingObject(solver, set, way, separator), chosen_(static_cast(chosen)) { assert (chosen_ >= 0 && chosen_ < 2); } // Copy constructor OsiBiLinearBranchingObject::OsiBiLinearBranchingObject ( const OsiBiLinearBranchingObject & rhs) : OsiTwoWayBranchingObject(rhs), chosen_(rhs.chosen_) { } // Assignment operator OsiBiLinearBranchingObject & OsiBiLinearBranchingObject::operator=( const OsiBiLinearBranchingObject & rhs) { if (this != &rhs) { OsiTwoWayBranchingObject::operator=(rhs); chosen_ = rhs.chosen_; } return *this; } OsiBranchingObject * OsiBiLinearBranchingObject::clone() const { return (new OsiBiLinearBranchingObject(*this)); } // Destructor OsiBiLinearBranchingObject::~OsiBiLinearBranchingObject () { } double OsiBiLinearBranchingObject::branch(OsiSolverInterface * solver) { const OsiBiLinear * set = dynamic_cast (originalObject_) ; assert (set); int way = (!branchIndex_) ? (2 * firstBranch_ - 1) : -(2 * firstBranch_ - 1); branchIndex_++; set->newBounds(solver, way, chosen_, value_); return 0.0; } /* Return true if branch should only bound variables */ bool OsiBiLinearBranchingObject::boundBranch() const { const OsiBiLinear * set = dynamic_cast (originalObject_) ; assert (set); return (set->branchingStrategy()&4) != 0; } // Print what would happen void OsiBiLinearBranchingObject::print(const OsiSolverInterface * /*solver*/) { const OsiBiLinear * set = dynamic_cast (originalObject_) ; assert (set); int way = (!branchIndex_) ? (2 * firstBranch_ - 1) : -(2 * firstBranch_ - 1); int iColumn = (chosen_ == 1) ? set->xColumn() : set->yColumn(); printf("OsiBiLinear would branch %s on %c variable %d from value %g\n", (way < 0) ? "down" : "up", (chosen_ == 0) ? 'X' : 'Y', iColumn, value_); } // Default Constructor OsiBiLinearEquality::OsiBiLinearEquality () : OsiBiLinear(), numberPoints_(0) { } // Useful constructor OsiBiLinearEquality::OsiBiLinearEquality (OsiSolverInterface * solver, int xColumn, int yColumn, int xyRow, double rhs, double xMesh) : OsiBiLinear(), numberPoints_(0) { double xB[2]; double yB[2]; const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); xColumn_ = xColumn; yColumn_ = yColumn; xyRow_ = xyRow; coefficient_ = rhs; xB[0] = lower[xColumn_]; xB[1] = upper[xColumn_]; yB[0] = lower[yColumn_]; yB[1] = upper[yColumn_]; if (xB[1]*yB[1] < coefficient_ + 1.0e-12 || xB[0]*yB[0] > coefficient_ - 1.0e-12) { printf("infeasible row - reformulate\n"); abort(); } // reduce range of x if possible if (yB[0]*xB[1] > coefficient_ + 1.0e12) { xB[1] = coefficient_ / yB[0]; solver->setColUpper(xColumn_, xB[1]); } if (yB[1]*xB[0] < coefficient_ - 1.0e12) { xB[0] = coefficient_ / yB[1]; solver->setColLower(xColumn_, xB[0]); } // See how many points numberPoints_ = static_cast ((xB[1] - xB[0] + 0.5 * xMesh) / xMesh); // redo exactly xMeshSize_ = (xB[1] - xB[0]) / static_cast (numberPoints_); numberPoints_++; //#define KEEPXY #ifndef KEEPXY // Take out xyRow solver->setRowLower(xyRow_, 0.0); solver->setRowUpper(xyRow_, 0.0); #else // make >= solver->setRowLower(xyRow_, coefficient_ - 0.05); solver->setRowUpper(xyRow_, COIN_DBL_MAX); #endif double rowLower[3]; double rowUpper[3]; #ifndef KEEPXY double * columnLower = new double [numberPoints_]; double * columnUpper = new double [numberPoints_]; double * objective = new double [numberPoints_]; CoinBigIndex *starts = new CoinBigIndex[numberPoints_+1]; int * index = new int[3*numberPoints_]; double * element = new double [3*numberPoints_]; #else double * columnLower = new double [numberPoints_+2]; double * columnUpper = new double [numberPoints_+2]; double * objective = new double [numberPoints_+2]; CoinBigIndex *starts = new CoinBigIndex[numberPoints_+3]; int * index = new int[4*numberPoints_+2]; double * element = new double [4*numberPoints_+2]; #endif int i; starts[0] = 0; // rows int numberRows = solver->getNumRows(); // convexity rowLower[0] = 1.0; rowUpper[0] = 1.0; convexity_ = numberRows; starts[1] = 0; // x rowLower[1] = 0.0; rowUpper[1] = 0.0; index[0] = xColumn_; element[0] = -1.0; xRow_ = numberRows + 1; starts[2] = 1; rowLower[2] = 0.0; rowUpper[2] = 0.0; index[1] = yColumn; element[1] = -1.0; yRow_ = numberRows + 2; starts[3] = 2; solver->addRows(3, starts, index, element, rowLower, rowUpper); int n = 0; firstLambda_ = solver->getNumCols(); double x = xB[0]; assert(xColumn_ != yColumn_); for (i = 0; i < numberPoints_; i++) { double y = coefficient_ / x; columnLower[i] = 0.0; columnUpper[i] = 2.0; objective[i] = 0.0; double value; #ifdef KEEPXY // xy value = coefficient_; element[n] = value; index[n++] = xyRow_; #endif // convexity value = 1.0; element[n] = value; index[n++] = 0 + numberRows; // x value = x; if (fabs(value) < 1.0e-19) value = 1.0e-19; element[n] = value; index[n++] = 1 + numberRows; // y value = y; if (fabs(value) < 1.0e-19) value = 1.0e-19; element[n] = value; index[n++] = 2 + numberRows; starts[i+1] = n; x += xMeshSize_; } #ifdef KEEPXY // costed slacks columnLower[numberPoints_] = 0.0; columnUpper[numberPoints_] = xMeshSize_; objective[numberPoints_] = 1.0e3;; // convexity element[n] = 1.0; index[n++] = 0 + numberRows; starts[numberPoints_+1] = n; columnLower[numberPoints_+1] = 0.0; columnUpper[numberPoints_+1] = xMeshSize_; objective[numberPoints_+1] = 1.0e3;; // convexity element[n] = -1.0; index[n++] = 0 + numberRows; starts[numberPoints_+2] = n; solver->addCols(numberPoints_ + 2, starts, index, element, columnLower, columnUpper, objective); #else solver->addCols(numberPoints_, starts, index, element, columnLower, columnUpper, objective); #endif delete [] columnLower; delete [] columnUpper; delete [] objective; delete [] starts; delete [] index; delete [] element; } // Copy constructor OsiBiLinearEquality::OsiBiLinearEquality ( const OsiBiLinearEquality & rhs) : OsiBiLinear(rhs), numberPoints_(rhs.numberPoints_) { } // Clone OsiObject * OsiBiLinearEquality::clone() const { return new OsiBiLinearEquality(*this); } // Assignment operator OsiBiLinearEquality & OsiBiLinearEquality::operator=( const OsiBiLinearEquality & rhs) { if (this != &rhs) { OsiBiLinear::operator=(rhs); numberPoints_ = rhs.numberPoints_; } return *this; } // Destructor OsiBiLinearEquality::~OsiBiLinearEquality () { } // Possible improvement double OsiBiLinearEquality::improvement(const OsiSolverInterface * solver) const { const double * pi = solver->getRowPrice(); int i; const double * solution = solver->getColSolution(); printf(" for x %d y %d - pi %g %g\n", xColumn_, yColumn_, pi[xRow_], pi[yRow_]); for (i = 0; i < numberPoints_; i++) { if (fabs(solution[i+firstLambda_]) > 1.0e-7) printf("(%d %g) ", i, solution[i+firstLambda_]); } printf("\n"); return 0.0; } /* change grid if type 0 then use solution and make finer if 1 then back to original */ double OsiBiLinearEquality::newGrid(OsiSolverInterface * solver, int type) const { CoinPackedMatrix * matrix = solver->getMutableMatrixByCol(); if (!matrix) { printf("Unable to modify matrix\n"); abort(); } double * element = matrix->getMutableElements(); #ifndef NDEBUG const int * row = matrix->getIndices(); #endif const CoinBigIndex * columnStart = matrix->getVectorStarts(); //const int * columnLength = matrix->getVectorLengths(); // get original bounds double xB[2]; const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); xB[0] = lower[xColumn_]; xB[1] = upper[xColumn_]; assert (fabs((xB[1] - xB[0]) - xMeshSize_*(numberPoints_ - 1)) < 1.0e-7); double mesh = 0.0; int i; if (type == 0) { const double * solution = solver->getColSolution(); int first = -1; int last = -1; double xValue = 0.0; double step = 0.0; for (i = 0; i < numberPoints_; i++) { int iColumn = i + firstLambda_; if (fabs(solution[iColumn]) > 1.0e-7) { int k = columnStart[iColumn] + 1; xValue += element[k] * solution[iColumn]; if (first == -1) { first = i; step = -element[k]; } else { step += element[k]; } last = i; } } if (last > first + 1) { printf("not adjacent - presuming small djs\n"); } // new step size assert (numberPoints_ > 2); step = CoinMax((1.5 * step) / static_cast (numberPoints_ - 1), 0.5 * step); xB[0] = CoinMax(xB[0], xValue - 0.5 * step); xB[1] = CoinMin(xB[1], xValue + 0.5 * step); // and now divide these mesh = (xB[1] - xB[0]) / static_cast (numberPoints_ - 1); } else { // back to original mesh = xMeshSize_; } double x = xB[0]; for (i = 0; i < numberPoints_; i++) { int iColumn = i + firstLambda_; double y = coefficient_ / x; //assert (columnLength[iColumn]==3); - could have cuts int k = columnStart[iColumn]; #ifdef KEEPXY // xy assert (row[k] == xyRow_); k++; #endif assert (row[k] == convexity_); k++; double value; // x value = x; assert (row[k] == xRow_); assert (fabs(value) > 1.0e-10); element[k++] = value; // y value = y; assert (row[k] == yRow_); assert (fabs(value) > 1.0e-10); element[k++] = value; x += mesh; } return mesh; } /** Default Constructor Equivalent to an unspecified binary variable. */ OsiSimpleFixedInteger::OsiSimpleFixedInteger () : OsiSimpleInteger() { } /** Useful constructor Loads actual upper & lower bounds for the specified variable. */ OsiSimpleFixedInteger::OsiSimpleFixedInteger (const OsiSolverInterface * solver, int iColumn) : OsiSimpleInteger(solver, iColumn) { } // Useful constructor - passed solver index and original bounds OsiSimpleFixedInteger::OsiSimpleFixedInteger ( int iColumn, double lower, double upper) : OsiSimpleInteger(iColumn, lower, upper) { } // Useful constructor - passed simple integer OsiSimpleFixedInteger::OsiSimpleFixedInteger ( const OsiSimpleInteger &rhs) : OsiSimpleInteger(rhs) { } // Copy constructor OsiSimpleFixedInteger::OsiSimpleFixedInteger ( const OsiSimpleFixedInteger & rhs) : OsiSimpleInteger(rhs) { } // Clone OsiObject * OsiSimpleFixedInteger::clone() const { return new OsiSimpleFixedInteger(*this); } // Assignment operator OsiSimpleFixedInteger & OsiSimpleFixedInteger::operator=( const OsiSimpleFixedInteger & rhs) { if (this != &rhs) { OsiSimpleInteger::operator=(rhs); } return *this; } // Destructor OsiSimpleFixedInteger::~OsiSimpleFixedInteger () { } // Infeasibility - large is 0.5 double OsiSimpleFixedInteger::infeasibility(const OsiBranchingInformation * info, int & whichWay) const { double value = info->solution_[columnNumber_]; value = CoinMax(value, info->lower_[columnNumber_]); value = CoinMin(value, info->upper_[columnNumber_]); double nearest = floor(value + (1.0 - 0.5)); if (nearest > value) { whichWay = 1; } else { whichWay = 0; } infeasibility_ = fabs(value - nearest); bool satisfied = false; if (infeasibility_ <= info->integerTolerance_) { otherInfeasibility_ = 1.0; satisfied = true; if (info->lower_[columnNumber_] != info->upper_[columnNumber_]) infeasibility_ = 1.0e-5; else infeasibility_ = 0.0; } else if (info->defaultDual_ < 0.0) { otherInfeasibility_ = 1.0 - infeasibility_; } else { const double * pi = info->pi_; const double * activity = info->rowActivity_; const double * lower = info->rowLower_; const double * upper = info->rowUpper_; const double * element = info->elementByColumn_; const int * row = info->row_; const CoinBigIndex * columnStart = info->columnStart_; const int * columnLength = info->columnLength_; double direction = info->direction_; double downMovement = value - floor(value); double upMovement = 1.0 - downMovement; double valueP = info->objective_[columnNumber_] * direction; CoinBigIndex start = columnStart[columnNumber_]; CoinBigIndex end = start + columnLength[columnNumber_]; double upEstimate = 0.0; double downEstimate = 0.0; if (valueP > 0.0) upEstimate = valueP * upMovement; else downEstimate -= valueP * downMovement; double tolerance = info->primalTolerance_; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; if (lower[iRow] < -1.0e20) assert (pi[iRow] <= 1.0e-3); if (upper[iRow] > 1.0e20) assert (pi[iRow] >= -1.0e-3); valueP = pi[iRow] * direction; double el2 = element[j]; double value2 = valueP * el2; double u = 0.0; double d = 0.0; if (value2 > 0.0) u = value2; else d = -value2; // if up makes infeasible then make at least default double newUp = activity[iRow] + upMovement * el2; if (newUp > upper[iRow] + tolerance || newUp < lower[iRow] - tolerance) u = CoinMax(u, info->defaultDual_); upEstimate += u * upMovement * fabs(el2); // if down makes infeasible then make at least default double newDown = activity[iRow] - downMovement * el2; if (newDown > upper[iRow] + tolerance || newDown < lower[iRow] - tolerance) d = CoinMax(d, info->defaultDual_); downEstimate += d * downMovement * fabs(el2); } if (downEstimate >= upEstimate) { infeasibility_ = CoinMax(1.0e-12, upEstimate); otherInfeasibility_ = CoinMax(1.0e-12, downEstimate); whichWay = 1; } else { infeasibility_ = CoinMax(1.0e-12, downEstimate); otherInfeasibility_ = CoinMax(1.0e-12, upEstimate); whichWay = 0; } } if (preferredWay_ >= 0 && !satisfied) whichWay = preferredWay_; whichWay_ = static_cast(whichWay); return infeasibility_; } // Creates a branching object OsiBranchingObject * OsiSimpleFixedInteger::createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const { double value = info->solution_[columnNumber_]; value = CoinMax(value, info->lower_[columnNumber_]); value = CoinMin(value, info->upper_[columnNumber_]); assert (info->upper_[columnNumber_] > info->lower_[columnNumber_]); double nearest = floor(value + 0.5); double integerTolerance = info->integerTolerance_; if (fabs(value - nearest) < integerTolerance) { // adjust value if (nearest != info->upper_[columnNumber_]) value = nearest + 2.0 * integerTolerance; else value = nearest - 2.0 * integerTolerance; } OsiBranchingObject * branch = new OsiIntegerBranchingObject(solver, this, way, value); return branch; } #include #include #include #include #include #include //#define CGL_DEBUG 2 #include "CoinHelperFunctions.hpp" #include "CoinPackedVector.hpp" #include "OsiRowCutDebugger.hpp" #include "CoinWarmStartBasis.hpp" //#include "CglTemporary.hpp" #include "CoinFinite.hpp" //------------------------------------------------------------------- // Generate Stored cuts //------------------------------------------------------------------- void CglTemporary::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo /*info*/) { // Get basic problem information const double * solution = si.getColSolution(); int numberRowCuts = cuts_.sizeRowCuts(); for (int i = 0; i < numberRowCuts; i++) { const OsiRowCut * rowCutPointer = cuts_.rowCutPtr(i); double violation = rowCutPointer->violated(solution); if (violation >= requiredViolation_) cs.insert(*rowCutPointer); } // delete cuts_ = OsiCuts(); } //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CglTemporary::CglTemporary () : CglStored() { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CglTemporary::CglTemporary (const CglTemporary & source) : CglStored(source) { } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- CglCutGenerator * CglTemporary::clone() const { return new CglTemporary(*this); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CglTemporary::~CglTemporary () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CglTemporary & CglTemporary::operator=(const CglTemporary & rhs) { if (this != &rhs) { CglStored::operator=(rhs); } return *this; } void checkQP(ClpSimplex * /*model*/) { #ifdef JJF_ZERO printf("Checking quadratic model %x\n", model); if (model) { ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(model->objectiveAsObject())); assert (quadraticObj); CoinPackedMatrix * quadraticObjective = quadraticObj->quadraticObjective(); int numberColumns = quadraticObj->numberColumns(); const int * columnQuadratic = quadraticObjective->getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticObjective->getVectorStarts(); const int * columnQuadraticLength = quadraticObjective->getVectorLengths(); //const double * quadraticElement = quadraticObjective->getElements(); for (int i = 0; i < numberColumns; i++) { for (int j = columnQuadraticStart[i]; j < columnQuadraticStart[i] + columnQuadraticLength[i]; j++) assert (columnQuadratic[j] >= 0 && columnQuadratic[j] < 1000); } } #endif } //############################################################################# // Solve methods //############################################################################# void OsiSolverLinearizedQuadratic::initialSolve() { OsiClpSolverInterface::initialSolve(); int secondaryStatus = modelPtr_->secondaryStatus(); if (modelPtr_->status() == 0 && (secondaryStatus == 2 || secondaryStatus == 4)) modelPtr_->cleanup(1); if (isProvenOptimal() && modelPtr_->numberColumns() == quadraticModel_->numberColumns()) { // see if qp can get better solution const double * solution = modelPtr_->primalColumnSolution(); int numberColumns = modelPtr_->numberColumns(); bool satisfied = true; for (int i = 0; i < numberColumns; i++) { if (isInteger(i)) { double value = solution[i]; if (fabs(value - floor(value + 0.5)) > 1.0e-6) { satisfied = false; break; } } } if (satisfied) { checkQP(quadraticModel_); ClpSimplex qpTemp(*quadraticModel_); checkQP(&qpTemp); double * lower = qpTemp.columnLower(); double * upper = qpTemp.columnUpper(); double * lower2 = modelPtr_->columnLower(); double * upper2 = modelPtr_->columnUpper(); for (int i = 0; i < numberColumns; i++) { if (isInteger(i)) { double value = floor(solution[i] + 0.5); lower[i] = value; upper[i] = value; } else { lower[i] = lower2[i]; upper[i] = upper2[i]; } } //qpTemp.writeMps("bad.mps"); //modelPtr_->writeMps("bad2.mps"); //qpTemp.objectiveAsObject()->setActivated(0); //qpTemp.primal(); //qpTemp.objectiveAsObject()->setActivated(1); qpTemp.primal(); //assert (!qpTemp.problemStatus()); if (qpTemp.objectiveValue() < bestObjectiveValue_ && !qpTemp.problemStatus()) { delete [] bestSolution_; bestSolution_ = CoinCopyOfArray(qpTemp.primalColumnSolution(), numberColumns); bestObjectiveValue_ = qpTemp.objectiveValue(); printf("better qp objective of %g\n", bestObjectiveValue_); } } } } //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiSolverLinearizedQuadratic::OsiSolverLinearizedQuadratic () : OsiClpSolverInterface() { bestObjectiveValue_ = COIN_DBL_MAX; bestSolution_ = NULL; specialOptions3_ = 0; quadraticModel_ = NULL; } OsiSolverLinearizedQuadratic::OsiSolverLinearizedQuadratic ( ClpSimplex * quadraticModel) : OsiClpSolverInterface(new ClpSimplex(*quadraticModel), true) { bestObjectiveValue_ = COIN_DBL_MAX; bestSolution_ = NULL; specialOptions3_ = 0; quadraticModel_ = new ClpSimplex(*quadraticModel); // linearize int numberColumns = modelPtr_->numberColumns(); const double * solution = modelPtr_->primalColumnSolution(); // Replace objective ClpObjective * trueObjective = modelPtr_->objectiveAsObject(); ClpObjective * objective = new ClpLinearObjective(NULL, numberColumns); modelPtr_->setObjectivePointer(objective); double offset; double saveOffset = modelPtr_->objectiveOffset(); memcpy(modelPtr_->objective(), trueObjective->gradient(modelPtr_, solution, offset, true, 2), numberColumns*sizeof(double)); modelPtr_->setObjectiveOffset(saveOffset + offset); delete trueObjective; checkQP(quadraticModel_); } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * OsiSolverLinearizedQuadratic::clone(bool /*copyData*/) const { //assert (copyData); return new OsiSolverLinearizedQuadratic(*this); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiSolverLinearizedQuadratic::OsiSolverLinearizedQuadratic ( const OsiSolverLinearizedQuadratic & rhs) : OsiSolverInterface(rhs) , OsiClpSolverInterface(rhs) { bestObjectiveValue_ = rhs.bestObjectiveValue_; if (rhs.bestSolution_) { bestSolution_ = CoinCopyOfArray(rhs.bestSolution_, modelPtr_->numberColumns()); } else { bestSolution_ = NULL; } specialOptions3_ = rhs.specialOptions3_; if (rhs.quadraticModel_) { quadraticModel_ = new ClpSimplex(*rhs.quadraticModel_); } else { quadraticModel_ = NULL; } checkQP(rhs.quadraticModel_); checkQP(quadraticModel_); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiSolverLinearizedQuadratic::~OsiSolverLinearizedQuadratic () { delete [] bestSolution_; delete quadraticModel_; } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiSolverLinearizedQuadratic & OsiSolverLinearizedQuadratic::operator=(const OsiSolverLinearizedQuadratic & rhs) { if (this != &rhs) { delete [] bestSolution_; delete quadraticModel_; OsiClpSolverInterface::operator=(rhs); bestObjectiveValue_ = rhs.bestObjectiveValue_; if (rhs.bestSolution_) { bestSolution_ = CoinCopyOfArray(rhs.bestSolution_, modelPtr_->numberColumns()); } else { bestSolution_ = NULL; } specialOptions3_ = rhs.specialOptions3_; if (rhs.quadraticModel_) { quadraticModel_ = new ClpSimplex(*rhs.quadraticModel_); } else { quadraticModel_ = NULL; } checkQP(rhs.quadraticModel_); checkQP(quadraticModel_); } return *this; } /* Expands out all possible combinations for a knapsack If buildObj NULL then just computes space needed - returns number elements On entry numberOutput is maximum allowed, on exit it is number needed or -1 (as will be number elements) if maximum exceeded. numberOutput will have at least space to return values which reconstruct input. Rows returned will be original rows but no entries will be returned for any rows all of whose entries are in knapsack. So up to user to allow for this. If reConstruct >=0 then returns number of entrie which make up item "reConstruct" in expanded knapsack. Values in buildRow and buildElement; */ int CoinModel::expandKnapsack(int knapsackRow, int & numberOutput, double * buildObj, CoinBigIndex * buildStart, int * buildRow, double * buildElement, int reConstruct) const { /* mark rows -2 in knapsack and other variables -1 not involved 0 only in knapsack */ int * markRow = new int [numberRows_]; int iRow; int iColumn; int * whichColumn = new int [numberColumns_]; for (iColumn = 0; iColumn < numberColumns_; iColumn++) whichColumn[iColumn] = -1; int numJ = 0; for (iRow = 0; iRow < numberRows_; iRow++) markRow[iRow] = -1; CoinModelLink triple; triple = firstInRow(knapsackRow); while (triple.column() >= 0) { int iColumn = triple.column(); #ifndef NDEBUG const char * el = getElementAsString(knapsackRow, iColumn); assert (!strcmp("Numeric", el)); #endif whichColumn[iColumn] = numJ; numJ++; triple = next(triple); } for (iRow = 0; iRow < numberRows_; iRow++) { triple = firstInRow(iRow); int type = -3; while (triple.column() >= 0) { int iColumn = triple.column(); if (whichColumn[iColumn] >= 0) { if (type == -3) type = 0; else if (type != 0) type = -2; } else { if (type == -3) type = -1; else if (type == 0) type = -2; } triple = next(triple); } if (type == -3) type = -1; markRow[iRow] = type; } int * bound = new int [numberColumns_+1]; int * whichRow = new int [numberRows_]; ClpSimplex tempModel; CoinModel tempModel2(*this); tempModel.loadProblem(tempModel2); int * stack = new int [numberColumns_+1]; double * size = new double [numberColumns_+1]; double * rhsOffset = new double[numberRows_]; int * build = new int[numberColumns_]; int maxNumber = numberOutput; numJ = 0; double minSize = getRowLower(knapsackRow); double maxSize = getRowUpper(knapsackRow); double offset = 0.0; triple = firstInRow(knapsackRow); while (triple.column() >= 0) { iColumn = triple.column(); double lowerColumn = columnLower(iColumn); double upperColumn = columnUpper(iColumn); double gap = upperColumn - lowerColumn; if (gap > 1.0e8) gap = 1.0e8; assert (fabs(floor(gap + 0.5) - gap) < 1.0e-5); whichColumn[numJ] = iColumn; bound[numJ] = static_cast (gap); size[numJ++] = triple.value(); offset += triple.value() * lowerColumn; triple = next(triple); } int jRow; for (iRow = 0; iRow < numberRows_; iRow++) whichRow[iRow] = iRow; ClpSimplex smallModel(&tempModel, numberRows_, whichRow, numJ, whichColumn, true, true, true); // modify rhs to allow for nonzero lower bounds double * rowLower = smallModel.rowLower(); double * rowUpper = smallModel.rowUpper(); const double * columnLower = smallModel.columnLower(); //const double * columnUpper = smallModel.columnUpper(); const CoinPackedMatrix * matrix = smallModel.matrix(); const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * objective = smallModel.objective(); double objectiveOffset = 0.0; CoinZeroN(rhsOffset, numberRows_); for (iColumn = 0; iColumn < numJ; iColumn++) { double lower = columnLower[iColumn]; if (lower) { objectiveOffset += objective[iColumn]; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { double value = element[j] * lower; int kRow = row[j]; rhsOffset[kRow] += value; if (rowLower[kRow] > -1.0e20) rowLower[kRow] -= value; if (rowUpper[kRow] < 1.0e20) rowUpper[kRow] -= value; } } } // relax for (jRow = 0; jRow < numberRows_; jRow++) { if (markRow[jRow] == 0 && knapsackRow != jRow) { if (rowLower[jRow] > -1.0e20) rowLower[jRow] -= 1.0e-7; if (rowUpper[jRow] < 1.0e20) rowUpper[jRow] += 1.0e-7; } else { rowLower[jRow] = -COIN_DBL_MAX; rowUpper[jRow] = COIN_DBL_MAX; } } double * rowActivity = smallModel.primalRowSolution(); CoinZeroN(rowActivity, numberRows_); maxSize -= offset; minSize -= offset; // now generate int i; int iStack = numJ; for (i = 0; i < numJ; i++) { stack[i] = 0; } double tooMuch = 10.0 * maxSize; stack[numJ] = 1; size[numJ] = tooMuch; bound[numJ] = 0; double sum = tooMuch; numberOutput = 0; int nelCreate = 0; /* typeRun is - 0 for initial sizes 1 for build 2 for reconstruct */ int typeRun = buildObj ? 1 : 0; if (reConstruct >= 0) { assert (buildRow && buildElement); typeRun = 2; } if (typeRun == 1) buildStart[0] = 0; while (iStack >= 0) { if (sum >= minSize && sum <= maxSize) { double checkSize = 0.0; bool good = true; int nRow = 0; double obj = objectiveOffset; // nRow is zero? CoinZeroN(rowActivity,nRow); for (iColumn = 0; iColumn < numJ; iColumn++) { int iValue = stack[iColumn]; if (iValue > bound[iColumn]) { good = false; break; } else if (iValue) { obj += objective[iColumn] * iValue; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { double value = element[j] * iValue; int kRow = row[j]; if (rowActivity[kRow]) { rowActivity[kRow] += value; if (!rowActivity[kRow]) rowActivity[kRow] = 1.0e-100; } else { build[nRow++] = kRow; rowActivity[kRow] = value; } } } } if (good) { for (jRow = 0; jRow < nRow; jRow++) { int kRow = build[jRow]; double value = rowActivity[kRow]; if (value > rowUpper[kRow] || value < rowLower[kRow]) { good = false; break; } } } if (good) { if (typeRun == 1) { buildObj[numberOutput] = obj; for (jRow = 0; jRow < nRow; jRow++) { int kRow = build[jRow]; double value = rowActivity[kRow]; if (markRow[kRow] < 0 && fabs(value) > 1.0e-13) { buildElement[nelCreate] = value; buildRow[nelCreate++] = kRow; } } buildStart[numberOutput+1] = nelCreate; } else if (!typeRun) { for (jRow = 0; jRow < nRow; jRow++) { int kRow = build[jRow]; double value = rowActivity[kRow]; if (markRow[kRow] < 0 && fabs(value) > 1.0e-13) { nelCreate++; } } } if (typeRun == 2 && reConstruct == numberOutput) { // build and exit nelCreate = 0; for (iColumn = 0; iColumn < numJ; iColumn++) { int iValue = stack[iColumn]; if (iValue) { buildRow[nelCreate] = whichColumn[iColumn]; buildElement[nelCreate++] = iValue; } } numberOutput = 1; for (i = 0; i < numJ; i++) { bound[i] = 0; } break; } numberOutput++; if (numberOutput > maxNumber) { nelCreate = -1; numberOutput = -1; for (i = 0; i < numJ; i++) { bound[i] = 0; } break; } else if (typeRun == 1 && numberOutput == maxNumber) { // On second run for (i = 0; i < numJ; i++) { bound[i] = 0; } break; } for (int j = 0; j < numJ; j++) { checkSize += stack[j] * size[j]; } assert (fabs(sum - checkSize) < 1.0e-3); } for (jRow = 0; jRow < nRow; jRow++) { int kRow = build[jRow]; rowActivity[kRow] = 0.0; } } if (sum > maxSize || stack[iStack] > bound[iStack]) { sum -= size[iStack] * stack[iStack]; stack[iStack--] = 0; if (iStack >= 0) { stack[iStack] ++; sum += size[iStack]; } } else { // must be less // add to last possible iStack = numJ - 1; sum += size[iStack]; stack[iStack]++; } } //printf("%d will be created\n",numberOutput); delete [] whichColumn; delete [] whichRow; delete [] bound; delete [] stack; delete [] size; delete [] rhsOffset; delete [] build; delete [] markRow; return nelCreate; } #include "ClpConstraint.hpp" #include "ClpConstraintLinear.hpp" #include "ClpConstraintQuadratic.hpp" #ifdef COIN_HAS_ASL //#include "ClpAmplObjective.hpp" #endif /* Return an approximate solution to a CoinModel. Lots of bounds may be odd to force a solution. mode = 0 just tries to get a continuous solution */ ClpSimplex * approximateSolution(CoinModel & coinModel, int numberPasses, double deltaTolerance, int /*mode*/) { #ifndef JJF_ONE //#ifdef COIN_HAS_ASL // matrix etc will be changed CoinModel coinModel2 = coinModel; if (coinModel2.moreInfo()) { // for now just ampl objective ClpSimplex * model = new ClpSimplex(); model->loadProblem(coinModel2); int numberConstraints; ClpConstraint ** constraints = NULL; int type = model->loadNonLinear(coinModel2.moreInfo(), numberConstraints, constraints); if (type == 1 || type == 3) { model->nonlinearSLP(numberPasses, deltaTolerance); } else if (type == 2 || type == 4) { model->nonlinearSLP(numberConstraints, constraints, numberPasses, deltaTolerance); } else { printf("error or linear - fix %d\n", type); } //exit(66); return model; } // first check and set up arrays int numberColumns = coinModel.numberColumns(); int numberRows = coinModel.numberRows(); // List of nonlinear rows int * which = new int[numberRows]; bool testLinear = false; int numberConstraints = 0; int iColumn; bool linearObjective = true; int maximumQuadraticElements = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { // See if quadratic objective const char * expr = coinModel.getColumnObjectiveAsString(iColumn); if (strcmp(expr, "Numeric")) { linearObjective = false; // check if value*x+-value*y.... assert (strlen(expr) < 20000); char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel); // must be column unless first when may be linear term if (jColumn >= 0) { maximumQuadraticElements++; } else if (jColumn != -2) { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } } if (!linearObjective) { // zero objective for (iColumn = 0; iColumn < numberColumns; iColumn++) coinModel2.setObjective(iColumn, 0.0); } int iRow; for (iRow = 0; iRow < numberRows; iRow++) { int numberQuadratic = 0; bool linear = true; CoinModelLink triple = coinModel.firstInRow(iRow); while (triple.column() >= 0) { int iColumn = triple.column(); const char * expr = coinModel.getElementAsString(iRow, iColumn); if (strcmp("Numeric", expr)) { linear = false; // check if value*x+-value*y.... assert (strlen(expr) < 20000); char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel); // must be column unless first when may be linear term if (jColumn >= 0) { numberQuadratic++; } else if (jColumn != -2) { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } triple = coinModel.next(triple); } if (!linear || testLinear) { CoinModelLink triple = coinModel.firstInRow(iRow); while (triple.column() >= 0) { int iColumn = triple.column(); coinModel2.setElement(iRow, iColumn, 0.0); triple = coinModel.next(triple); } which[numberConstraints++] = iRow; maximumQuadraticElements = CoinMax(maximumQuadraticElements, numberQuadratic); } } ClpSimplex * model = new ClpSimplex(); // return if nothing if (!numberConstraints && linearObjective) { delete [] which; model->loadProblem(coinModel); model->dual(); return model; } // space for quadratic // allow for linear term maximumQuadraticElements += numberColumns; CoinBigIndex * startQuadratic = new CoinBigIndex [numberColumns+1]; int * columnQuadratic = new int [maximumQuadraticElements]; double * elementQuadratic = new double [maximumQuadraticElements]; ClpConstraint ** constraints = new ClpConstraint * [numberConstraints]; double * linearTerm = new double [numberColumns]; int saveNumber = numberConstraints; numberConstraints = 0; ClpQuadraticObjective * quadObj = NULL; if (!linearObjective) { int numberQuadratic = 0; CoinZeroN(linearTerm, numberColumns); for (iColumn = 0; iColumn < numberColumns; iColumn++) { startQuadratic[iColumn] = numberQuadratic; // See if quadratic objective const char * expr = coinModel.getColumnObjectiveAsString(iColumn); if (strcmp(expr, "Numeric")) { // value*x*y char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel); // must be column unless first when may be linear term if (jColumn >= 0) { columnQuadratic[numberQuadratic] = jColumn; if (jColumn != iColumn) elementQuadratic[numberQuadratic++] = 1.0 * value; // convention else if (jColumn == iColumn) elementQuadratic[numberQuadratic++] = 2.0 * value; // convention } else if (jColumn == -2) { linearTerm[iColumn] = value; } else { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } else { // linear part linearTerm[iColumn] = coinModel.getColumnObjective(iColumn); } } startQuadratic[numberColumns] = numberQuadratic; quadObj = new ClpQuadraticObjective(linearTerm, numberColumns, startQuadratic, columnQuadratic, elementQuadratic); } int iConstraint; for (iConstraint = 0; iConstraint < saveNumber; iConstraint++) { iRow = which[iConstraint]; if (iRow >= 0) { int numberQuadratic = 0; int lastColumn = -1; int largestColumn = -1; CoinZeroN(linearTerm, numberColumns); CoinModelLink triple = coinModel.firstInRow(iRow); while (triple.column() >= 0) { int iColumn = triple.column(); while (lastColumn < iColumn) { startQuadratic[lastColumn+1] = numberQuadratic; lastColumn++; } const char * expr = coinModel.getElementAsString(iRow, iColumn); if (strcmp("Numeric", expr)) { largestColumn = CoinMax(largestColumn, iColumn); // value*x*y char temp[20000]; strcpy(temp, expr); char * pos = temp; bool ifFirst = true; while (*pos) { double value; int jColumn = decodeBit(pos, pos, value, ifFirst, coinModel); // must be column unless first when may be linear term if (jColumn >= 0) { columnQuadratic[numberQuadratic] = jColumn; if (jColumn == iColumn) elementQuadratic[numberQuadratic++] = 2.0 * value; // convention else elementQuadratic[numberQuadratic++] = 1.0 * value; // convention largestColumn = CoinMax(largestColumn, jColumn); } else if (jColumn == -2) { linearTerm[iColumn] = value; // and put in as row -1 columnQuadratic[numberQuadratic] = -1; if (jColumn == iColumn) elementQuadratic[numberQuadratic++] = 2.0 * value; // convention else elementQuadratic[numberQuadratic++] = 1.0 * value; // convention largestColumn = CoinMax(largestColumn, iColumn); } else { printf("bad nonlinear term %s\n", temp); abort(); } ifFirst = false; } } else { // linear part linearTerm[iColumn] = coinModel.getElement(iRow, iColumn); // and put in as row -1 columnQuadratic[numberQuadratic] = -1; elementQuadratic[numberQuadratic++] = linearTerm[iColumn]; if (linearTerm[iColumn]) largestColumn = CoinMax(largestColumn, iColumn); } triple = coinModel.next(triple); } while (lastColumn < numberColumns) { startQuadratic[lastColumn+1] = numberQuadratic; lastColumn++; } // here we create ClpConstraint if (testLinear) { int n = 0; int * indices = new int[numberColumns]; for (int j = 0; j < numberColumns; j++) { if (linearTerm[j]) { linearTerm[n] = linearTerm[j]; indices[n++] = j; } } /// Constructor from constraint constraints[numberConstraints++] = new ClpConstraintLinear(iRow, n, numberColumns, indices, linearTerm); delete [] indices; } else { constraints[numberConstraints++] = new ClpConstraintQuadratic(iRow, largestColumn + 1, numberColumns, startQuadratic, columnQuadratic, elementQuadratic); } } } delete [] startQuadratic; delete [] columnQuadratic; delete [] elementQuadratic; delete [] linearTerm; delete [] which; model->loadProblem(coinModel2); if (quadObj) model->setObjective(quadObj); delete quadObj; #ifndef NDEBUG int returnCode; if (numberConstraints) { returnCode = model->nonlinearSLP(numberConstraints, constraints, numberPasses, deltaTolerance); for (iConstraint = 0; iConstraint < saveNumber; iConstraint++) delete constraints[iConstraint]; } else { returnCode = model->nonlinearSLP(numberPasses, deltaTolerance); } assert (!returnCode); #else if (numberConstraints) { model->nonlinearSLP(numberConstraints, constraints, numberPasses, deltaTolerance); for (iConstraint = 0; iConstraint < saveNumber; iConstraint++) delete constraints[iConstraint]; } else { model->nonlinearSLP(numberPasses, deltaTolerance); } #endif delete [] constraints; return model; #else printf("loadNonLinear needs ampl\n"); abort(); return NULL; #endif } OsiChooseStrongSubset::OsiChooseStrongSubset() : OsiChooseStrong(), numberObjectsToUse_(0) { } OsiChooseStrongSubset::OsiChooseStrongSubset(const OsiSolverInterface * solver) : OsiChooseStrong(solver), numberObjectsToUse_(-1) { } OsiChooseStrongSubset::OsiChooseStrongSubset(const OsiChooseStrongSubset & rhs) : OsiChooseStrong(rhs) { numberObjectsToUse_ = -1; } OsiChooseStrongSubset & OsiChooseStrongSubset::operator=(const OsiChooseStrongSubset & rhs) { if (this != &rhs) { OsiChooseStrong::operator=(rhs); numberObjectsToUse_ = -1; } return *this; } OsiChooseStrongSubset::~OsiChooseStrongSubset () { } // Clone OsiChooseVariable * OsiChooseStrongSubset::clone() const { return new OsiChooseStrongSubset(*this); } // Initialize int OsiChooseStrongSubset::setupList ( OsiBranchingInformation *info, bool initialize) { assert (solver_ == info->solver_); // Only has to work with Clp OsiSolverInterface * solverA = const_cast (solver_); OsiSolverLink * solver = dynamic_cast (solverA); assert (solver); int numberObjects = solver->numberObjects(); if (numberObjects > pseudoCosts_.numberObjects()) { // redo useful arrays pseudoCosts_.initialize(numberObjects); } int numObj = numberObjects; if (numberObjectsToUse_ < 0) { // Sort objects so bilinear at end OsiObject ** sorted = new OsiObject * [numberObjects]; OsiObject ** objects = solver->objects(); numObj = 0; int numberBiLinear = 0; int i; for (i = 0; i < numberObjects; i++) { OsiObject * obj = objects[i]; OsiBiLinear * objB = dynamic_cast (obj); if (!objB) objects[numObj++] = obj; else sorted[numberBiLinear++] = obj; } numberObjectsToUse_ = numObj; for (i = 0; i < numberBiLinear; i++) objects[numObj++] = sorted[i]; delete [] sorted; // See if any master objects for (i = 0; i < numberObjectsToUse_; i++) { OsiUsesBiLinear * obj = dynamic_cast (objects[i]); if (obj) obj->addBiLinearObjects(solver); } } solver->setNumberObjects(numberObjectsToUse_); numObj = numberObjectsToUse_; // Use shadow prices //info->defaultDual_=0.0; int numberUnsatisfied = OsiChooseStrong::setupList ( info, initialize); solver->setNumberObjects(numberObjects); numObj = numberObjects; return numberUnsatisfied; } /* Choose a variable Returns - -1 Node is infeasible 0 Normal termination - we have a candidate 1 All looks satisfied - no candidate 2 We can change the bound on a variable - but we also have a strong branching candidate 3 We can change the bound on a variable - but we have a non-strong branching candidate 4 We can change the bound on a variable - no other candidates We can pick up branch from whichObject() and whichWay() We can pick up a forced branch (can change bound) from whichForcedObject() and whichForcedWay() If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() */ int OsiChooseStrongSubset::chooseVariable( OsiSolverInterface * solver, OsiBranchingInformation *info, bool fixVariables) { //int numberObjects = solver->numberObjects(); //solver->setNumberObjects(numberObjectsToUse_); //numberObjects_=numberObjectsToUse_; // Use shadow prices //info->defaultDual_=0.0; int returnCode = OsiChooseStrong::chooseVariable(solver, info, fixVariables); //solver->setNumberObjects(numberObjects); //numberObjects_=numberObjects; return returnCode; } /** Default Constructor Equivalent to an unspecified binary variable. */ OsiUsesBiLinear::OsiUsesBiLinear () : OsiSimpleInteger(), numberBiLinear_(0), type_(0), objects_(NULL) { } /** Useful constructor Loads actual upper & lower bounds for the specified variable. */ OsiUsesBiLinear::OsiUsesBiLinear (const OsiSolverInterface * solver, int iColumn, int type) : OsiSimpleInteger(solver, iColumn), numberBiLinear_(0), type_(type), objects_(NULL) { if (type_) { assert(originalLower_ == floor(originalLower_ + 0.5)); assert(originalUpper_ == floor(originalUpper_ + 0.5)); } } // Useful constructor - passed solver index and original bounds OsiUsesBiLinear::OsiUsesBiLinear ( int iColumn, double lower, double upper, int type) : OsiSimpleInteger(iColumn, lower, upper), numberBiLinear_(0), type_(type), objects_(NULL) { if (type_) { assert(originalLower_ == floor(originalLower_ + 0.5)); assert(originalUpper_ == floor(originalUpper_ + 0.5)); } } // Useful constructor - passed simple integer OsiUsesBiLinear::OsiUsesBiLinear ( const OsiSimpleInteger &rhs, int type) : OsiSimpleInteger(rhs), numberBiLinear_(0), type_(type), objects_(NULL) { if (type_) { assert(originalLower_ == floor(originalLower_ + 0.5)); assert(originalUpper_ == floor(originalUpper_ + 0.5)); } } // Copy constructor OsiUsesBiLinear::OsiUsesBiLinear ( const OsiUsesBiLinear & rhs) : OsiSimpleInteger(rhs), numberBiLinear_(0), type_(rhs.type_), objects_(NULL) { } // Clone OsiObject * OsiUsesBiLinear::clone() const { return new OsiUsesBiLinear(*this); } // Assignment operator OsiUsesBiLinear & OsiUsesBiLinear::operator=( const OsiUsesBiLinear & rhs) { if (this != &rhs) { OsiSimpleInteger::operator=(rhs); delete [] objects_; numberBiLinear_ = 0; type_ = rhs.type_; objects_ = NULL; } return *this; } // Destructor OsiUsesBiLinear::~OsiUsesBiLinear () { delete [] objects_; } // Infeasibility - large is 0.5 double OsiUsesBiLinear::infeasibility(const OsiBranchingInformation * info, int & whichWay) const { assert (type_ == 0); // just continuous for now double value = info->solution_[columnNumber_]; value = CoinMax(value, info->lower_[columnNumber_]); value = CoinMin(value, info->upper_[columnNumber_]); infeasibility_ = 0.0; for (int i = 0; i < numberBiLinear_; i++) { OsiBiLinear * obj = dynamic_cast (objects_[i]); assert (obj); //obj->getPseudoShadow(info); //infeasibility_ += objects_[i]->infeasibility(info,whichWay); infeasibility_ += obj->getMovement(info); } bool satisfied = false; whichWay = -1; if (!infeasibility_) { otherInfeasibility_ = 1.0; satisfied = true; infeasibility_ = 0.0; } else { otherInfeasibility_ = 10.0 * infeasibility_; if (value - info->lower_[columnNumber_] > info->upper_[columnNumber_] - value) whichWay = 1; else whichWay = -1; } if (preferredWay_ >= 0 && !satisfied) whichWay = preferredWay_; whichWay_ = static_cast(whichWay); return infeasibility_; } // Creates a branching object OsiBranchingObject * OsiUsesBiLinear::createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const { double value = info->solution_[columnNumber_]; value = CoinMax(value, info->lower_[columnNumber_]); value = CoinMin(value, info->upper_[columnNumber_]); assert (info->upper_[columnNumber_] > info->lower_[columnNumber_]); double nearest = floor(value + 0.5); double integerTolerance = info->integerTolerance_; if (fabs(value - nearest) < integerTolerance) { // adjust value if (nearest != info->upper_[columnNumber_]) value = nearest + 2.0 * integerTolerance; else value = nearest - 2.0 * integerTolerance; } OsiBranchingObject * branch = new OsiIntegerBranchingObject(solver, this, way, value, value, value); return branch; } // This looks at solution and sets bounds to contain solution /** More precisely: it first forces the variable within the existing bounds, and then tightens the bounds to fix the variable at the nearest integer value. */ double OsiUsesBiLinear::feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const { double value = info->solution_[columnNumber_]; double newValue = CoinMax(value, info->lower_[columnNumber_]); newValue = CoinMin(newValue, info->upper_[columnNumber_]); solver->setColLower(columnNumber_, newValue); solver->setColUpper(columnNumber_, newValue); return fabs(value - newValue); } // Add all bi-linear objects void OsiUsesBiLinear::addBiLinearObjects(OsiSolverLink * solver) { delete [] objects_; numberBiLinear_ = 0; OsiObject ** objects = solver->objects(); int i; int numberObjects = solver->numberObjects(); for (i = 0; i < numberObjects; i++) { OsiObject * obj = objects[i]; OsiBiLinear * objB = dynamic_cast (obj); if (objB) { if (objB->xColumn() == columnNumber_ || objB->yColumn() == columnNumber_) numberBiLinear_++; } } if (numberBiLinear_) { objects_ = new OsiObject * [numberBiLinear_]; numberBiLinear_ = 0; for (i = 0; i < numberObjects; i++) { OsiObject * obj = objects[i]; OsiBiLinear * objB = dynamic_cast (obj); if (objB) { if (objB->xColumn() == columnNumber_ || objB->yColumn() == columnNumber_) objects_[numberBiLinear_++] = obj;; } } } else { objects_ = NULL; } } Cbc-2.8.12/src/unitTestClp.cpp0000644000076600007660000006011412244670720014530 0ustar coincoin/* $Id: unitTestClp.cpp 1985 2013-11-25 15:50:40Z tkr $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include #include #include "CoinTime.hpp" #include "CoinFileIO.hpp" #include "CbcModel.hpp" #include "CbcHeuristic.hpp" #include "CbcCutGenerator.hpp" #include "CbcBranchCut.hpp" #include "CglProbing.hpp" #include "OsiClpSolverInterface.hpp" #include "ClpFactorization.hpp" #include "OsiRowCutDebugger.hpp" //############################################################################# #ifdef NDEBUG #undef NDEBUG #endif //############################################################################# // Display message on stdout and stderr void testingMessage( const char * const msg ) { std::cout << msg; //cout <(std::cout.precision()) ; /* Set the range of problems to be tested. testSwitch = -2 is special and is picked up below. */ int loSet = 0 ; int hiSet = 0 ; if (testSwitch == -1) { loSet = 0 ; hiSet = 1 ; } else if (testSwitch >= 0) { loSet = static_cast(stuff[6]) ; hiSet = testSwitch ; std::cout << "Solving miplib problems in sets " << loSet << ":" << hiSet << "." << std::endl ; } /* Vectors to hold test problem names and characteristics. */ std::vector mpsName ; std::vector nRows ; std::vector nCols ; std::vector objValueC ; std::vector objValue ; std::vector testSet ; std::vector rowCutDebugger ; /* A macro to make the vector creation marginally readable. Parameters are name, rows, columns, integer objective, continuous objective, set ID, row cut debugger To enable the row cut debugger for a given problem, change the last parameter to true. Don't forget to turn it off before committing changes! */ #define PUSH_MPS(zz_mpsName_zz,\ zz_nRows_zz,zz_nCols_zz,zz_objValue_zz,zz_objValueC_zz, \ zz_testSet_zz, zz_rcDbg_zz) \ mpsName.push_back(zz_mpsName_zz) ; \ nRows.push_back(zz_nRows_zz) ; \ nCols.push_back(zz_nCols_zz) ; \ objValueC.push_back(zz_objValueC_zz) ; \ testSet.push_back(zz_testSet_zz) ; \ objValue.push_back(zz_objValue_zz) ; \ rowCutDebugger.push_back(zz_rcDbg_zz) ; /* Push the miplib problems. Except for -2 (unitTest), push all, even if we're not going to do all of them. */ if (testSwitch == -2) { PUSH_MPS("p0033", 16, 33, 3089, 2520.57, 0, false); PUSH_MPS("p0201", 133, 201, 7615, 6875.0, 0, false); // PUSH_MPS("flugpl", 18, 18, 1201500, 1167185.7, 0, false); } else { /* Load up the problem vector. Note that the row counts here include the objective function. */ PUSH_MPS("10teams", 230, 2025, 924, 917, 1, false); PUSH_MPS("air03", 124, 10757, 340160, 338864.25, 0, false); PUSH_MPS("air04", 823, 8904, 56137, 55535.436, 2, false); PUSH_MPS("air05", 426, 7195, 26374, 25877.609, 2, false); PUSH_MPS("arki001", 1048, 1388, 7580813.0459, 7579599.80787, 7, false); PUSH_MPS("bell3a", 123, 133, 878430.32, 862578.64, 0, false); PUSH_MPS("bell5", 91, 104, 8966406.49, 8608417.95, 1, false); PUSH_MPS("blend2", 274, 353, 7.598985, 6.9156751140, 0, false); PUSH_MPS("cap6000", 2176, 6000, -2451377, -2451537.325, 1, false); PUSH_MPS("dano3mip", 3202, 13873, 728.1111, 576.23162474, 7, false); PUSH_MPS("danoint", 664, 521, 65.67, 62.637280418, 6, false); PUSH_MPS("dcmulti", 290, 548, 188182, 183975.5397, 0, false); PUSH_MPS("dsbmip", 1182, 1886, -305.19817501, -305.19817501, 0, false); PUSH_MPS("egout", 98, 141, 568.101, 149.589, 0, false); PUSH_MPS("enigma", 21, 100, 0.0, 0.0, 0, false); PUSH_MPS("fast0507", 507, 63009, 174, 172.14556668, 5, false); PUSH_MPS("fiber", 363, 1298, 405935.18000, 156082.51759, 0, false); PUSH_MPS("fixnet6", 478, 878, 3983, 1200.88, 1, false); PUSH_MPS("flugpl", 18, 18, 1201500, 1167185.7, 0, false); PUSH_MPS("gen", 780, 870, 112313, 112130.0, 0, false); PUSH_MPS("gesa2", 1392, 1224, 25779856.372, 25476489.678, 1, false); PUSH_MPS("gesa2_o", 1248, 1224, 25779856.372, 25476489.678, 1, false); PUSH_MPS("gesa3", 1368, 1152, 27991042.648, 27833632.451, 0, false); PUSH_MPS("gesa3_o", 1224, 1152, 27991042.648, 27833632.451, 0, false); PUSH_MPS("gt2", 29, 188, 21166.000, 13460.233074, 0, false); PUSH_MPS("harp2", 112, 2993, -73899798.00, -74353341.502, 6, false); PUSH_MPS("khb05250", 101, 1350, 106940226, 95919464.0, 0, false); PUSH_MPS("l152lav", 97, 1989, 4722, 4656.36, 1, false); PUSH_MPS("lseu", 28, 89, 1120, 834.68, 0, false); PUSH_MPS("mas74", 13, 151, 11801.18573, 10482.79528, 3, false); PUSH_MPS("mas76", 12, 151, 40005.05414, 38893.9036, 2, false); PUSH_MPS("misc03", 96, 160, 3360, 1910., 0, false); PUSH_MPS("misc06", 820, 1808, 12850.8607, 12841.6, 0, false); PUSH_MPS("misc07", 212, 260, 2810, 1415.0, 1, false); PUSH_MPS("mitre", 2054, 10724, 115155, 114740.5184, 1, false); PUSH_MPS("mkc", 3411, 5325, -553.75, -611.85, 7, false); // suboptimal PUSH_MPS("mod008", 6, 319, 307, 290.9, 0, false); PUSH_MPS("mod010", 146, 2655, 6548, 6532.08, 0, false); PUSH_MPS("mod011", 4480, 10958, -54558535, -62121982.55, 2, false); PUSH_MPS("modglob", 291, 422, 20740508, 20430947., 2, false); PUSH_MPS("noswot", 182, 128, -43, -43.0, 6, false); PUSH_MPS("nw04", 36, 87482, 16862, 16310.66667, 1, false); PUSH_MPS("p0033", 16, 33, 3089, 2520.57, 0, false); PUSH_MPS("p0201", 133, 201, 7615, 6875.0, 0, false); PUSH_MPS("p0282", 241, 282, 258411, 176867.50, 0, false); PUSH_MPS("p0548", 176, 548, 8691, 315.29, 0, false); PUSH_MPS("p2756", 755, 2756, 3124, 2688.75, 0, false); PUSH_MPS("pk1", 45, 86, 11.0, 0.0, 2, false); PUSH_MPS("pp08a", 136, 240, 7350.0, 2748.3452381, 1, false); PUSH_MPS("pp08aCUTS", 246, 240, 7350.0, 5480.6061563, 1, false); PUSH_MPS("qiu", 1192, 840, -132.873137, -931.638857, 3, false); PUSH_MPS("qnet1", 503, 1541, 16029.692681, 14274.102667, 0, false); PUSH_MPS("qnet1_o", 456, 1541, 16029.692681, 12095.571667, 0, false); PUSH_MPS("rentacar", 6803, 9557, 30356761, 28806137.644, 0, false); PUSH_MPS("rgn", 24, 180, 82.1999, 48.7999, 0, false); PUSH_MPS("rout", 291, 556, 1077.56, 981.86428571, 3, false); PUSH_MPS("set1ch", 492, 712, 54537.75, 32007.73, 5, false); PUSH_MPS("seymour", 4944, 1372, 423, 403.84647413, 7, false); PUSH_MPS("seymour_1", 4944, 1372, 410.76370, 403.84647413, 5, false); PUSH_MPS("stein27", 118, 27, 18, 13.0, 0, false); PUSH_MPS("stein45", 331, 45, 30, 22.0, 1, false); PUSH_MPS("swath", 884, 6805, 497.603, 334.4968581, 7, false); PUSH_MPS("vpm1", 234, 378, 20, 15.4167, 0, false); PUSH_MPS("vpm2", 234, 378, 13.75, 9.8892645972, 0, false); } #undef PUSH_MPS /* Normally the problems are executed in order. Define RANDOM_ORDER below to randomize. #define RANDOM_ORDER */ int which[100]; int nLoop = static_cast(mpsName.size()); assert (nLoop <= 100); for (int i = 0; i < nLoop; i++) which[i] = i; # ifdef RANDOM_ORDER unsigned int iTime = static_cast(CoinGetTimeOfDay()-1.256e9); std::cout << "Time (seed) " << iTime << "." << std::endl ; double sort[100]; CoinDrand48(true,iTime); for (int i = 0; i < nLoop; i++) sort[i] = CoinDrand48(); CoinSort_2(sort,sort+nLoop,which); # endif int problemCnt = 0; for (m = 0 ; m < mpsName.size() ; m++) { int setID = testSet[m]; if (loSet <= setID && setID <= hiSet) problemCnt++; } int numberFailures = 0; int numberAttempts = 0; int numProbSolved = 0; double timeTaken = 0.0; //#define CLP_FACTORIZATION_INSTRUMENT # ifdef CLP_FACTORIZATION_INSTRUMENT double timeTakenFac = 0.0; # endif /* Open the main loop to step through the MPS problems. */ for (unsigned int mw = 0 ; mw < mpsName.size() ; mw++) { m = which[mw]; int setID = testSet[m]; // Skip if problem is not in specified problem set(s) if (!(loSet <= setID && setID <= hiSet)) continue ; numberAttempts++; std::cout << " processing mps file: " << mpsName[m] << " (" << numberAttempts << " out of " << problemCnt << ")" << std::endl ; /* Stage 1: Read the MPS and make sure the size of the constraint matrix is correct. */ CbcModel *model = new CbcModel(saveModel) ; std::string fn = dirMiplib+mpsName[m] ; if (!CbcTestMpsFile(fn)) { std::cout << "ERROR: Cannot find MPS file " << fn << "." << std::endl ; continue; } model->solver()->readMps(fn.c_str(), "") ; assert(model->getNumRows() == nRows[m]) ; assert(model->getNumCols() == nCols[m]) ; // Careful! We're initialising for the benefit of other code. CoinDrand48(true,1234567); //printf("RAND1 %g %g\n",CoinDrand48(true,1234567),model->randomNumberGenerator()->randomDouble()); //printf("RAND1 %g\n",CoinDrand48(true,1234567)); // Higher limits for the serious problems. int testMaximumNodes = 200000; if (hiSet > 1) testMaximumNodes = 20000000; if (model->getMaximumNodes() > testMaximumNodes) { model->setMaximumNodes(testMaximumNodes); } /* Stage 2: Call solver to solve the problem. */ # ifdef CLP_FACTORIZATION_INSTRUMENT extern double factorization_instrument(int type); double facTime1 = factorization_instrument(0); std::cout << "Factorization - initial solve " << facTime1 << " seconds." << std::endl ; timeTakenFac += facTime1; # endif double startTime = CoinCpuTime()+CoinCpuTimeJustChildren(); // Setup specific to clp OsiClpSolverInterface *siClp = dynamic_cast(model->solver()) ; ClpSimplex *modelC = NULL; if (siClp) { modelC = siClp->getModelPtr(); ClpMatrixBase * matrix = modelC->clpMatrix(); ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); if (stuff && stuff[9] && clpMatrix) { // vector matrix! clpMatrix->makeSpecialColumnCopy(); } # ifdef JJF_ZERO if (clpMatrix) { int numberRows = clpMatrix->getNumRows(); int numberColumns = clpMatrix->getNumCols(); double * elements = clpMatrix->getMutableElements(); const int * row = clpMatrix->getIndices(); const CoinBigIndex * columnStart = clpMatrix->getVectorStarts(); const int * columnLength = clpMatrix->getVectorLengths(); double * smallest = new double [numberRows]; double * largest = new double [numberRows]; char * flag = new char [numberRows]; CoinZeroN(flag, numberRows); for (int i = 0; i < numberRows; i++) { smallest[i] = COIN_DBL_MAX; largest[i] = 0.0; } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { bool isInteger = modelC->isInteger(iColumn); CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = fabs(elements[j]); if (!isInteger) flag[iRow] = 1; smallest[iRow] = CoinMin(smallest[iRow], value); largest[iRow] = CoinMax(largest[iRow], value); } } double * rowLower = modelC->rowLower(); double * rowUpper = modelC->rowUpper(); bool changed = false; for (int i = 0; i < numberRows; i++) { if (flag[i] && smallest[i] > 10.0 && false) { smallest[i] = 1.0 / smallest[i]; if (rowLower[i] > -1.0e20) rowLower[i] *= smallest[i]; if (rowUpper[i] < 1.0e20) rowUpper[i] *= smallest[i]; changed = true; } else { smallest[i] = 0.0; } } if (changed) { printf("SCALED\n"); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (smallest[iRow]) elements[j] *= smallest[iRow]; } } } delete [] smallest; delete [] largest; delete [] flag; } # endif // JJF_ZERO model->checkModel(); modelC->tightenPrimalBounds(0.0, 0, true); model->initialSolve(); if (modelC->dualBound() == 1.0e10) { // user did not set - so modify // get largest scaled away from bound ClpSimplex temp = *modelC; temp.dual(0, 7); double largestScaled = 1.0e-12; double largest = 1.0e-12; int numberRows = temp.numberRows(); const double * rowPrimal = temp.primalRowSolution(); const double * rowLower = temp.rowLower(); const double * rowUpper = temp.rowUpper(); const double * rowScale = temp.rowScale(); int iRow; for (iRow = 0; iRow < numberRows; iRow++) { double value = rowPrimal[iRow]; double above = value - rowLower[iRow]; double below = rowUpper[iRow] - value; if (above < 1.0e12) { largest = CoinMax(largest, above); } if (below < 1.0e12) { largest = CoinMax(largest, below); } if (rowScale) { double multiplier = rowScale[iRow]; above *= multiplier; below *= multiplier; } if (above < 1.0e12) { largestScaled = CoinMax(largestScaled, above); } if (below < 1.0e12) { largestScaled = CoinMax(largestScaled, below); } } int numberColumns = temp.numberColumns(); const double * columnPrimal = temp.primalColumnSolution(); const double * columnLower = temp.columnLower(); const double * columnUpper = temp.columnUpper(); const double * columnScale = temp.columnScale(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = columnPrimal[iColumn]; double above = value - columnLower[iColumn]; double below = columnUpper[iColumn] - value; if (above < 1.0e12) { largest = CoinMax(largest, above); } if (below < 1.0e12) { largest = CoinMax(largest, below); } if (columnScale) { double multiplier = 1.0 / columnScale[iColumn]; above *= multiplier; below *= multiplier; } if (above < 1.0e12) { largestScaled = CoinMax(largestScaled, above); } if (below < 1.0e12) { largestScaled = CoinMax(largestScaled, below); } } std::cout << "Largest (scaled) away from bound " << largestScaled << " unscaled " << largest << std::endl; # ifdef JJF_ZERO modelC->setDualBound(CoinMax(1.0001e8, CoinMin(1000.0*largestScaled,1.00001e10))); # else modelC->setDualBound(CoinMax(1.0001e9, CoinMin(1000.0*largestScaled,1.0001e10))); # endif } } // end clp-specific setup /* Cut passes: For small models (n < 500) always do 100 passes, if possible (-100). For larger models, use minimum drop to stop (100, 20). */ model->setMinimumDrop(CoinMin(5.0e-2, fabs(model->getMinimizationObjValue())*1.0e-3+1.0e-4)); if (CoinAbs(model->getMaximumCutPassesAtRoot()) <= 100) { if (model->getNumCols() < 500) { model->setMaximumCutPassesAtRoot(-100); } else if (model->getNumCols() < 5000) { model->setMaximumCutPassesAtRoot(100); } else { model->setMaximumCutPassesAtRoot(20); } } // If defaults then increase trust for small models if (model->numberStrong() == 5 && model->numberBeforeTrust() == 10) { int numberColumns = model->getNumCols(); if (numberColumns <= 50) { model->setNumberBeforeTrust(1000); } else if (numberColumns <= 100) { model->setNumberBeforeTrust(100); } else if (numberColumns <= 300) { model->setNumberBeforeTrust(50); } } //if (model->getNumCols()>=500) { // switch off Clp stuff //model->setFastNodeDepth(-1); //} /* Activate the row cut debugger, if requested. */ if (rowCutDebugger[m] == true) { std::string probName ; model->solver()->getStrParam(OsiProbName,probName) ; model->solver()->activateRowCutDebugger(probName.c_str()) ; if (model->solver()->getRowCutDebugger()) std::cout << "Row cut debugger activated for " ; else std::cout << "Failed to activate row cut debugger for " ; std::cout << mpsName[m] << "." << std::endl ; } setCutAndHeuristicOptions(*model) ; /* More clp-specific setup. */ if (siClp) { # ifdef CLP_MULTIPLE_FACTORIZATIONS if (!modelC->factorization()->isDenseOrSmall()) { int denseCode = stuff ? static_cast (stuff[4]) : -1; int smallCode = stuff ? static_cast (stuff[10]) : -1; if (stuff && stuff[8] >= 1) { if (denseCode < 0) denseCode = 40; if (smallCode < 0) smallCode = 40; } if (denseCode > 0) modelC->factorization()->setGoDenseThreshold(denseCode); if (smallCode > 0) modelC->factorization()->setGoSmallThreshold(smallCode); if (denseCode >= modelC->numberRows()) { //printf("problem going dense\n"); //modelC->factorization()->goDenseOrSmall(modelC->numberRows()); } } # endif if (stuff && stuff[8] >= 1) { if (modelC->numberColumns() + modelC->numberRows() <= 10000 && model->fastNodeDepth() == -1) model->setFastNodeDepth(-9); } } //OsiObject * obj = new CbcBranchToFixLots(model,0.3,0.0,3,3000003); //model->addObjects(1,&obj); //delete obj; /* Finally, the actual call to solve the MIP with branch-and-cut. */ model->branchAndBound(); # ifdef CLP_FACTORIZATION_INSTRUMENT double facTime = factorization_instrument(0); std::cout << "Factorization " << facTime << " seconds." << std::endl , timeTakenFac += facTime; # endif /* Stage 3: Do the statistics and check the answer. */ double timeOfSolution = CoinCpuTime()+CoinCpuTimeJustChildren()-startTime; std::cout << "Cuts at root node changed objective from " << model->getContinuousObjective() << " to " << model->rootObjectiveAfterCuts() << std::endl ; int numberGenerators = model->numberCutGenerators(); for (int iGenerator = 0 ; iGenerator < numberGenerators ; iGenerator++) { CbcCutGenerator *generator = model->cutGenerator(iGenerator); # ifdef CLIQUE_ANALYSIS # ifndef CLP_INVESTIGATE CglImplication *implication = dynamic_cast(generator->generator()); if (implication) continue; # endif # endif std::cout << generator->cutGeneratorName() << " was tried " << generator->numberTimesEntered() << " times and created " << generator->numberCutsInTotal() << " cuts of which " << generator->numberCutsActive() << " were active after adding rounds of cuts"; if (generator->timing()) std::cout << " (" << generator->timeInCutGenerator() << " seconds)" ; std::cout << "." << std::endl; } std::cout << model->getNumberHeuristicSolutions() << " solutions found by heuristics." << std::endl ; int numberHeuristics = model->numberHeuristics(); for (int iHeuristic = 0 ; iHeuristic < numberHeuristics ; iHeuristic++) { CbcHeuristic *heuristic = model->heuristic(iHeuristic); if (heuristic->numRuns()) { std::cout << heuristic->heuristicName() << " was tried " << heuristic->numRuns() << " times out of " << heuristic->numCouldRun() << " and created " << heuristic->numberSolutionsFound() << " solutions." << std::endl ; } } /* Check for the correct answer. */ if (!model->status()) { double objActual = model->getObjValue() ; double objExpect = objValue[m] ; double tolerance = CoinMin(fabs(objActual),fabs(objExpect)) ; tolerance = CoinMax(1.0e-5,1.0e-5*tolerance) ; //CoinRelFltEq eq(1.0e-3) ; std::cout << "cbc_clp (" << mpsName[m] << ") " << std::setprecision(10) << objActual ; if (fabs(objActual-objExpect) < tolerance) { std::cout << std::setprecision(dfltPrecision) << "; okay" ; numProbSolved++; } else { std::cout << " != " << objExpect << std::setprecision(dfltPrecision) << "; error = " << fabs(objExpect-objActual) ; numberFailures++; //#ifdef COIN_DEVELOP //abort(); //#endif } } else { std::cout << "cbc_clp (" << mpsName[m] << ") status not optimal; " << "assuming too many nodes" ; } timeTaken += timeOfSolution; std::cout << " -- (" << model->getNodeCount() << " n / " << model->getIterationCount() << " i / " << timeOfSolution << " s) (subtotal " << timeTaken << " seconds)" << std::endl; delete model; } /* End main loop on MPS problems. Print a summary and calculate the return value. */ int returnCode = 0; std::cout << "cbc_clp solved " << numProbSolved << " out of " << numberAttempts; int numberOnNodes = numberAttempts-numProbSolved-numberFailures; if (numberFailures || numberOnNodes) { if (numberOnNodes) { std::cout << " (" << numberOnNodes << " stopped on nodes)"; returnCode = numberOnNodes; } if (numberFailures) { std::cout << " (" << numberFailures << " gave bad answer!)"; returnCode += 100*numberFailures; } } std::cout << " and took " << timeTaken << " seconds." << std::endl; if (testSwitch == -2) { if (numberFailures || numberOnNodes) { std::cout << "****** Unit Test failed." << std::endl ; std::cerr << "****** Unit Test failed." << std::endl ; } else { std::cerr << "****** Unit Test succeeded." << std::endl ; } } # ifdef CLP_FACTORIZATION_INSTRUMENT std::cout << "Total factorization time " << timeTakenFac << "seconds." << std::endl ; # endif return (returnCode) ; } Cbc-2.8.12/src/CbcGenParam.cpp0000644000076600007660000000654012131315050014342 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenParam.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include "CoinParam.hpp" #include "CbcModel.hpp" #include "CbcGenCtlBlk.hpp" #include "CbcGenParam.hpp" namespace { char svnid[] = "$Id: CbcGenParam.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } /* Constructors and destructors There's a generic constructor and one for integer, double, keyword, string, and action parameters. */ /* Default constructor. */ CbcGenParam::CbcGenParam () : CoinParam(), paramCode_(CbcGenParamCode(0)), obj_(0) { /* Nothing to be done here */ } /* Constructor for double parameter */ CbcGenParam::CbcGenParam (CbcGenParamCode code, std::string name, std::string help, double lower, double upper, double dflt, bool display) : CoinParam(name, help, lower, upper, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for integer parameter */ CbcGenParam::CbcGenParam (CbcGenParamCode code, std::string name, std::string help, int lower, int upper, int dflt, bool display) : CoinParam(name, help, lower, upper, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for keyword parameter. */ CbcGenParam::CbcGenParam (CbcGenParamCode code, std::string name, std::string help, std::string firstValue, int dflt, bool display) : CoinParam(name, help, firstValue, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for string parameter. */ CbcGenParam::CbcGenParam (CbcGenParamCode code, std::string name, std::string help, std::string dflt, bool display) : CoinParam(name, help, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for action parameter. */ CbcGenParam::CbcGenParam (CbcGenParamCode code, std::string name, std::string help, bool display) : CoinParam(name, help, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Copy constructor. */ CbcGenParam::CbcGenParam (const CbcGenParam &orig) : CoinParam(orig), paramCode_(orig.paramCode_), obj_(orig.obj_) { /* Nothing to be done here */ } /* Clone */ CbcGenParam *CbcGenParam::clone () { return (new CbcGenParam(*this)) ; } CbcGenParam &CbcGenParam::operator= (const CbcGenParam & rhs) { if (this != &rhs) { CoinParam::operator=(rhs) ; paramCode_ = rhs.paramCode_ ; obj_ = rhs.obj_ ; } return *this ; } /* Destructor */ CbcGenParam::~CbcGenParam () { /* Nothing more to do */ } Cbc-2.8.12/src/CbcCutSubsetModifier.cpp0000644000076600007660000000472712131315050016255 0ustar coincoin// $Id: CbcCutSubsetModifier.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2003, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCutGenerator #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" #include #include #include #include #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #else #include "OsiSolverInterface.hpp" #endif #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcCutGenerator.hpp" #include "CbcBranchDynamic.hpp" #include "CglProbing.hpp" #include "CoinTime.hpp" #include "CbcCutSubsetModifier.hpp" // Default Constructor CbcCutSubsetModifier::CbcCutSubsetModifier () : CbcCutModifier(), firstOdd_(COIN_INT_MAX) { } // Useful constructor CbcCutSubsetModifier::CbcCutSubsetModifier (int firstOdd) : CbcCutModifier() { firstOdd_ = firstOdd; } // Copy constructor CbcCutSubsetModifier::CbcCutSubsetModifier ( const CbcCutSubsetModifier & rhs) : CbcCutModifier(rhs) { firstOdd_ = rhs.firstOdd_; } // Clone CbcCutModifier * CbcCutSubsetModifier::clone() const { return new CbcCutSubsetModifier(*this); } // Assignment operator CbcCutSubsetModifier & CbcCutSubsetModifier::operator=( const CbcCutSubsetModifier & rhs) { if (this != &rhs) { CbcCutModifier::operator=(rhs); firstOdd_ = rhs.firstOdd_; } return *this; } // Destructor CbcCutSubsetModifier::~CbcCutSubsetModifier () { } /* Returns 0 unchanged 1 strengthened 2 weakened 3 deleted */ int CbcCutSubsetModifier::modify(const OsiSolverInterface * /*solver*/, OsiRowCut & cut) { int n = cut.row().getNumElements(); if (!n) return 0; const int * column = cut.row().getIndices(); //const double * element = cut.row().getElements(); int returnCode = 0; for (int i = 0; i < n; i++) { if (column[i] >= firstOdd_) { returnCode = 3; break; } } #ifdef COIN_DETAIL if (!returnCode) { const double * element = cut.row().getElements(); printf("%g <= ", cut.lb()); for (int i = 0; i < n; i++) { printf("%g*x%d ", element[i], column[i]); } printf("<= %g\n", cut.ub()); } #endif //return 3; return returnCode; } Cbc-2.8.12/src/config_default.h0000644000076600007660000000437512131315050014662 0ustar coincoin /* include the COIN-OR-wide system specific configure header */ #include "configall_system.h" /* include the public project specific macros */ #include "config_cbc_default.h" /***************************************************************************/ /* HERE DEFINE THE PROJECT SPECIFIC MACROS */ /* These are only in effect in a setting that doesn't use configure */ /***************************************************************************/ /* Define to the debug sanity check level (0 is no test) */ #define COIN_CBC_CHECKLEVEL 0 /* Define to the debug verbosity level (0 is no output) */ #define COIN_CBC_VERBOSITY 0 /* Define to 1 if the Cgl package is used */ #define COIN_HAS_CGL 1 /* Define to 1 if the Clp package is used */ #define COIN_HAS_CLP 1 /* Define to 1 if the CoinUtils package is used */ #define COIN_HAS_COINUTILS 1 /* Define to 1 if the Osi package is used */ #define COIN_HAS_OSI 1 /* Define to 1 if the Vol package is used */ #define COIN_HAS_VOL 1 /* Define to 1 if the Cplex package is used */ /* #undef COIN_HAS_CPX */ /* Define to 1 if the Dylp package is used */ /* #undef COIN_HAS_DYLP */ /* Define to 1 if the Glpk package is used */ /* #undef COIN_HAS_GLPK */ /* Define to 1 if the Mosek package is used */ /* #undef COIN_HAS_MSK */ /* Define to 1 if the Soplex package is used */ /* #undef COIN_HAS_SPX */ /* Define to 1 if the Sym package is used */ /* #undef COIN_HAS_SYM */ /* Define to 1 if the Xpress package is used */ /* #undef COIN_HAS_XPR */ /* For additional information about how to set OSICBC_DFLT_SOLVER, OSICBC_DFLT_SOLVER_CLP, and OSICBC_DFLT_SOLVER_HPP, please see comments at the beginning of OsiCbcSolverInterface.cpp. Unless you know what you're doing, you should use clp with OsiCbc. Just uncomment the next three defines. */ /* Define to the name of the default solver interface class, e.g., OsiClpSolverInterface. */ /* #define OSICBC_DFLT_SOLVER OsiClpSolverInterface */ /* Define this symbol if clp is the default solver. */ /* #define OSICBC_DFLT_SOLVER_CLP 1 */ /* Define to the name of the .hpp file for the default solver interface class, e.g., "OsiClpSolverInterface.hpp" (include quotes) */ /* #define OSICBC_DFLT_SOLVER_HPP "OsiClpSolverInterface.hpp" */ Cbc-2.8.12/src/CbcHeuristicFPump.cpp0000644000076600007660000041301212130022033015546 0ustar coincoin/* $Id: CbcHeuristicFPump.cpp 1883 2013-04-06 13:33:15Z stefan $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #endif #include "CbcMessage.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchDynamic.hpp" #include "CoinHelperFunctions.hpp" #include "CoinWarmStartBasis.hpp" #include "CoinTime.hpp" #include "CbcEventHandler.hpp" // Default Constructor CbcHeuristicFPump::CbcHeuristicFPump() : CbcHeuristic(), startTime_(0.0), maximumTime_(0.0), fakeCutoff_(COIN_DBL_MAX), absoluteIncrement_(0.0), relativeIncrement_(0.0), defaultRounding_(0.49999), initialWeight_(0.0), weightFactor_(0.1), artificialCost_(COIN_DBL_MAX), iterationRatio_(0.0), reducedCostMultiplier_(1.0), maximumPasses_(100), maximumRetries_(1), accumulate_(0), fixOnReducedCosts_(1), roundExpensive_(false) { setWhen(1); } // Constructor from model CbcHeuristicFPump::CbcHeuristicFPump(CbcModel & model, double downValue, bool roundExpensive) : CbcHeuristic(model), startTime_(0.0), maximumTime_(0.0), fakeCutoff_(COIN_DBL_MAX), absoluteIncrement_(0.0), relativeIncrement_(0.0), defaultRounding_(downValue), initialWeight_(0.0), weightFactor_(0.1), artificialCost_(COIN_DBL_MAX), iterationRatio_(0.0), reducedCostMultiplier_(1.0), maximumPasses_(100), maximumRetries_(1), accumulate_(0), fixOnReducedCosts_(1), roundExpensive_(roundExpensive) { setWhen(1); } // Destructor CbcHeuristicFPump::~CbcHeuristicFPump () { } // Clone CbcHeuristic * CbcHeuristicFPump::clone() const { return new CbcHeuristicFPump(*this); } // Create C++ lines to get to current state void CbcHeuristicFPump::generateCpp( FILE * fp) { CbcHeuristicFPump other; fprintf(fp, "0#include \"CbcHeuristicFPump.hpp\"\n"); fprintf(fp, "3 CbcHeuristicFPump heuristicFPump(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicFPump"); if (maximumPasses_ != other.maximumPasses_) fprintf(fp, "3 heuristicFPump.setMaximumPasses(%d);\n", maximumPasses_); else fprintf(fp, "4 heuristicFPump.setMaximumPasses(%d);\n", maximumPasses_); if (maximumRetries_ != other.maximumRetries_) fprintf(fp, "3 heuristicFPump.setMaximumRetries(%d);\n", maximumRetries_); else fprintf(fp, "4 heuristicFPump.setMaximumRetries(%d);\n", maximumRetries_); if (accumulate_ != other.accumulate_) fprintf(fp, "3 heuristicFPump.setAccumulate(%d);\n", accumulate_); else fprintf(fp, "4 heuristicFPump.setAccumulate(%d);\n", accumulate_); if (fixOnReducedCosts_ != other.fixOnReducedCosts_) fprintf(fp, "3 heuristicFPump.setFixOnReducedCosts(%d);\n", fixOnReducedCosts_); else fprintf(fp, "4 heuristicFPump.setFixOnReducedCosts(%d);\n", fixOnReducedCosts_); if (maximumTime_ != other.maximumTime_) fprintf(fp, "3 heuristicFPump.setMaximumTime(%g);\n", maximumTime_); else fprintf(fp, "4 heuristicFPump.setMaximumTime(%g);\n", maximumTime_); if (fakeCutoff_ != other.fakeCutoff_) fprintf(fp, "3 heuristicFPump.setFakeCutoff(%g);\n", fakeCutoff_); else fprintf(fp, "4 heuristicFPump.setFakeCutoff(%g);\n", fakeCutoff_); if (absoluteIncrement_ != other.absoluteIncrement_) fprintf(fp, "3 heuristicFPump.setAbsoluteIncrement(%g);\n", absoluteIncrement_); else fprintf(fp, "4 heuristicFPump.setAbsoluteIncrement(%g);\n", absoluteIncrement_); if (relativeIncrement_ != other.relativeIncrement_) fprintf(fp, "3 heuristicFPump.setRelativeIncrement(%g);\n", relativeIncrement_); else fprintf(fp, "4 heuristicFPump.setRelativeIncrement(%g);\n", relativeIncrement_); if (defaultRounding_ != other.defaultRounding_) fprintf(fp, "3 heuristicFPump.setDefaultRounding(%g);\n", defaultRounding_); else fprintf(fp, "4 heuristicFPump.setDefaultRounding(%g);\n", defaultRounding_); if (initialWeight_ != other.initialWeight_) fprintf(fp, "3 heuristicFPump.setInitialWeight(%g);\n", initialWeight_); else fprintf(fp, "4 heuristicFPump.setInitialWeight(%g);\n", initialWeight_); if (weightFactor_ != other.weightFactor_) fprintf(fp, "3 heuristicFPump.setWeightFactor(%g);\n", weightFactor_); else fprintf(fp, "4 heuristicFPump.setWeightFactor(%g);\n", weightFactor_); if (artificialCost_ != other.artificialCost_) fprintf(fp, "3 heuristicFPump.setArtificialCost(%g);\n", artificialCost_); else fprintf(fp, "4 heuristicFPump.setArtificialCost(%g);\n", artificialCost_); if (iterationRatio_ != other.iterationRatio_) fprintf(fp, "3 heuristicFPump.setIterationRatio(%g);\n", iterationRatio_); else fprintf(fp, "4 heuristicFPump.setIterationRatio(%g);\n", iterationRatio_); if (reducedCostMultiplier_ != other.reducedCostMultiplier_) fprintf(fp, "3 heuristicFPump.setReducedCostMultiplier(%g);\n", reducedCostMultiplier_); else fprintf(fp, "4 heuristicFPump.setReducedCostMultiplier(%g);\n", reducedCostMultiplier_); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicFPump);\n"); } // Copy constructor CbcHeuristicFPump::CbcHeuristicFPump(const CbcHeuristicFPump & rhs) : CbcHeuristic(rhs), startTime_(rhs.startTime_), maximumTime_(rhs.maximumTime_), fakeCutoff_(rhs.fakeCutoff_), absoluteIncrement_(rhs.absoluteIncrement_), relativeIncrement_(rhs.relativeIncrement_), defaultRounding_(rhs.defaultRounding_), initialWeight_(rhs.initialWeight_), weightFactor_(rhs.weightFactor_), artificialCost_(rhs.artificialCost_), iterationRatio_(rhs.iterationRatio_), reducedCostMultiplier_(rhs.reducedCostMultiplier_), maximumPasses_(rhs.maximumPasses_), maximumRetries_(rhs.maximumRetries_), accumulate_(rhs.accumulate_), fixOnReducedCosts_(rhs.fixOnReducedCosts_), roundExpensive_(rhs.roundExpensive_) { } // Assignment operator CbcHeuristicFPump & CbcHeuristicFPump::operator=( const CbcHeuristicFPump & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); startTime_ = rhs.startTime_; maximumTime_ = rhs.maximumTime_; fakeCutoff_ = rhs.fakeCutoff_; absoluteIncrement_ = rhs.absoluteIncrement_; relativeIncrement_ = rhs.relativeIncrement_; defaultRounding_ = rhs.defaultRounding_; initialWeight_ = rhs.initialWeight_; weightFactor_ = rhs.weightFactor_; artificialCost_ = rhs.artificialCost_; iterationRatio_ = rhs.iterationRatio_; reducedCostMultiplier_ = rhs.reducedCostMultiplier_; maximumPasses_ = rhs.maximumPasses_; maximumRetries_ = rhs.maximumRetries_; accumulate_ = rhs.accumulate_; fixOnReducedCosts_ = rhs.fixOnReducedCosts_; roundExpensive_ = rhs.roundExpensive_; } return *this; } // Resets stuff if model changes void CbcHeuristicFPump::resetModel(CbcModel * ) { } /**************************BEGIN MAIN PROCEDURE ***********************************/ // See if feasibility pump will give better solution // Sets value of solution // Returns 1 if solution, 0 if not int CbcHeuristicFPump::solution(double & solutionValue, double * betterSolution) { startTime_ = CoinCpuTime(); numCouldRun_++; double incomingObjective = solutionValue; #define LEN_PRINT 200 char pumpPrint[LEN_PRINT]; pumpPrint[0] = '\0'; /* Decide if we want to run. Standard values for when are described in CbcHeuristic.hpp. If we're off, or running only at root and this isn't the root, bail out. The double test (against phase, then atRoot and passNumber) has a fair bit of redundancy, but the results will differ depending on whether we're actually at the root of the main search tree or at the root of a small tree (recursive call to branchAndBound). FPump also supports some exotic values (11 -- 15) for when, described in CbcHeuristicFPump.hpp. */ if (!when() || (when() == 1 && model_->phase() != 1)) return 0; // switched off // See if at root node bool atRoot = model_->getNodeCount() == 0; int passNumber = model_->getCurrentPassNumber(); // just do once if (!atRoot) return 0; int options = feasibilityPumpOptions_; if ((options % 1000000) > 0) { int kOption = options / 1000000; options = options % 1000000; /* Add 10 to do even if solution 1 - do after cuts 2 - do after cuts (not before) 3 - not used do after every cut round (and after cuts) k not used do after every (k-2)th round */ if (kOption < 10 && model_->getSolutionCount()) return 0; if (model_->getSolutionCount()) kOption = kOption % 10; bool good; if (kOption == 1) { good = (passNumber == 999999); } else if (kOption == 2) { good = (passNumber == 999999); passNumber = 2; // so won't run before //} else if (kOption==3) { //good = true; } else { //good = (((passNumber-1)%(kOption-2))==0); good = false; } if (passNumber != 1 && !good) return 0; } else { if (passNumber != 1) return 0; } // loop round doing repeated pumps double cutoff; model_->solver()->getDblParam(OsiDualObjectiveLimit, cutoff); double direction = model_->solver()->getObjSense(); cutoff *= direction; int numberBandBsolutions = 0; double firstCutoff = fabs(cutoff); cutoff = CoinMin(cutoff, solutionValue); // check plausible and space for rounded solution int numberColumns = model_->getNumCols(); int numberIntegers = model_->numberIntegers(); const int * integerVariableOrig = model_->integerVariable(); double iterationLimit = -1.0; //iterationRatio_=1.0; if (iterationRatio_ > 0.0) iterationLimit = (2 * model_->solver()->getNumRows() + 2 * numberColumns) * iterationRatio_; int totalNumberIterations = 0; int averageIterationsPerTry = -1; int numberIterationsLastPass = 0; // 1. initially check 0-1 /* I'm skeptical of the above comment, but it's likely accurate as the default. Bit 4 or bit 8 needs to be set in order to consider working with general integers. */ int i, j; int general = 0; int * integerVariable = new int[numberIntegers]; const double * lower = model_->solver()->getColLower(); const double * upper = model_->solver()->getColUpper(); bool doGeneral = (accumulate_ & 4) != 0; j = 0; /* Scan the objects, recording the columns and counting general integers. Seems like the NDEBUG tests could be made into an applicability test. If a scan of the objects reveals complex objects, just clean up and return failure. */ for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariableOrig[i]; #ifndef NDEBUG const OsiObject * object = model_->object(i); const CbcSimpleInteger * integerObject = dynamic_cast (object); const OsiSimpleInteger * integerObject2 = dynamic_cast (object); assert(integerObject || integerObject2); #endif if (upper[iColumn] - lower[iColumn] > 1.000001) { general++; if (doGeneral) integerVariable[j++] = iColumn; } else { integerVariable[j++] = iColumn; } } /* If 2/3 of integers are general integers, and we're not going to work with them, might as well go home. The else case is unclear to me. We reach it if general integers are less than 2/3 of the total, or if either of bit 4 or 8 is set. But only bit 8 is used in the decision. (Let manyGen = 1 if more than 2/3 of integers are general integers. Then a k-map on manyGen, bit4, and bit8 shows it clearly.) So there's something odd here. In the case where bit4 = 1 and bit8 = 0, we've included general integers in integerVariable, but we're not going to process them. */ if (general*3 > 2*numberIntegers && !doGeneral) { delete [] integerVariable; return 0; } else if ((accumulate_&4) == 0) { doGeneral = false; j = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariableOrig[i]; if (upper[iColumn] - lower[iColumn] < 1.000001) integerVariable[j++] = iColumn; } } if (!general) doGeneral = false; #ifdef CLP_INVESTIGATE if (doGeneral) printf("DOing general with %d out of %d\n", general, numberIntegers); #endif /* This `closest solution' will satisfy integrality, but violate some other constraints? */ // For solution closest to feasible if none found int * closestSolution = general ? NULL : new int[numberIntegers]; double closestObjectiveValue = COIN_DBL_MAX; int numberIntegersOrig = numberIntegers; numberIntegers = j; double * newSolution = new double [numberColumns]; double newSolutionValue = COIN_DBL_MAX; int maxSolutions = model_->getMaximumSolutions(); int numberSolutions=0; bool solutionFound = false; int * usedColumn = NULL; double * lastSolution = NULL; int fixContinuous = 0; bool fixInternal = false; bool allSlack = false; if (when_ >= 21 && when_ <= 25) { when_ -= 10; allSlack = true; } double time1 = CoinCpuTime(); /* Obtain a relaxed lp solution. */ model_->solver()->resolve(); if (!model_->solver()->isProvenOptimal()) { // presumably max time or some such return 0; } numRuns_++; if (cutoff < 1.0e50 && false) { // Fix on djs double direction = model_->solver()->getObjSense() ; double gap = cutoff - model_->solver()->getObjValue() * direction ; double tolerance; model_->solver()->getDblParam(OsiDualTolerance, tolerance) ; if (gap > 0.0) { gap += 100.0 * tolerance; int nFix = model_->solver()->reducedCostFix(gap); printf("dj fixing fixed %d variables\n", nFix); } } /* I have no idea why we're doing this, except perhaps that saveBasis will be automagically deleted on exit from the routine. */ CoinWarmStartBasis saveBasis; CoinWarmStartBasis * basis = dynamic_cast(model_->solver()->getWarmStart()) ; if (basis) { saveBasis = * basis; delete basis; } double continuousObjectiveValue = model_->solver()->getObjValue() * model_->solver()->getObjSense(); double * firstPerturbedObjective = NULL; double * firstPerturbedSolution = NULL; double firstPerturbedValue = COIN_DBL_MAX; if (when_ >= 11 && when_ <= 15) { fixInternal = when_ > 11 && when_ < 15; if (when_ < 13) fixContinuous = 0; else if (when_ != 14) fixContinuous = 1; else fixContinuous = 2; when_ = 1; if ((accumulate_&1) != 0) { usedColumn = new int [numberColumns]; for (int i = 0; i < numberColumns; i++) usedColumn[i] = -1; } lastSolution = CoinCopyOfArray(model_->solver()->getColSolution(), numberColumns); } int finalReturnCode = 0; int totalNumberPasses = 0; int numberTries = 0; CoinWarmStartBasis bestBasis; bool exitAll = false; //double saveBestObjective = model_->getMinimizationObjValue(); OsiSolverInterface * solver = NULL; double artificialFactor = 0.00001; // also try rounding! double * roundingSolution = new double[numberColumns]; double roundingObjective = solutionValue; CbcRounding roundingHeuristic(*model_); int dualPass = 0; int secondPassOpt = 0; #define RAND_RAND #ifdef RAND_RAND int offRandom = 0; #endif int maximumAllowed = -1; bool moreIterations = false; if (options > 0) { if (options >= 1000) maximumAllowed = options / 1000; int options2 = (options % 1000) / 100; #ifdef RAND_RAND offRandom = options2 & 1; #endif moreIterations = (options2 & 2) != 0; secondPassOpt = (options / 10) % 10; /* 1 to 7 - re-use solution 8 use dual and current solution(ish) 9 use dual and allslack 1 - primal and mod obj 2 - dual and mod obj 3 - primal and no mod obj add 3 to redo current solution */ if (secondPassOpt >= 8) { dualPass = secondPassOpt - 7; secondPassOpt = 0; } } // Number of passes to do int maximumPasses = maximumPasses_; #ifdef COIN_HAS_CLP { OsiClpSolverInterface * clpSolver = dynamic_cast (model_->solver()); if (clpSolver ) { if (maximumPasses == 30) { if (clpSolver->fakeObjective()) maximumPasses = 100; // feasibility problem? } randomNumberGenerator_.randomize(); if (model_->getRandomSeed()!=-1) clpSolver->getModelPtr()->setRandomSeed(randomNumberGenerator_.getSeed()); clpSolver->getModelPtr()->randomNumberGenerator()->randomize(); } } #endif #ifdef RAND_RAND double * randomFactor = new double [numberColumns]; for (int i = 0; i < numberColumns; i++) { double value = floor(1.0e3 * randomNumberGenerator_.randomDouble()); randomFactor[i] = 1.0 + value * 1.0e-4; } #endif // guess exact multiple of objective double exactMultiple = model_->getCutoffIncrement(); exactMultiple *= 2520; if (fabs(exactMultiple / 0.999 - floor(exactMultiple / 0.999 + 0.5)) < 1.0e-9) exactMultiple /= 2520.0 * 0.999; else if (fabs(exactMultiple - floor(exactMultiple + 0.5)) < 1.0e-9) exactMultiple /= 2520.0; else exactMultiple = 0.0; // check for rounding errors (only for integral case) if (fabs(exactMultiple - floor(exactMultiple + 0.5)) < 1.0e-8) exactMultiple = floor(exactMultiple + 0.5); //printf("exact multiple %g\n",exactMultiple); // Clone solver for rounding OsiSolverInterface * clonedSolver = cloneBut(2); // wasmodel_->solver()->clone(); while (!exitAll) { // Cutoff rhs double useRhs = COIN_DBL_MAX; double useOffset = 0.0; int numberPasses = 0; artificialFactor *= 10.0; int lastMove = (!numberTries) ? -10 : 1000000; double lastSumInfeas = COIN_DBL_MAX; numberTries++; // Clone solver - otherwise annoys root node computations solver = cloneBut(2); // was model_->solver()->clone(); #ifdef COIN_HAS_CLP { OsiClpSolverInterface * clpSolver = dynamic_cast (solver); if (clpSolver) { // better to clean up using primal? ClpSimplex * lp = clpSolver->getModelPtr(); int options = lp->specialOptions(); lp->setSpecialOptions(options | 8192); //lp->setSpecialOptions(options|0x01000000); #ifdef CLP_INVESTIGATE clpSolver->setHintParam(OsiDoReducePrint, false, OsiHintTry); lp->setLogLevel(CoinMax(1, lp->logLevel())); #endif } } #endif if (CoinMin(fakeCutoff_, cutoff) < 1.0e50) { // Fix on djs double direction = solver->getObjSense() ; double gap = CoinMin(fakeCutoff_, cutoff) - solver->getObjValue() * direction ; double tolerance; solver->getDblParam(OsiDualTolerance, tolerance) ; if (gap > 0.0 && (fixOnReducedCosts_ == 1 || (numberTries == 1 && fixOnReducedCosts_ == 2))) { gap += 100.0 * tolerance; gap *= reducedCostMultiplier_; int nFix = solver->reducedCostFix(gap); if (nFix) { sprintf(pumpPrint, "Reduced cost fixing fixed %d variables on major pass %d", nFix, numberTries); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; //pumpPrint[0]='\0'; } } } // if cutoff exists then add constraint bool useCutoff = (fabs(cutoff) < 1.0e20 && (fakeCutoff_ != COIN_DBL_MAX || numberTries > 1)); // but there may be a close one if (firstCutoff < 2.0*solutionValue && numberTries == 1 && CoinMin(cutoff, fakeCutoff_) < 1.0e20) useCutoff = true; if (useCutoff) { double rhs = CoinMin(cutoff, fakeCutoff_); const double * objective = solver->getObjCoefficients(); int numberColumns = solver->getNumCols(); int * which = new int[numberColumns]; double * els = new double[numberColumns]; int nel = 0; for (int i = 0; i < numberColumns; i++) { double value = objective[i]; if (value) { which[nel] = i; els[nel++] = direction * value; } } solver->getDblParam(OsiObjOffset, useOffset); #ifdef COIN_DEVELOP if (useOffset) printf("CbcHeuristicFPump obj offset %g\n", useOffset); #endif useOffset *= direction; // Tweak rhs and save useRhs = rhs; #ifdef JJF_ZERO double tempValue = 60.0 * useRhs; if (fabs(tempValue - floor(tempValue + 0.5)) < 1.0e-7 && rhs != fakeCutoff_) { // add a little useRhs += 1.0e-5; } #endif solver->addRow(nel, which, els, -COIN_DBL_MAX, useRhs + useOffset); delete [] which; delete [] els; bool takeHint; OsiHintStrength strength; solver->getHintParam(OsiDoDualInResolve, takeHint, strength); solver->setHintParam(OsiDoDualInResolve, true, OsiHintDo); solver->resolve(); solver->setHintParam(OsiDoDualInResolve, takeHint, strength); if (!solver->isProvenOptimal()) { // presumably max time or some such exitAll = true; break; } } solver->setDblParam(OsiDualObjectiveLimit, 1.0e50); solver->resolve(); // Solver may not be feasible if (!solver->isProvenOptimal()) { exitAll = true; break; } const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * solution = solver->getColSolution(); if (lastSolution) memcpy(lastSolution, solution, numberColumns*sizeof(double)); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // 2 space for last rounded solutions #define NUMBER_OLD 4 double ** oldSolution = new double * [NUMBER_OLD]; for (j = 0; j < NUMBER_OLD; j++) { oldSolution[j] = new double[numberColumns]; for (i = 0; i < numberColumns; i++) oldSolution[j][i] = -COIN_DBL_MAX; } // 3. Replace objective with an initial 0-valued objective double * saveObjective = new double [numberColumns]; memcpy(saveObjective, solver->getObjCoefficients(), numberColumns*sizeof(double)); for (i = 0; i < numberColumns; i++) { solver->setObjCoeff(i, 0.0); } bool finished = false; double direction = solver->getObjSense(); int returnCode = 0; bool takeHint; OsiHintStrength strength; solver->getHintParam(OsiDoDualInResolve, takeHint, strength); solver->setHintParam(OsiDoDualInResolve, false); //solver->messageHandler()->setLogLevel(0); // 4. Save objective offset so we can see progress double saveOffset; solver->getDblParam(OsiObjOffset, saveOffset); // Get amount for original objective double scaleFactor = 0.0; #ifdef COIN_DEVELOP double largestCost = 0.0; int nArtificial = 0; #endif for (i = 0; i < numberColumns; i++) { double value = saveObjective[i]; scaleFactor += value * value; #ifdef COIN_DEVELOP largestCost = CoinMax(largestCost, fabs(value)); if (value*direction >= artificialCost_) nArtificial++; #endif } if (scaleFactor) scaleFactor = (initialWeight_ * sqrt(static_cast (numberIntegers))) / sqrt(scaleFactor); #ifdef CLP_INVESTIGATE #ifdef COIN_DEVELOP if (scaleFactor || nArtificial) printf("Using %g fraction of original objective (decay %g) - largest %g - %d artificials\n", scaleFactor, weightFactor_, largestCost, nArtificial); #else if (scaleFactor) printf("Using %g fraction of original objective (decay %g)\n", scaleFactor, weightFactor_); #endif #endif // This is an array of sums of infeasibilities so can see if "bobbling" #define SIZE_BOBBLE 20 double saveSumInf[SIZE_BOBBLE]; CoinFillN(saveSumInf, SIZE_BOBBLE, COIN_DBL_MAX); // 0 before doing anything int bobbleMode = 0; // 5. MAIN WHILE LOOP //bool newLineNeeded=false; /* finished occurs exactly twice in this routine: immediately above, where it's set to false, and here in the loop condition. */ while (!finished) { double newTrueSolutionValue = 0.0; double newSumInfeas = 0.0; int newNumberInfeas = 0; returnCode = 0; if (model_->maximumSecondsReached()) { exitAll = true; break; } // see what changed if (usedColumn) { for (i = 0; i < numberColumns; i++) { if (fabs(solution[i] - lastSolution[i]) > 1.0e-8) usedColumn[i] = numberPasses; lastSolution[i] = solution[i]; } } if (averageIterationsPerTry >= 0) { int n = totalNumberIterations - numberIterationsLastPass; double perPass = totalNumberIterations / (totalNumberPasses + numberPasses + 1.0e-5); perPass /= (solver->getNumRows() + numberColumns); double test = moreIterations ? 0.3 : 0.05; if (n > CoinMax(20000, 3*averageIterationsPerTry) && (switches_&2) == 0 && maximumPasses<200 && perPass>test) { exitAll = true; } } // Exit on exact total number if maximumPasses large if ((maximumPasses >= 200 || (switches_&2) != 0) && numberPasses + totalNumberPasses >= maximumPasses) exitAll = true; bool exitThis = false; if (iterationLimit < 0.0) { if (numberPasses >= maximumPasses) { // If going well then keep going if maximumPasses small if (lastMove < numberPasses - 4 || lastMove == 1000000) exitThis = true; if (maximumPasses > 20 || numberPasses >= 40) exitThis = true; } } if (iterationLimit > 0.0 && totalNumberIterations > iterationLimit && numberPasses > 15) { // exiting on iteration count exitAll = true; } else if (maximumPasses<30 && numberPasses>100) { // too many passes anyway exitAll = true; } if (maximumTime_ > 0.0 && CoinCpuTime() >= startTime_ + maximumTime_) { exitAll = true; // force exit switches_ |= 2048; } if (exitAll || exitThis) break; memcpy(newSolution, solution, numberColumns*sizeof(double)); int flip; if (numberPasses == 0 && false) { // always use same seed randomNumberGenerator_.setSeed(987654321); } returnCode = rounds(solver, newSolution,/*saveObjective,*/ numberIntegers, integerVariable, /*pumpPrint,*/numberPasses, /*roundExpensive_,*/defaultRounding_, &flip); if (numberPasses == 0 && false) { // Make sure random will be different for (i = 1; i < numberTries; i++) randomNumberGenerator_.randomDouble(); } numberPasses++; if (returnCode) { // SOLUTION IS INTEGER // Put back correct objective for (i = 0; i < numberColumns; i++) solver->setObjCoeff(i, saveObjective[i]); // solution - but may not be better // Compute using dot product solver->setDblParam(OsiObjOffset, saveOffset); newSolutionValue = -saveOffset; for ( i = 0 ; i < numberColumns ; i++ ) newSolutionValue += saveObjective[i] * newSolution[i]; newSolutionValue *= direction; sprintf(pumpPrint, "Solution found of %g", newSolutionValue); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; //newLineNeeded=false; if (newSolutionValue < solutionValue) { double saveValue = solutionValue; if (!doGeneral) { int numberLeft = 0; for (i = 0; i < numberIntegersOrig; i++) { int iColumn = integerVariableOrig[i]; double value = floor(newSolution[iColumn] + 0.5); if (solver->isBinary(iColumn)) { solver->setColLower(iColumn, value); solver->setColUpper(iColumn, value); } else { if (fabs(value - newSolution[iColumn]) > 1.0e-7) numberLeft++; } } if (numberLeft) { sprintf(pumpPrint, "Branch and bound needed to clear up %d general integers", numberLeft); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; returnCode = smallBranchAndBound(solver, numberNodes_, newSolution, newSolutionValue, solutionValue, "CbcHeuristicFpump"); if (returnCode < 0) { if (returnCode == -2) exitAll = true; returnCode = 0; // returned on size or event } if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } if (returnCode != 1) newSolutionValue = saveValue; if (returnCode && newSolutionValue < saveValue) numberBandBsolutions++; } } if (returnCode && newSolutionValue < saveValue) { memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); solutionFound = true; if (exitNow(newSolutionValue)) exitAll = true; CoinWarmStartBasis * basis = dynamic_cast(solver->getWarmStart()) ; if (basis) { bestBasis = * basis; delete basis; int action = model_->dealWithEventHandler(CbcEventHandler::heuristicSolution, newSolutionValue, betterSolution); if (action == 0) { double * saveOldSolution = CoinCopyOfArray(model_->bestSolution(), numberColumns); double saveObjectiveValue = model_->getMinimizationObjValue(); model_->setBestSolution(betterSolution, numberColumns, newSolutionValue); if (saveOldSolution && saveObjectiveValue < model_->getMinimizationObjValue()) model_->setBestSolution(saveOldSolution, numberColumns, saveObjectiveValue); delete [] saveOldSolution; } if (action == 0 || model_->maximumSecondsReached()) { exitAll = true; // exit break; } } if ((accumulate_&1) != 0) { model_->incrementUsed(betterSolution); // for local search } solutionValue = newSolutionValue; solutionFound = true; numberSolutions++; if (numberSolutions>=maxSolutions) exitAll = true; if (general && saveValue != newSolutionValue) { sprintf(pumpPrint, "Cleaned solution of %g", solutionValue); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; } if (exitNow(newSolutionValue)) exitAll = true; } else { sprintf(pumpPrint, "Mini branch and bound could not fix general integers"); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; } } else { sprintf(pumpPrint, "After further testing solution no better than previous of %g", solutionValue); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; //newLineNeeded=false; returnCode = 0; } break; } else { // SOLUTION IS not INTEGER // 1. check for loop bool matched; for (int k = NUMBER_OLD - 1; k > 0; k--) { double * b = oldSolution[k]; matched = true; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (newSolution[iColumn] != b[iColumn]) { matched = false; break; } } if (matched) break; } int numberPerturbed = 0; if (matched || numberPasses % 100 == 0) { // perturbation //sprintf(pumpPrint+strlen(pumpPrint)," perturbation applied"); //newLineNeeded=true; double factorX[10] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; double factor = 1.0; double target = -1.0; double * randomX = new double [numberIntegers]; for (i = 0; i < numberIntegers; i++) randomX[i] = CoinMax(0.0, randomNumberGenerator_.randomDouble() - 0.3); for (int k = 0; k < 10; k++) { #ifdef COIN_DEVELOP_x printf("kpass %d\n", k); #endif int numberX[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = randomX[i]; double difference = fabs(solution[iColumn] - newSolution[iColumn]); for (int j = 0; j < 10; j++) { if (difference + value*factorX[j] > 0.5) numberX[j]++; } } if (target < 0.0) { if (numberX[9] <= 200) break; // not very many changes target = CoinMax(200.0, CoinMin(0.05 * numberX[9], 1000.0)); } int iX = -1; int iBand = -1; for (i = 0; i < 10; i++) { #ifdef COIN_DEVELOP_x printf("** %d changed at %g\n", numberX[i], factorX[i]); #endif if (numberX[i] >= target && numberX[i] < 2.0*target && iX < 0) iX = i; if (iBand<0 && numberX[i]>target) { iBand = i; factor = factorX[i]; } } if (iX >= 0) { factor = factorX[iX]; break; } else { assert (iBand >= 0); double hi = factor; double lo = (iBand > 0) ? factorX[iBand-1] : 0.0; double diff = (hi - lo) / 9.0; for (i = 0; i < 10; i++) { factorX[i] = lo; lo += diff; } } } for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = randomX[i]; double difference = fabs(solution[iColumn] - newSolution[iColumn]); if (difference + value*factor > 0.5) { numberPerturbed++; if (newSolution[iColumn] < lower[iColumn] + primalTolerance) { newSolution[iColumn] += 1.0; } else if (newSolution[iColumn] > upper[iColumn] - primalTolerance) { newSolution[iColumn] -= 1.0; } else { // general integer if (difference + value > 0.75) newSolution[iColumn] += 1.0; else newSolution[iColumn] -= 1.0; } } } delete [] randomX; } else { for (j = NUMBER_OLD - 1; j > 0; j--) { for (i = 0; i < numberColumns; i++) oldSolution[j][i] = oldSolution[j-1][i]; } for (j = 0; j < numberColumns; j++) oldSolution[0][j] = newSolution[j]; } // 2. update the objective function based on the new rounded solution double offset = 0.0; double costValue = (1.0 - scaleFactor) * solver->getObjSense(); int numberChanged = 0; const double * oldObjective = solver->getObjCoefficients(); for (i = 0; i < numberColumns; i++) { // below so we can keep original code and allow for objective int iColumn = i; // Special code for "artificials" if (direction*saveObjective[iColumn] >= artificialCost_) { //solver->setObjCoeff(iColumn,scaleFactor*saveObjective[iColumn]); solver->setObjCoeff(iColumn, (artificialFactor*saveObjective[iColumn]) / artificialCost_); } if (!solver->isBinary(iColumn) && !doGeneral) continue; // deal with fixed variables (i.e., upper=lower) if (fabs(lower[iColumn] - upper[iColumn]) < primalTolerance || !solver->isInteger(iColumn)) { //if (lower[iColumn] > 1. - primalTolerance) solver->setObjCoeff(iColumn,-costValue); //else solver->setObjCoeff(iColumn,costValue); continue; } double newValue = 0.0; if (newSolution[iColumn] < lower[iColumn] + primalTolerance) { newValue = costValue + scaleFactor * saveObjective[iColumn]; } else { if (newSolution[iColumn] > upper[iColumn] - primalTolerance) { newValue = -costValue + scaleFactor * saveObjective[iColumn]; } } #ifdef RAND_RAND if (!offRandom) newValue *= randomFactor[iColumn]; #endif if (newValue != oldObjective[iColumn]) { numberChanged++; } solver->setObjCoeff(iColumn, newValue); offset += costValue * newSolution[iColumn]; } if (numberPasses==1 && !totalNumberPasses && (model_->specialOptions()&8388608)!=0) { // doing multiple solvers - make a real difference - flip 5% for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = floor(newSolution[iColumn]+0.5); if (fabs(value-solution[iColumn])>primalTolerance) { value = randomNumberGenerator_.randomDouble(); if(value<0.05) { //printf("Flipping %d - random %g\n",iColumn,value); solver->setObjCoeff(iColumn,-solver->getObjCoefficients()[iColumn]); } } } } solver->setDblParam(OsiObjOffset, -offset); if (!general && false) { // Solve in two goes - first keep satisfied ones fixed double * saveLower = new double [numberIntegers]; double * saveUpper = new double [numberIntegers]; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; saveLower[i] = COIN_DBL_MAX; saveUpper[i] = -COIN_DBL_MAX; if (solution[iColumn] < lower[iColumn] + primalTolerance) { saveUpper[i] = upper[iColumn]; solver->setColUpper(iColumn, lower[iColumn]); } else if (solution[iColumn] > upper[iColumn] - primalTolerance) { saveLower[i] = lower[iColumn]; solver->setColLower(iColumn, upper[iColumn]); } } solver->resolve(); if (!solver->isProvenOptimal()) { // presumably max time or some such exitAll = true; break; } for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (saveLower[i] != COIN_DBL_MAX) solver->setColLower(iColumn, saveLower[i]); if (saveUpper[i] != -COIN_DBL_MAX) solver->setColUpper(iColumn, saveUpper[i]); saveUpper[i] = -COIN_DBL_MAX; } memcpy(newSolution, solution, numberColumns*sizeof(double)); int flip; returnCode = rounds(solver, newSolution,/*saveObjective,*/ numberIntegers, integerVariable, /*pumpPrint,*/numberPasses, /*roundExpensive_,*/defaultRounding_, &flip); numberPasses++; if (returnCode) { // solution - but may not be better // Compute using dot product double newSolutionValue = -saveOffset; for ( i = 0 ; i < numberColumns ; i++ ) newSolutionValue += saveObjective[i] * newSolution[i]; newSolutionValue *= direction; sprintf(pumpPrint, "Intermediate solution found of %g", newSolutionValue); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; if (newSolutionValue < solutionValue) { memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); CoinWarmStartBasis * basis = dynamic_cast(solver->getWarmStart()) ; solutionFound = true; numberSolutions++; if (numberSolutions>=maxSolutions) exitAll = true; if (exitNow(newSolutionValue)) exitAll = true; if (basis) { bestBasis = * basis; delete basis; int action = model_->dealWithEventHandler(CbcEventHandler::heuristicSolution, newSolutionValue, betterSolution); if (!action) { double * saveOldSolution = CoinCopyOfArray(model_->bestSolution(), numberColumns); double saveObjectiveValue = model_->getMinimizationObjValue(); model_->setBestSolution(betterSolution, numberColumns, newSolutionValue); if (saveOldSolution && saveObjectiveValue < model_->getMinimizationObjValue()) model_->setBestSolution(saveOldSolution, numberColumns, saveObjectiveValue); delete [] saveOldSolution; } if (!action || model_->maximumSecondsReached()) { exitAll = true; // exit break; } } if ((accumulate_&1) != 0) { model_->incrementUsed(betterSolution); // for local search } solutionValue = newSolutionValue; solutionFound = true; numberSolutions++; if (numberSolutions>=maxSolutions) exitAll = true; if (exitNow(newSolutionValue)) exitAll = true; } else { returnCode = 0; } } } int numberIterations = 0; if (!doGeneral) { // faster to do from all slack!!!! if (allSlack) { CoinWarmStartBasis dummy; solver->setWarmStart(&dummy); } #ifdef COIN_DEVELOP printf("%d perturbed out of %d columns (%d changed)\n", numberPerturbed, numberColumns, numberChanged); #endif bool takeHint; OsiHintStrength strength; solver->getHintParam(OsiDoDualInResolve, takeHint, strength); if (dualPass && numberChanged > 2) { solver->setHintParam(OsiDoDualInResolve, true); // dual may be better if (dualPass == 1 && 2*numberChanged < numberColumns && (numberChanged < 5000 || 6*numberChanged < numberColumns)) { // but we need to make infeasible CoinWarmStartBasis * basis = dynamic_cast(solver->getWarmStart()) ; if (basis) { // modify const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double * solution = CoinCopyOfArray(solver->getColSolution(), numberColumns); const double * objective = solver->getObjCoefficients(); int nChanged = 0; for (i = 0; i < numberIntegersOrig; i++) { int iColumn = integerVariableOrig[i]; #ifdef RAND_RAND if (nChanged > numberChanged) break; #endif if (objective[iColumn] > 0.0) { if (basis->getStructStatus(iColumn) == CoinWarmStartBasis::atUpperBound) { solution[iColumn] = lower[iColumn]; basis->setStructStatus(iColumn, CoinWarmStartBasis::atLowerBound); nChanged++; } } else if (objective[iColumn] < 0.0) { if (basis->getStructStatus(iColumn) == CoinWarmStartBasis::atLowerBound) { solution[iColumn] = upper[iColumn]; basis->setStructStatus(iColumn, CoinWarmStartBasis::atUpperBound); nChanged++; } } } if (!nChanged) { for (i = 0; i < numberIntegersOrig; i++) { int iColumn = integerVariableOrig[i]; if (objective[iColumn] > 0.0) { if (basis->getStructStatus(iColumn) == CoinWarmStartBasis::basic) { solution[iColumn] = lower[iColumn]; basis->setStructStatus(iColumn, CoinWarmStartBasis::atLowerBound); break; } } else if (objective[iColumn] < 0.0) { if (basis->getStructStatus(iColumn) == CoinWarmStartBasis::basic) { solution[iColumn] = upper[iColumn]; basis->setStructStatus(iColumn, CoinWarmStartBasis::atUpperBound); break; } } } } solver->setColSolution(solution); delete [] solution; solver->setWarmStart(basis); delete basis; } } else { // faster to do from all slack!!!! ??? CoinWarmStartBasis dummy; solver->setWarmStart(&dummy); } } if (numberTries > 1 && numberPasses == 1 && firstPerturbedObjective) { // Modify to use convex combination // use basis from first time solver->setWarmStart(&saveBasis); // and objective if (secondPassOpt < 3 || (secondPassOpt >= 4 && secondPassOpt < 6)) solver->setObjective(firstPerturbedObjective); // and solution solver->setColSolution(firstPerturbedSolution); //if (secondPassOpt==2||secondPassOpt==5|| if (firstPerturbedValue > cutoff) solver->setHintParam(OsiDoDualInResolve, true); // dual may be better } solver->resolve(); if (!solver->isProvenOptimal()) { // presumably max time or some such exitAll = true; break; } solver->setHintParam(OsiDoDualInResolve, takeHint); newTrueSolutionValue = -saveOffset; newSumInfeas = 0.0; newNumberInfeas = 0; { const double * newSolution = solver->getColSolution(); for ( i = 0 ; i < numberColumns ; i++ ) { if (solver->isInteger(i)) { double value = newSolution[i]; double nearest = floor(value + 0.5); newSumInfeas += fabs(value - nearest); if (fabs(value - nearest) > 1.0e-6) newNumberInfeas++; } newTrueSolutionValue += saveObjective[i] * newSolution[i]; } newTrueSolutionValue *= direction; if (numberPasses == 1 && secondPassOpt) { if (numberTries == 1 || secondPassOpt > 3) { // save basis CoinWarmStartBasis * basis = dynamic_cast(solver->getWarmStart()) ; if (basis) { saveBasis = * basis; delete basis; } delete [] firstPerturbedObjective; delete [] firstPerturbedSolution; firstPerturbedObjective = CoinCopyOfArray(solver->getObjCoefficients(), numberColumns); firstPerturbedSolution = CoinCopyOfArray(solver->getColSolution(), numberColumns); firstPerturbedValue = newTrueSolutionValue; } } if (newNumberInfeas && newNumberInfeas < 15) { #ifdef JJF_ZERO roundingObjective = solutionValue; OsiSolverInterface * saveSolver = model_->swapSolver(solver); double * currentObjective = CoinCopyOfArray(solver->getObjCoefficients(), numberColumns); solver->setObjective(saveObjective); double saveOffset2; solver->getDblParam(OsiObjOffset, saveOffset2); solver->setDblParam(OsiObjOffset, saveOffset); int ifSol = roundingHeuristic.solution(roundingObjective, roundingSolution); solver->setObjective(currentObjective); solver->setDblParam(OsiObjOffset, saveOffset2); delete [] currentObjective; model_->swapSolver(saveSolver); if (ifSol > 0) abort(); #endif int numberRows = solver->getNumRows(); double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); int * which = new int[newNumberInfeas]; int * stack = new int[newNumberInfeas+1]; double * baseValue = new double[newNumberInfeas]; int * whichRow = new int[numberRows]; double * rowValue = new double[numberRows]; memset(rowValue, 0, numberRows*sizeof(double)); int nRow = 0; // Column copy const double * element = solver->getMatrixByCol()->getElements(); const int * row = solver->getMatrixByCol()->getIndices(); const CoinBigIndex * columnStart = solver->getMatrixByCol()->getVectorStarts(); const int * columnLength = solver->getMatrixByCol()->getVectorLengths(); int n = 0; double contrib = 0.0; for ( i = 0 ; i < numberColumns ; i++ ) { double value = newSolution[i]; if (solver->isInteger(i)) { double nearest = floor(value + 0.5); if (fabs(value - nearest) > 1.0e-6) { //printf("Column %d value %g\n",i,value); for (CoinBigIndex j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; //printf("row %d element %g\n",iRow,element[j]); if (!rowValue[iRow]) { rowValue[iRow] = 1.0; whichRow[nRow++] = iRow; } } baseValue[n] = floor(value); contrib += saveObjective[i] * value; value = 0.0; stack[n] = 0; which[n++] = i; } } for (CoinBigIndex j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } if (newNumberInfeas < 15) { stack[n] = newNumberInfeas + 100; int iStack = n; memset(rowValue, 0, numberRows*sizeof(double)); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); while (iStack >= 0) { double contrib2 = 0.0; // Could do faster for (int k = 0 ; k < n ; k++ ) { i = which[k]; double value = baseValue[k] + stack[k]; contrib2 += saveObjective[i] * value; for (CoinBigIndex j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowValue[iRow] += value * element[j]; } } // check if feasible bool feasible = true; for (int k = 0; k < nRow; k++) { i = whichRow[k]; double value = rowValue[i] + rowActivity[i]; rowValue[i] = 0.0; if (value < rowLower[i] - 1.0e-7 || value > rowUpper[i] + 1.0e-7) feasible = false; } if (feasible) { double newObj = newTrueSolutionValue * direction; newObj += contrib2 - contrib; newObj *= direction; #ifdef COIN_DEVELOP printf("FFFeasible! - obj %g\n", newObj); #endif if (newObj < roundingObjective - 1.0e-6) { #ifdef COIN_DEVELOP printf("FBetter\n"); #endif roundingObjective = newObj; memcpy(roundingSolution, newSolution, numberColumns*sizeof(double)); for (int k = 0 ; k < n ; k++ ) { i = which[k]; double value = baseValue[k] + stack[k]; roundingSolution[i] = value; } } } while (iStack >= 0 && stack[iStack]) { stack[iStack]--; iStack--; } if (iStack >= 0) { stack[iStack] = 1; iStack = n; stack[n] = 1; } } } delete [] rowActivity; delete [] which; delete [] stack; delete [] baseValue; delete [] whichRow; delete [] rowValue; } } if (true) { OsiSolverInterface * saveSolver = model_->swapSolver(clonedSolver); clonedSolver->setColSolution(solver->getColSolution()); CbcRounding heuristic1(*model_); heuristic1.setHeuristicName("rounding in feaspump!"); heuristic1.setWhen(1); roundingObjective = CoinMin(roundingObjective, solutionValue); double testSolutionValue = newTrueSolutionValue; int returnCode = heuristic1.solution(roundingObjective, roundingSolution, testSolutionValue) ; if (returnCode == 1) { #ifdef COIN_DEVELOP printf("rounding obj of %g?\n", roundingObjective); #endif //roundingObjective = newSolutionValue; //} else { //roundingObjective = COIN_DBL_MAX; } model_->swapSolver(saveSolver); } if (!solver->isProvenOptimal()) { // presumably max time or some such exitAll = true; break; } // in case very dubious solver lower = solver->getColLower(); upper = solver->getColUpper(); solution = solver->getColSolution(); numberIterations = solver->getIterationCount(); } else { int * addStart = new int[2*general+1]; int * addIndex = new int[4*general]; double * addElement = new double[4*general]; double * addLower = new double[2*general]; double * addUpper = new double[2*general]; double * obj = new double[general]; int nAdd = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (newSolution[iColumn] > lower[iColumn] + primalTolerance && newSolution[iColumn] < upper[iColumn] - primalTolerance) { assert (upper[iColumn] - lower[iColumn] > 1.00001); obj[nAdd] = 1.0; addLower[nAdd] = 0.0; addUpper[nAdd] = COIN_DBL_MAX; nAdd++; } } OsiSolverInterface * solver2 = solver; if (nAdd) { CoinZeroN(addStart, nAdd + 1); solver2 = solver->clone(); solver2->addCols(nAdd, addStart, NULL, NULL, addLower, addUpper, obj); // feasible solution double * sol = new double[nAdd+numberColumns]; memcpy(sol, solution, numberColumns*sizeof(double)); // now rows int nAdd = 0; int nEl = 0; int nAddRow = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (newSolution[iColumn] > lower[iColumn] + primalTolerance && newSolution[iColumn] < upper[iColumn] - primalTolerance) { addLower[nAddRow] = -newSolution[iColumn];; addUpper[nAddRow] = COIN_DBL_MAX; addIndex[nEl] = iColumn; addElement[nEl++] = -1.0; addIndex[nEl] = numberColumns + nAdd; addElement[nEl++] = 1.0; nAddRow++; addStart[nAddRow] = nEl; addLower[nAddRow] = newSolution[iColumn];; addUpper[nAddRow] = COIN_DBL_MAX; addIndex[nEl] = iColumn; addElement[nEl++] = 1.0; addIndex[nEl] = numberColumns + nAdd; addElement[nEl++] = 1.0; nAddRow++; addStart[nAddRow] = nEl; sol[nAdd+numberColumns] = fabs(sol[iColumn] - newSolution[iColumn]); nAdd++; } } solver2->setColSolution(sol); delete [] sol; solver2->addRows(nAddRow, addStart, addIndex, addElement, addLower, addUpper); } delete [] addStart; delete [] addIndex; delete [] addElement; delete [] addLower; delete [] addUpper; delete [] obj; solver2->resolve(); if (!solver2->isProvenOptimal()) { // presumably max time or some such exitAll = true; break; } //assert (solver2->isProvenOptimal()); if (nAdd) { solver->setColSolution(solver2->getColSolution()); numberIterations = solver2->getIterationCount(); delete solver2; } else { numberIterations = solver->getIterationCount(); } lower = solver->getColLower(); upper = solver->getColUpper(); solution = solver->getColSolution(); newTrueSolutionValue = -saveOffset; newSumInfeas = 0.0; newNumberInfeas = 0; { const double * newSolution = solver->getColSolution(); for ( i = 0 ; i < numberColumns ; i++ ) { if (solver->isInteger(i)) { double value = newSolution[i]; double nearest = floor(value + 0.5); newSumInfeas += fabs(value - nearest); if (fabs(value - nearest) > 1.0e-6) newNumberInfeas++; } newTrueSolutionValue += saveObjective[i] * newSolution[i]; } newTrueSolutionValue *= direction; } } if (lastMove != 1000000) { if (newSumInfeas < lastSumInfeas) { lastMove = numberPasses; lastSumInfeas = newSumInfeas; } else if (newSumInfeas > lastSumInfeas + 1.0e-5) { lastMove = 1000000; // going up } } totalNumberIterations += numberIterations; if (solver->getNumRows() < 3000) sprintf(pumpPrint, "Pass %3d: suminf. %10.5f (%d) obj. %g iterations %d", numberPasses + totalNumberPasses, newSumInfeas, newNumberInfeas, newTrueSolutionValue, numberIterations); else sprintf(pumpPrint, "Pass %3d: (%.2f seconds) suminf. %10.5f (%d) obj. %g iterations %d", numberPasses + totalNumberPasses, model_->getCurrentSeconds(), newSumInfeas, newNumberInfeas, newTrueSolutionValue, numberIterations); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; if (closestSolution && solver->getObjValue() < closestObjectiveValue) { int i; const double * objective = solver->getObjCoefficients(); for (i = 0; i < numberIntegersOrig; i++) { int iColumn = integerVariableOrig[i]; if (objective[iColumn] > 0.0) closestSolution[i] = 0; else closestSolution[i] = 1; } closestObjectiveValue = solver->getObjValue(); } // See if we need to think about changing rhs if ((switches_&12) != 0 && useRhs < 1.0e50) { double oldRhs = useRhs; bool trying = false; if ((switches_&4) != 0 && numberPasses && (numberPasses % 50) == 0) { if (solutionValue > 1.0e20) { // only if no genuine solution double gap = useRhs - continuousObjectiveValue; useRhs += 0.1 * gap; if (exactMultiple) { useRhs = exactMultiple * ceil(useRhs / exactMultiple); useRhs = CoinMax(useRhs, oldRhs + exactMultiple); } trying = true; } } if ((switches_&8) != 0) { // Put in new suminf and check double largest = newSumInfeas; double smallest = newSumInfeas; for (int i = 0; i < SIZE_BOBBLE - 1; i++) { double value = saveSumInf[i+1]; saveSumInf[i] = value; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } saveSumInf[SIZE_BOBBLE-1] = newSumInfeas; if (smallest*1.5 > largest && smallest > 2.0) { if (bobbleMode == 0) { // go closer double gap = oldRhs - continuousObjectiveValue; useRhs -= 0.4 * gap; if (exactMultiple) { double value = floor(useRhs / exactMultiple); useRhs = CoinMin(value * exactMultiple, oldRhs - exactMultiple); } if (useRhs < continuousObjectiveValue) { // skip decrease bobbleMode = 1; useRhs = oldRhs; } } if (bobbleMode) { trying = true; // weaken if (solutionValue < 1.0e20) { double gap = solutionValue - oldRhs; useRhs += 0.3 * gap; } else { double gap = oldRhs - continuousObjectiveValue; useRhs += 0.05 * gap; } if (exactMultiple) { double value = ceil(useRhs / exactMultiple); useRhs = CoinMin(value * exactMultiple, solutionValue - exactMultiple); } } bobbleMode++; // reset CoinFillN(saveSumInf, SIZE_BOBBLE, COIN_DBL_MAX); } } if (useRhs != oldRhs) { // tidy up if (exactMultiple) { double value = floor(useRhs / exactMultiple); double bestPossible = ceil(continuousObjectiveValue / exactMultiple); useRhs = CoinMax(value, bestPossible) * exactMultiple; } else { useRhs = CoinMax(useRhs, continuousObjectiveValue); } int k = solver->getNumRows() - 1; solver->setRowUpper(k, useRhs + useOffset); bool takeHint; OsiHintStrength strength; solver->getHintParam(OsiDoDualInResolve, takeHint, strength); if (useRhs < oldRhs) { solver->setHintParam(OsiDoDualInResolve, true); solver->resolve(); } else if (useRhs > oldRhs) { solver->setHintParam(OsiDoDualInResolve, false); solver->resolve(); } solver->setHintParam(OsiDoDualInResolve, takeHint); if (!solver->isProvenOptimal()) { // presumably max time or some such exitAll = true; break; } } else if (trying) { // doesn't look good break; } } } // reduce scale factor scaleFactor *= weightFactor_; } // END WHILE // see if rounding worked! if (roundingObjective < solutionValue) { if (roundingObjective < solutionValue - 1.0e-6*fabs(roundingObjective)) { sprintf(pumpPrint, "Rounding solution of %g is better than previous of %g\n", roundingObjective, solutionValue); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; } solutionValue = roundingObjective; newSolutionValue = solutionValue; memcpy(betterSolution, roundingSolution, numberColumns*sizeof(double)); solutionFound = true; numberSolutions++; if (numberSolutions>=maxSolutions) exitAll = true; if (exitNow(roundingObjective)) exitAll = true; } if (!solutionFound) { sprintf(pumpPrint, "No solution found this major pass"); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; } //} delete solver; solver = NULL; for ( j = 0; j < NUMBER_OLD; j++) delete [] oldSolution[j]; delete [] oldSolution; delete [] saveObjective; if (usedColumn && !exitAll) { OsiSolverInterface * newSolver = cloneBut(3); // was model_->continuousSolver()->clone(); #if 0 //def COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (newSolver); if (clpSolver) { ClpSimplex * simplex = clpSolver->getModelPtr(); simplex->writeMps("start.mps",2,1); } #endif const double * colLower = newSolver->getColLower(); const double * colUpper = newSolver->getColUpper(); bool stopBAB = false; int allowedPass = -1; if (maximumAllowed > 0) allowedPass = CoinMax(numberPasses - maximumAllowed, -1); while (!stopBAB) { stopBAB = true; int i; int nFix = 0; int nFixI = 0; int nFixC = 0; int nFixC2 = 0; for (i = 0; i < numberIntegersOrig; i++) { int iColumn = integerVariableOrig[i]; //const OsiObject * object = model_->object(i); //double originalLower; //double originalUpper; //getIntegerInformation( object,originalLower, originalUpper); //assert(colLower[iColumn]==originalLower); //newSolver->setColLower(iColumn,CoinMax(colLower[iColumn],originalLower)); newSolver->setColLower(iColumn, colLower[iColumn]); //assert(colUpper[iColumn]==originalUpper); //newSolver->setColUpper(iColumn,CoinMin(colUpper[iColumn],originalUpper)); newSolver->setColUpper(iColumn, colUpper[iColumn]); if (usedColumn[iColumn] <= allowedPass) { double value = lastSolution[iColumn]; double nearest = floor(value + 0.5); if (fabs(value - nearest) < 1.0e-7) { if (nearest == colLower[iColumn]) { newSolver->setColUpper(iColumn, colLower[iColumn]); nFix++; } else if (nearest == colUpper[iColumn]) { newSolver->setColLower(iColumn, colUpper[iColumn]); nFix++; } else if (fixInternal) { newSolver->setColLower(iColumn, nearest); newSolver->setColUpper(iColumn, nearest); nFix++; nFixI++; } } } } if (fixContinuous) { for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn) && usedColumn[iColumn] <= allowedPass) { double value = lastSolution[iColumn]; if (value < colLower[iColumn] + 1.0e-8) { newSolver->setColUpper(iColumn, colLower[iColumn]); nFixC++; } else if (value > colUpper[iColumn] - 1.0e-8) { newSolver->setColLower(iColumn, colUpper[iColumn]); nFixC++; } else if (fixContinuous == 2) { newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); nFixC++; nFixC2++; } } } } newSolver->initialSolve(); if (!newSolver->isProvenOptimal()) { //newSolver->writeMps("bad.mps"); //assert (newSolver->isProvenOptimal()); exitAll = true; break; } sprintf(pumpPrint, "Before mini branch and bound, %d integers at bound fixed and %d continuous", nFix, nFixC); if (nFixC2 + nFixI != 0) sprintf(pumpPrint + strlen(pumpPrint), " of which %d were internal integer and %d internal continuous", nFixI, nFixC2); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; double saveValue = newSolutionValue; if (newSolutionValue - model_->getCutoffIncrement() > continuousObjectiveValue - 1.0e-7) { double saveFraction = fractionSmall_; if (numberTries > 1 && !numberBandBsolutions) fractionSmall_ *= 0.5; // Give branch and bound a bit more freedom double cutoff2 = newSolutionValue + CoinMax(model_->getCutoffIncrement(), 1.0e-3); #if 0 { OsiClpSolverInterface * clpSolver = dynamic_cast (newSolver); if (clpSolver) { ClpSimplex * simplex = clpSolver->getModelPtr(); simplex->writeMps("testA.mps",2,1); } } #endif int returnCode2 = smallBranchAndBound(newSolver, numberNodes_, newSolution, newSolutionValue, cutoff2, "CbcHeuristicLocalAfterFPump"); fractionSmall_ = saveFraction; if (returnCode2 < 0) { if (returnCode2 == -2) { exitAll = true; returnCode = 0; } else { returnCode2 = 0; // returned on size - try changing //#define ROUND_AGAIN #ifdef ROUND_AGAIN if (numberTries == 1 && numberPasses > 20 && allowedPass < numberPasses - 1) { allowedPass = (numberPasses + allowedPass) >> 1; sprintf(pumpPrint, "Fixing all variables which were last changed on pass %d and trying again", allowedPass); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; stopBAB = false; continue; } #endif } } if ((returnCode2&2) != 0) { // could add cut returnCode2 &= ~2; } if (returnCode2) { numberBandBsolutions++; // may not have got solution earlier returnCode |= 1; } } else { // no need exitAll = true; //returnCode=0; } // recompute solution value if (returnCode && true) { #if 0 { OsiClpSolverInterface * clpSolver = dynamic_cast (newSolver); if (clpSolver) { ClpSimplex * simplex = clpSolver->getModelPtr(); simplex->writeMps("testB.mps",2,1); } } #endif delete newSolver; newSolver = cloneBut(3); // was model_->continuousSolver()->clone(); newSolutionValue = -saveOffset; double newSumInfeas = 0.0; const double * obj = newSolver->getObjCoefficients(); for (int i = 0 ; i < numberColumns ; i++ ) { if (newSolver->isInteger(i)) { double value = newSolution[i]; double nearest = floor(value + 0.5); newSumInfeas += fabs(value - nearest); } newSolutionValue += obj[i] * newSolution[i]; } newSolutionValue *= direction; } bool gotSolution = false; if (returnCode && newSolutionValue < saveValue) { sprintf(pumpPrint, "Mini branch and bound improved solution from %g to %g (%.2f seconds)", saveValue, newSolutionValue, model_->getCurrentSeconds()); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); gotSolution = true; if (fixContinuous && nFixC + nFixC2 > 0) { // may be able to do even better int nFixed = 0; const double * lower = model_->solver()->getColLower(); const double * upper = model_->solver()->getColUpper(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double value = newSolution[iColumn]; if (newSolver->isInteger(iColumn)) { value = floor(newSolution[iColumn] + 0.5); newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); nFixed++; } else { newSolver->setColLower(iColumn, lower[iColumn]); newSolver->setColUpper(iColumn, upper[iColumn]); if (value < lower[iColumn]) value = lower[iColumn]; else if (value > upper[iColumn]) value = upper[iColumn]; } newSolution[iColumn] = value; } newSolver->setColSolution(newSolution); //#define CLP_INVESTIGATE2 #ifdef CLP_INVESTIGATE2 { // check // get row activities int numberRows = newSolver->getNumRows(); double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); newSolver->getMatrixByCol()->times(newSolution, rowActivity) ; double largestInfeasibility = primalTolerance; double sumInfeasibility = 0.0; int numberBadRows = 0; const double * rowLower = newSolver->getRowLower(); const double * rowUpper = newSolver->getRowUpper(); for (i = 0 ; i < numberRows ; i++) { double value; value = rowLower[i] - rowActivity[i]; if (value > primalTolerance) { numberBadRows++; largestInfeasibility = CoinMax(largestInfeasibility, value); sumInfeasibility += value; } value = rowActivity[i] - rowUpper[i]; if (value > primalTolerance) { numberBadRows++; largestInfeasibility = CoinMax(largestInfeasibility, value); sumInfeasibility += value; } } printf("%d bad rows, largest inf %g sum %g\n", numberBadRows, largestInfeasibility, sumInfeasibility); delete [] rowActivity; } #endif #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (newSolver); if (clpSolver) { ClpSimplex * simplex = clpSolver->getModelPtr(); //simplex->writeBasis("test.bas",true,2); //simplex->writeMps("test.mps",2,1); if (nFixed*3 > numberColumns*2) simplex->allSlackBasis(); // may as well go from all slack simplex->primal(1); clpSolver->setWarmStart(NULL); } #endif newSolver->initialSolve(); if (newSolver->isProvenOptimal()) { double value = newSolver->getObjValue() * newSolver->getObjSense(); if (value < newSolutionValue) { //newSolver->writeMps("query","mps"); #ifdef JJF_ZERO { double saveOffset; newSolver->getDblParam(OsiObjOffset, saveOffset); const double * obj = newSolver->getObjCoefficients(); double newTrueSolutionValue = -saveOffset; double newSumInfeas = 0.0; int numberColumns = newSolver->getNumCols(); const double * solution = newSolver->getColSolution(); for (int i = 0 ; i < numberColumns ; i++ ) { if (newSolver->isInteger(i)) { double value = solution[i]; double nearest = floor(value + 0.5); newSumInfeas += fabs(value - nearest); } if (solution[i]) printf("%d obj %g val %g - total %g\n", i, obj[i], solution[i], newTrueSolutionValue); newTrueSolutionValue += obj[i] * solution[i]; } printf("obj %g - inf %g\n", newTrueSolutionValue, newSumInfeas); } #endif sprintf(pumpPrint, "Freeing continuous variables gives a solution of %g", value); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; newSolutionValue = value; memcpy(betterSolution, newSolver->getColSolution(), numberColumns*sizeof(double)); } } else { //newSolver->writeMps("bad3.mps"); sprintf(pumpPrint, "On closer inspection solution is not valid"); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; exitAll = true; break; } } } else { sprintf(pumpPrint, "Mini branch and bound did not improve solution (%.2f seconds)", model_->getCurrentSeconds()); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; if (returnCode && newSolutionValue < saveValue + 1.0e-3 && nFixC + nFixC2) { // may be able to do better const double * lower = model_->solver()->getColLower(); const double * upper = model_->solver()->getColUpper(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (newSolver->isInteger(iColumn)) { double value = floor(newSolution[iColumn] + 0.5); newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); } else { newSolver->setColLower(iColumn, lower[iColumn]); newSolver->setColUpper(iColumn, upper[iColumn]); } } newSolver->initialSolve(); if (newSolver->isProvenOptimal()) { double value = newSolver->getObjValue() * newSolver->getObjSense(); if (value < saveValue) { sprintf(pumpPrint, "Freeing continuous variables gives a solution of %g", value); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; newSolutionValue = value; memcpy(betterSolution, newSolver->getColSolution(), numberColumns*sizeof(double)); gotSolution = true; } } } } if (gotSolution) { if ((accumulate_&1) != 0) { model_->incrementUsed(betterSolution); // for local search } solutionValue = newSolutionValue; solutionFound = true; numberSolutions++; if (numberSolutions>=maxSolutions) exitAll = true; if (exitNow(newSolutionValue)) exitAll = true; CoinWarmStartBasis * basis = dynamic_cast(newSolver->getWarmStart()) ; if (basis) { bestBasis = * basis; delete basis; int action = model_->dealWithEventHandler(CbcEventHandler::heuristicSolution, newSolutionValue, betterSolution); if (action == 0) { double * saveOldSolution = CoinCopyOfArray(model_->bestSolution(), numberColumns); double saveObjectiveValue = model_->getMinimizationObjValue(); model_->setBestSolution(betterSolution, numberColumns, newSolutionValue); if (saveOldSolution && saveObjectiveValue < model_->getMinimizationObjValue()) model_->setBestSolution(saveOldSolution, numberColumns, saveObjectiveValue); delete [] saveOldSolution; } if (!action || model_->getCurrentSeconds() > model_->getMaximumSeconds()) { exitAll = true; // exit break; } } } } // end stopBAB while delete newSolver; } if (solutionFound) finalReturnCode = 1; cutoff = CoinMin(cutoff, solutionValue - model_->getCutoffIncrement()); if (numberTries >= maximumRetries_ || !solutionFound || exitAll || cutoff < continuousObjectiveValue + 1.0e-7) { break; } else { solutionFound = false; if (absoluteIncrement_ > 0.0 || relativeIncrement_ > 0.0) { double gap = relativeIncrement_ * fabs(solutionValue); double change = CoinMax(gap, absoluteIncrement_); cutoff = CoinMin(cutoff, solutionValue - change); } else { //double weights[10]={0.1,0.1,0.2,0.2,0.2,0.3,0.3,0.3,0.4,0.5}; double weights[10] = {0.1, 0.2, 0.3, 0.3, 0.4, 0.4, 0.4, 0.5, 0.5, 0.6}; cutoff -= weights[CoinMin(numberTries-1, 9)] * (cutoff - continuousObjectiveValue); } // But round down if (exactMultiple) cutoff = exactMultiple * floor(cutoff / exactMultiple); if (cutoff < continuousObjectiveValue) break; sprintf(pumpPrint, "Round again with cutoff of %g", cutoff); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; if ((accumulate_&3) < 2 && usedColumn) { for (int i = 0; i < numberColumns; i++) usedColumn[i] = -1; } averageIterationsPerTry = totalNumberIterations / numberTries; numberIterationsLastPass = totalNumberIterations; totalNumberPasses += numberPasses - 1; } } /* End of the `exitAll' loop. */ #ifdef RAND_RAND delete [] randomFactor; #endif delete solver; // probably NULL but do anyway if (!finalReturnCode && closestSolution && closestObjectiveValue <= 10.0 && usedColumn && !model_->maximumSecondsReached()) { // try a bit of branch and bound OsiSolverInterface * newSolver = cloneBut(1); // was model_->continuousSolver()->clone(); const double * colLower = newSolver->getColLower(); const double * colUpper = newSolver->getColUpper(); int i; double rhs = 0.0; for (i = 0; i < numberIntegersOrig; i++) { int iColumn = integerVariableOrig[i]; int direction = closestSolution[i]; closestSolution[i] = iColumn; if (direction == 0) { // keep close to LB rhs += colLower[iColumn]; lastSolution[i] = 1.0; } else { // keep close to UB rhs -= colUpper[iColumn]; lastSolution[i] = -1.0; } } newSolver->addRow(numberIntegersOrig, closestSolution, lastSolution, -COIN_DBL_MAX, rhs + 10.0); //double saveValue = newSolutionValue; //newSolver->writeMps("sub"); int returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, newSolutionValue, newSolutionValue, "CbcHeuristicLocalAfterFPump"); if (returnCode < 0) returnCode = 0; // returned on size if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } if (returnCode) { //printf("old sol of %g new of %g\n",saveValue,newSolutionValue); memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); //abort(); solutionValue = newSolutionValue; solutionFound = true; numberSolutions++; if (numberSolutions>=maxSolutions) exitAll = true; if (exitNow(newSolutionValue)) exitAll = true; } delete newSolver; } delete clonedSolver; delete [] roundingSolution; delete [] usedColumn; delete [] lastSolution; delete [] newSolution; delete [] closestSolution; delete [] integerVariable; delete [] firstPerturbedObjective; delete [] firstPerturbedSolution; if (solutionValue == incomingObjective) sprintf(pumpPrint, "After %.2f seconds - Feasibility pump exiting - took %.2f seconds", model_->getCurrentSeconds(), CoinCpuTime() - time1); else if (numberSolutions < maxSolutions) sprintf(pumpPrint, "After %.2f seconds - Feasibility pump exiting with objective of %g - took %.2f seconds", model_->getCurrentSeconds(), solutionValue, CoinCpuTime() - time1); else sprintf(pumpPrint, "After %.2f seconds - Feasibility pump exiting with objective of %g (stopping after %d solutions) - took %.2f seconds", model_->getCurrentSeconds(), solutionValue, numberSolutions,CoinCpuTime() - time1); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << pumpPrint << CoinMessageEol; if (bestBasis.getNumStructural()) model_->setBestSolutionBasis(bestBasis); //model_->setMinimizationObjValue(saveBestObjective); if ((accumulate_&1) != 0 && numberSolutions > 1 && !model_->getSolutionCount()) { model_->setSolutionCount(1); // for local search model_->setNumberHeuristicSolutions(1); } #ifdef COIN_DEVELOP { double ncol = model_->solver()->getNumCols(); double nrow = model_->solver()->getNumRows(); printf("XXX total iterations %d ratios - %g %g %g\n", totalNumberIterations, static_cast (totalNumberIterations) / nrow, static_cast (totalNumberIterations) / ncol, static_cast (totalNumberIterations) / (2*nrow + 2*ncol)); } #endif return finalReturnCode; } /**************************END MAIN PROCEDURE ***********************************/ // update model void CbcHeuristicFPump::setModel(CbcModel * model) { model_ = model; } /* Rounds solution - down if < downValue returns 1 if current is a feasible solution */ int CbcHeuristicFPump::rounds(OsiSolverInterface * solver, double * solution, //const double * objective, int numberIntegers, const int * integerVariable, /*char * pumpPrint,*/ int iter, /*bool roundExpensive,*/ double downValue, int *flip) { double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance ; solver->getDblParam(OsiPrimalTolerance, primalTolerance) ; int i; const double * cost = solver->getObjCoefficients(); int flip_up = 0; int flip_down = 0; double v = randomNumberGenerator_.randomDouble() * 20.0; int nn = 10 + static_cast (v); int nnv = 0; int * list = new int [nn]; double * val = new double [nn]; for (i = 0; i < nn; i++) val[i] = .001; const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = solver->getNumRows(); if (false && (iter&1) != 0) { // Do set covering variables const CoinPackedMatrix * matrixByRow = solver->getMatrixByRow(); const double * elementByRow = matrixByRow->getElements(); const int * column = matrixByRow->getIndices(); const CoinBigIndex * rowStart = matrixByRow->getVectorStarts(); const int * rowLength = matrixByRow->getVectorLengths(); for (i = 0; i < numberRows; i++) { if (rowLower[i] == 1.0 && rowUpper[i] == 1.0) { bool cover = true; double largest = 0.0; int jColumn = -1; for (CoinBigIndex k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) { int iColumn = column[k]; if (elementByRow[k] != 1.0 || !solver->isInteger(iColumn)) { cover = false; break; } else { if (solution[iColumn]) { double value = solution[iColumn] * (randomNumberGenerator_.randomDouble() + 5.0); if (value > largest) { largest = value; jColumn = iColumn; } } } } if (cover) { for (CoinBigIndex k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) { int iColumn = column[k]; if (iColumn == jColumn) solution[iColumn] = 1.0; else solution[iColumn] = 0.0; } } } } } int numberColumns = solver->getNumCols(); #ifdef JJF_ZERO // Do set covering variables const CoinPackedMatrix * matrixByRow = solver->getMatrixByRow(); const double * elementByRow = matrixByRow->getElements(); const int * column = matrixByRow->getIndices(); const CoinBigIndex * rowStart = matrixByRow->getVectorStarts(); const int * rowLength = matrixByRow->getVectorLengths(); double * sortTemp = new double[numberColumns]; int * whichTemp = new int [numberColumns]; char * rowTemp = new char [numberRows]; memset(rowTemp, 0, numberRows); for (i = 0; i < numberColumns; i++) whichTemp[i] = -1; int nSOS = 0; for (i = 0; i < numberRows; i++) { if (rowLower[i] == 1.0 && rowUpper[i] == 1.0) { bool cover = true; for (CoinBigIndex k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) { int iColumn = column[k]; if (elementByRow[k] != 1.0 || !solver->isInteger(iColumn)) { cover = false; break; } } if (cover) { rowTemp[i] = 1; nSOS++; for (CoinBigIndex k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) { int iColumn = column[k]; double value = solution[iColumn]; whichTemp[iColumn] = iColumn; } } } } if (nSOS) { // Column copy const CoinPackedMatrix * matrixByColumn = solver->getMatrixByCol(); //const double * element = matrixByColumn->getElements(); const int * row = matrixByColumn->getIndices(); const CoinBigIndex * columnStart = matrixByColumn->getVectorStarts(); const int * columnLength = matrixByColumn->getVectorLengths(); int nLook = 0; for (i = 0; i < numberColumns; i++) { if (whichTemp[i] >= 0) { whichTemp[nLook] = i; double value = solution[i]; if (value < 0.5) value *= (0.1 * randomNumberGenerator_.randomDouble() + 0.3); sortTemp[nLook++] = -value; } } CoinSort_2(sortTemp, sortTemp + nLook, whichTemp); double smallest = 1.0; int nFix = 0; int nOne = 0; for (int j = 0; j < nLook; j++) { int jColumn = whichTemp[j]; double thisValue = solution[jColumn]; if (!thisValue) continue; if (thisValue == 1.0) nOne++; smallest = CoinMin(smallest, thisValue); solution[jColumn] = 1.0; double largest = 0.0; for (CoinBigIndex jEl = columnStart[jColumn]; jEl < columnStart[jColumn] + columnLength[jColumn]; jEl++) { int jRow = row[jEl]; if (rowTemp[jRow]) { for (CoinBigIndex k = rowStart[jRow]; k < rowStart[jRow] + rowLength[jRow]; k++) { int iColumn = column[k]; if (solution[iColumn]) { if (iColumn != jColumn) { double value = solution[iColumn]; if (value > largest) largest = value; solution[iColumn] = 0.0; } } } } } if (largest > thisValue) printf("%d was at %g - chosen over a value of %g\n", jColumn, thisValue, largest); nFix++; } printf("%d fixed out of %d (%d at one already)\n", nFix, nLook, nOne); } delete [] sortTemp; delete [] whichTemp; delete [] rowTemp; #endif const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); // Check if valid with current solution (allow for 0.99999999s) for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = solution[iColumn]; double round = floor(value + 0.5); if (fabs(value - round) > primalTolerance) break; } if (i == numberIntegers) { // may be able to use solution even if 0.99999's double * saveLower = CoinCopyOfArray(columnLower, numberColumns); double * saveUpper = CoinCopyOfArray(columnUpper, numberColumns); double * saveSolution = CoinCopyOfArray(solution, numberColumns); double * tempSolution = CoinCopyOfArray(solution, numberColumns); CoinWarmStartBasis * saveBasis = dynamic_cast(solver->getWarmStart()) ; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = solution[iColumn]; double round = floor(value + 0.5); solver->setColLower(iColumn, round); solver->setColUpper(iColumn, round); tempSolution[iColumn] = round; } solver->setColSolution(tempSolution); delete [] tempSolution; solver->resolve(); solver->setColLower(saveLower); solver->setColUpper(saveUpper); solver->setWarmStart(saveBasis); delete [] saveLower; delete [] saveUpper; delete saveBasis; if (!solver->isProvenOptimal()) { solver->setColSolution(saveSolution); } delete [] saveSolution; if (solver->isProvenOptimal()) { // feasible delete [] list; delete [] val; return 1; } } //double * saveSolution = CoinCopyOfArray(solution,numberColumns); // return rounded solution for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = solution[iColumn]; double round = floor(value + primalTolerance); if (value - round > downValue) round += 1.; #ifndef JJF_ONE if (round < integerTolerance && cost[iColumn] < -1. + integerTolerance) flip_down++; if (round > 1. - integerTolerance && cost[iColumn] > 1. - integerTolerance) flip_up++; #else if (round < columnLower[iColumn] + integerTolerance && cost[iColumn] < -1. + integerTolerance) flip_down++; if (round > columnUpper[iColumn] - integerTolerance && cost[iColumn] > 1. - integerTolerance) flip_up++; #endif if (flip_up + flip_down == 0) { for (int k = 0; k < nn; k++) { if (fabs(value - round) > val[k]) { nnv++; for (int j = nn - 2; j >= k; j--) { val[j+1] = val[j]; list[j+1] = list[j]; } val[k] = fabs(value - round); list[k] = iColumn; break; } } } solution[iColumn] = round; } if (nnv > nn) nnv = nn; //if (iter != 0) //sprintf(pumpPrint+strlen(pumpPrint),"up = %5d , down = %5d", flip_up, flip_down); *flip = flip_up + flip_down; if (*flip == 0 && iter != 0) { //sprintf(pumpPrint+strlen(pumpPrint)," -- rand = %4d (%4d) ", nnv, nn); for (i = 0; i < nnv; i++) { // was solution[list[i]] = 1. - solution[list[i]]; but does that work for 7>=x>=6 int index = list[i]; double value = solution[index]; if (value <= 1.0) { solution[index] = 1.0 - value; } else if (value < columnLower[index] + integerTolerance) { solution[index] = value + 1.0; } else if (value > columnUpper[index] - integerTolerance) { solution[index] = value - 1.0; } else { solution[index] = value - 1.0; } } *flip = nnv; } else { //sprintf(pumpPrint+strlen(pumpPrint)," "); } delete [] list; delete [] val; //iter++; // get row activities double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); solver->getMatrixByCol()->times(solution, rowActivity) ; double largestInfeasibility = primalTolerance; double sumInfeasibility = 0.0; int numberBadRows = 0; for (i = 0 ; i < numberRows ; i++) { double value; value = rowLower[i] - rowActivity[i]; if (value > primalTolerance) { numberBadRows++; largestInfeasibility = CoinMax(largestInfeasibility, value); sumInfeasibility += value; } value = rowActivity[i] - rowUpper[i]; if (value > primalTolerance) { numberBadRows++; largestInfeasibility = CoinMax(largestInfeasibility, value); sumInfeasibility += value; } } #ifdef JJF_ZERO if (largestInfeasibility > primalTolerance && numberBadRows*10 < numberRows) { // Can we improve by flipping for (int iPass = 0; iPass < 10; iPass++) { int numberColumns = solver->getNumCols(); const CoinPackedMatrix * matrixByCol = solver->getMatrixByCol(); const double * element = matrixByCol->getElements(); const int * row = matrixByCol->getIndices(); const CoinBigIndex * columnStart = matrixByCol->getVectorStarts(); const int * columnLength = matrixByCol->getVectorLengths(); double oldSum = sumInfeasibility; // First improve by moving continuous ones for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!solver->isInteger(iColumn)) { double solValue = solution[iColumn]; double thetaUp = columnUpper[iColumn] - solValue; double improvementUp = 0.0; if (thetaUp > primalTolerance) { // can go up for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double distanceUp = rowUpper[iRow] - rowActivity[iRow]; double distanceDown = rowLower[iRow] - rowActivity[iRow]; double el = element[j]; if (el > 0.0) { // positive element if (distanceUp > 0.0) { if (thetaUp*el > distanceUp) thetaUp = distanceUp / el; } else { improvementUp -= el; } if (distanceDown > 0.0) { if (thetaUp*el > distanceDown) thetaUp = distanceDown / el; improvementUp += el; } } else { // negative element if (distanceDown < 0.0) { if (thetaUp*el < distanceDown) thetaUp = distanceDown / el; } else { improvementUp += el; } if (distanceUp < 0.0) { if (thetaUp*el < distanceUp) thetaUp = distanceUp / el; improvementUp -= el; } } } } double thetaDown = solValue - columnLower[iColumn]; double improvementDown = 0.0; if (thetaDown > primalTolerance) { // can go down for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double distanceUp = rowUpper[iRow] - rowActivity[iRow]; double distanceDown = rowLower[iRow] - rowActivity[iRow]; double el = -element[j]; // not change in sign form up if (el > 0.0) { // positive element if (distanceUp > 0.0) { if (thetaDown*el > distanceUp) thetaDown = distanceUp / el; } else { improvementDown -= el; } if (distanceDown > 0.0) { if (thetaDown*el > distanceDown) thetaDown = distanceDown / el; improvementDown += el; } } else { // negative element if (distanceDown < 0.0) { if (thetaDown*el < distanceDown) thetaDown = distanceDown / el; } else { improvementDown += el; } if (distanceUp < 0.0) { if (thetaDown*el < distanceUp) thetaDown = distanceUp / el; improvementDown -= el; } } } if (thetaUp < 1.0e-8) improvementUp = 0.0; if (thetaDown < 1.0e-8) improvementDown = 0.0; double theta; if (improvementUp >= improvementDown) { theta = thetaUp; } else { improvementUp = improvementDown; theta = -thetaDown; } if (improvementUp > 1.0e-8 && fabs(theta) > 1.0e-8) { // Could move double oldSum = 0.0; double newSum = 0.0; solution[iColumn] += theta; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double lower = rowLower[iRow]; double upper = rowUpper[iRow]; double value = rowActivity[iRow]; if (value > upper) oldSum += value - upper; else if (value < lower) oldSum += lower - value; value += theta * element[j]; rowActivity[iRow] = value; if (value > upper) newSum += value - upper; else if (value < lower) newSum += lower - value; } assert (newSum <= oldSum); sumInfeasibility += newSum - oldSum; } } } } // Now flip some integers? #ifdef JJF_ZERO for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double solValue = solution[iColumn]; assert (fabs(solValue - floor(solValue + 0.5)) < 1.0e-8); double improvementUp = 0.0; if (columnUpper[iColumn] >= solValue + 1.0) { // can go up double oldSum = 0.0; double newSum = 0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double lower = rowLower[iRow]; double upper = rowUpper[iRow]; double value = rowActivity[iRow]; if (value > upper) oldSum += value - upper; else if (value < lower) oldSum += lower - value; value += element[j]; if (value > upper) newSum += value - upper; else if (value < lower) newSum += lower - value; } improvementUp = oldSum - newSum; } double improvementDown = 0.0; if (columnLower[iColumn] <= solValue - 1.0) { // can go down double oldSum = 0.0; double newSum = 0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double lower = rowLower[iRow]; double upper = rowUpper[iRow]; double value = rowActivity[iRow]; if (value > upper) oldSum += value - upper; else if (value < lower) oldSum += lower - value; value -= element[j]; if (value > upper) newSum += value - upper; else if (value < lower) newSum += lower - value; } improvementDown = oldSum - newSum; } double theta; if (improvementUp >= improvementDown) { theta = 1.0; } else { improvementUp = improvementDown; theta = -1.0; } if (improvementUp > 1.0e-8 && fabs(theta) > 1.0e-8) { // Could move double oldSum = 0.0; double newSum = 0.0; solution[iColumn] += theta; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double lower = rowLower[iRow]; double upper = rowUpper[iRow]; double value = rowActivity[iRow]; if (value > upper) oldSum += value - upper; else if (value < lower) oldSum += lower - value; value += theta * element[j]; rowActivity[iRow] = value; if (value > upper) newSum += value - upper; else if (value < lower) newSum += lower - value; } assert (newSum <= oldSum); sumInfeasibility += newSum - oldSum; } } #else int bestColumn = -1; double bestImprovement = primalTolerance; double theta = 0.0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double solValue = solution[iColumn]; assert (fabs(solValue - floor(solValue + 0.5)) < 1.0e-8); double improvementUp = 0.0; if (columnUpper[iColumn] >= solValue + 1.0) { // can go up double oldSum = 0.0; double newSum = 0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double lower = rowLower[iRow]; double upper = rowUpper[iRow]; double value = rowActivity[iRow]; if (value > upper) oldSum += value - upper; else if (value < lower) oldSum += lower - value; value += element[j]; if (value > upper) newSum += value - upper; else if (value < lower) newSum += lower - value; } improvementUp = oldSum - newSum; } double improvementDown = 0.0; if (columnLower[iColumn] <= solValue - 1.0) { // can go down double oldSum = 0.0; double newSum = 0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double lower = rowLower[iRow]; double upper = rowUpper[iRow]; double value = rowActivity[iRow]; if (value > upper) oldSum += value - upper; else if (value < lower) oldSum += lower - value; value -= element[j]; if (value > upper) newSum += value - upper; else if (value < lower) newSum += lower - value; } improvementDown = oldSum - newSum; } double improvement = CoinMax(improvementUp, improvementDown); if (improvement > bestImprovement) { bestImprovement = improvement; bestColumn = iColumn; if (improvementUp > improvementDown) theta = 1.0; else theta = -1.0; } } if (bestColumn >= 0) { // Could move int iColumn = bestColumn; double oldSum = 0.0; double newSum = 0.0; solution[iColumn] += theta; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double lower = rowLower[iRow]; double upper = rowUpper[iRow]; double value = rowActivity[iRow]; if (value > upper) oldSum += value - upper; else if (value < lower) oldSum += lower - value; value += theta * element[j]; rowActivity[iRow] = value; if (value > upper) newSum += value - upper; else if (value < lower) newSum += lower - value; } assert (newSum <= oldSum); sumInfeasibility += newSum - oldSum; } #endif if (oldSum <= sumInfeasibility + primalTolerance) break; // no good } } //delete [] saveSolution; #endif delete [] rowActivity; return (largestInfeasibility > primalTolerance) ? 0 : 1; } // Set maximum Time (default off) - also sets starttime to current void CbcHeuristicFPump::setMaximumTime(double value) { startTime_ = CoinCpuTime(); maximumTime_ = value; } # ifdef COIN_HAS_CLP //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CbcDisasterHandler::CbcDisasterHandler (CbcModel * model) : OsiClpDisasterHandler(), cbcModel_(model) { if (model) { osiModel_ = dynamic_cast (model->solver()); if (osiModel_) setSimplex(osiModel_->getModelPtr()); } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CbcDisasterHandler::CbcDisasterHandler (const CbcDisasterHandler & rhs) : OsiClpDisasterHandler(rhs), cbcModel_(rhs.cbcModel_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CbcDisasterHandler::~CbcDisasterHandler () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcDisasterHandler & CbcDisasterHandler::operator=(const CbcDisasterHandler & rhs) { if (this != &rhs) { OsiClpDisasterHandler::operator=(rhs); cbcModel_ = rhs.cbcModel_; } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpDisasterHandler * CbcDisasterHandler::clone() const { return new CbcDisasterHandler(*this); } // Type of disaster 0 can fix, 1 abort int CbcDisasterHandler::typeOfDisaster() { if (!cbcModel_->parentModel() && (cbcModel_->specialOptions()&2048) == 0) { return 0; } else { if (cbcModel_->parentModel()) cbcModel_->setMaximumNodes(0); return 1; } } /* set model. */ void CbcDisasterHandler::setCbcModel(CbcModel * model) { cbcModel_ = model; if (model) { osiModel_ = dynamic_cast (model->solver()); if (osiModel_) setSimplex(osiModel_->getModelPtr()); else setSimplex(NULL); } } #endif Cbc-2.8.12/src/CbcGeneral.cpp0000644000076600007660000000332712131315050014225 0ustar coincoin// $Id: CbcGeneral.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcGeneral.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" // Default Constructor CbcGeneral::CbcGeneral() : CbcObject() { } // Constructor from model CbcGeneral::CbcGeneral(CbcModel * model) : CbcObject(model) { } // Destructor CbcGeneral::~CbcGeneral () { } // Copy constructor CbcGeneral::CbcGeneral ( const CbcGeneral & rhs) : CbcObject(rhs) { } #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #include "CoinWarmStartBasis.hpp" #include "ClpNode.hpp" #include "CbcBranchDynamic.hpp" // Assignment operator CbcGeneral & CbcGeneral::operator=( const CbcGeneral & rhs) { if (this != &rhs) { CbcObject::operator=(rhs); } return *this; } // Infeasibility - large is 0.5 double CbcGeneral::infeasibility(const OsiBranchingInformation * /*info*/, int &/*preferredWay*/) const { abort(); return 0.0; } CbcBranchingObject * CbcGeneral::createCbcBranch(OsiSolverInterface * /*solver*/, const OsiBranchingInformation * /*info*/, int /*way*/) { abort(); return NULL; } #endif Cbc-2.8.12/src/CbcHeuristicLocal.hpp0000644000076600007660000001612312053120460015567 0ustar coincoin/* $Id: CbcHeuristicLocal.hpp 1802 2012-11-21 09:38:56Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicLocal_H #define CbcHeuristicLocal_H #include "CbcHeuristic.hpp" /** LocalSearch class */ class CbcHeuristicLocal : public CbcHeuristic { public: // Default Constructor CbcHeuristicLocal (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicLocal (CbcModel & model); // Copy constructor CbcHeuristicLocal ( const CbcHeuristicLocal &); // Destructor ~CbcHeuristicLocal (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicLocal & operator=(const CbcHeuristicLocal& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) This is called after cuts have been added - so can not add cuts First tries setting a variable to better value. If feasible then tries setting others. If not feasible then tries swaps ******** This first version does not do LP's and does swaps of two integer variables. Later versions could do Lps. */ virtual int solution(double & objectiveValue, double * newSolution); /// This version fixes stuff and does IP int solutionFix(double & objectiveValue, double * newSolution, const int * keep); /// Sets type of search inline void setSearchType(int value) { swap_ = value; } /// Used array so we can set inline int * used() const { return used_; } protected: // Data // Original matrix by column CoinPackedMatrix matrix_; // Number of solutions so we only do after new solution int numberSolutions_; // Type of search 0=normal, 1=BAB int swap_; /// Whether a variable has been in a solution (also when) int * used_; }; /** Proximity Search class */ class CbcHeuristicFPump; class CbcHeuristicProximity : public CbcHeuristic { public: // Default Constructor CbcHeuristicProximity (); /* Constructor with model - assumed before cuts */ CbcHeuristicProximity (CbcModel & model); // Copy constructor CbcHeuristicProximity ( const CbcHeuristicProximity &); // Destructor ~CbcHeuristicProximity (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicProximity & operator=(const CbcHeuristicProximity& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) */ virtual int solution(double & objectiveValue, double * newSolution); /// Used array so we can set inline int * used() const { return used_; } protected: // Data // Copy of Feasibility pump CbcHeuristicFPump * feasibilityPump_; // Number of solutions so we only do after new solution int numberSolutions_; /// Whether a variable has been in a solution (also when) int * used_; }; /** Naive class a) Fix all ints as close to zero as possible b) Fix all ints with nonzero costs and < large to zero c) Put bounds round continuous and UIs and maximize */ class CbcHeuristicNaive : public CbcHeuristic { public: // Default Constructor CbcHeuristicNaive (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicNaive (CbcModel & model); // Copy constructor CbcHeuristicNaive ( const CbcHeuristicNaive &); // Destructor ~CbcHeuristicNaive (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicNaive & operator=(const CbcHeuristicNaive& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) */ virtual int solution(double & objectiveValue, double * newSolution); /// Sets large cost value inline void setLargeValue(double value) { large_ = value; } /// Gets large cost value inline double largeValue() const { return large_; } protected: /// Data /// Large value double large_; }; /** Crossover Search class */ class CbcHeuristicCrossover : public CbcHeuristic { public: // Default Constructor CbcHeuristicCrossover (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicCrossover (CbcModel & model); // Copy constructor CbcHeuristicCrossover ( const CbcHeuristicCrossover &); // Destructor ~CbcHeuristicCrossover (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicCrossover & operator=(const CbcHeuristicCrossover& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Fix variables if agree in useNumber_ solutions when_ 0 off, 1 only at new solutions, 2 also every now and then add 10 to make only if agree at lower bound */ virtual int solution(double & objectiveValue, double * newSolution); /// Sets number of solutions to use inline void setNumberSolutions(int value) { if (value > 0 && value <= 10) useNumber_ = value; } protected: // Data /// Attempts std::vector attempts_; /// Random numbers to stop same search happening double random_[10]; /// Number of solutions so we only do after new solution int numberSolutions_; /// Number of solutions to use int useNumber_; }; #endif Cbc-2.8.12/src/CbcFullNodeInfo.cpp0000644000076600007660000001415312131315050015173 0ustar coincoin// $Id: CbcFullNodeInfo.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/24/09 carved from CbcNode #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" #include //#define CBC_DEBUG 1 //#define CHECK_CUT_COUNTS //#define CHECK_NODE //#define CBC_CHECK_BASIS #include #include #define CUTS #include "OsiSolverInterface.hpp" #include "OsiChooseVariable.hpp" #include "OsiAuxInfo.hpp" #include "OsiSolverBranch.hpp" #include "CoinWarmStartBasis.hpp" #include "CoinTime.hpp" #include "CbcModel.hpp" #include "CbcNode.hpp" #include "CbcStatistics.hpp" #include "CbcStrategy.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchDynamic.hpp" #include "OsiRowCut.hpp" #include "OsiRowCutDebugger.hpp" #include "OsiCuts.hpp" #include "CbcCountRowCut.hpp" #include "CbcFeasibilityBase.hpp" #include "CbcMessage.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #include "ClpSimplexOther.hpp" #endif using namespace std; #include "CglCutGenerator.hpp" CbcFullNodeInfo::CbcFullNodeInfo() : CbcNodeInfo(), basis_(), numberIntegers_(0), lower_(NULL), upper_(NULL) { } CbcFullNodeInfo::CbcFullNodeInfo(CbcModel * model, int numberRowsAtContinuous) : CbcNodeInfo(NULL, model->currentNode()) { OsiSolverInterface * solver = model->solver(); numberRows_ = numberRowsAtContinuous; numberIntegers_ = model->numberIntegers(); int numberColumns = model->getNumCols(); lower_ = new double [numberColumns]; upper_ = new double [numberColumns]; const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); int i; for (i = 0; i < numberColumns; i++) { lower_[i] = lower[i]; upper_[i] = upper[i]; } basis_ = dynamic_cast(solver->getWarmStart()); } CbcFullNodeInfo::CbcFullNodeInfo(const CbcFullNodeInfo & rhs) : CbcNodeInfo(rhs) { basis_ = dynamic_cast(rhs.basis_->clone()) ; numberIntegers_ = rhs.numberIntegers_; lower_ = NULL; upper_ = NULL; if (rhs.lower_ != NULL) { int numberColumns = basis_->getNumStructural(); lower_ = new double [numberColumns]; upper_ = new double [numberColumns]; assert (upper_ != NULL); memcpy(lower_, rhs.lower_, numberColumns*sizeof(double)); memcpy(upper_, rhs.upper_, numberColumns*sizeof(double)); } } CbcNodeInfo * CbcFullNodeInfo::clone() const { return (new CbcFullNodeInfo(*this)); } CbcFullNodeInfo::~CbcFullNodeInfo () { delete basis_ ; delete [] lower_; delete [] upper_; } /* The basis supplied as a parameter is deleted and replaced with a new basis appropriate for the node, and lower and upper bounds on variables are reset according to the stored bounds arrays. Any cuts associated with this node are added to the list in addCuts, but not actually added to the constraint system in the model. Why pass in a basis at all? The short answer is ``We need the parameter to pass out a basis, so might as well use it to pass in the size.'' A longer answer is that in practice we take a memory allocation hit up in addCuts1 (the only place applyToModel is called) when we setSize() the basis that's passed in. It's immediately tossed here in favour of a clone of the basis attached to this nodeInfo. This can probably be fixed, given a bit of thought. */ void CbcFullNodeInfo::applyToModel (CbcModel *model, CoinWarmStartBasis *&basis, CbcCountRowCut **addCuts, int ¤tNumberCuts) const { OsiSolverInterface *solver = model->solver() ; // branch - do bounds assert (active_ == 7 || active_ == 15); int i; solver->setColLower(lower_); solver->setColUpper(upper_); int numberColumns = model->getNumCols(); // move basis - but make sure size stays // for bon-min - should not be needed int numberRows = model->getNumRows(); int numberRows = basis->getNumArtificial(); delete basis ; if (basis_) { basis = dynamic_cast(basis_->clone()) ; basis->resize(numberRows, numberColumns); #ifdef CBC_CHECK_BASIS std::cout << "Basis (after applying root " << this << ") " << std::endl ; basis->print() ; #endif } else { // We have a solver without a basis basis = NULL; } for (i = 0; i < numberCuts_; i++) addCuts[currentNumberCuts+i] = cuts_[i]; currentNumberCuts += numberCuts_; assert(!parent_); return ; } // Just apply bounds to one variable (1=>infeasible) int CbcFullNodeInfo::applyBounds(int iColumn, double & lower, double & upper, int force) { if ((force && 1) == 0) { if (lower > lower_[iColumn]) COIN_DETAIL_PRINT(printf("%d odd lower going from %g to %g\n", iColumn, lower, lower_[iColumn])); lower = lower_[iColumn]; } else { lower_[iColumn] = lower; } if ((force && 2) == 0) { if (upper < upper_[iColumn]) COIN_DETAIL_PRINT(printf("%d odd upper going from %g to %g\n", iColumn, upper, upper_[iColumn])); upper = upper_[iColumn]; } else { upper_[iColumn] = upper; } return (upper_[iColumn] >= lower_[iColumn]) ? 0 : 1; } /* Builds up row basis backwards (until original model). Returns NULL or previous one to apply . Depends on Free being 0 and impossible for cuts */ CbcNodeInfo * CbcFullNodeInfo::buildRowBasis(CoinWarmStartBasis & basis ) const { const unsigned int * saved = reinterpret_cast (basis_->getArtificialStatus()); unsigned int * now = reinterpret_cast (basis.getArtificialStatus()); int number = basis_->getNumArtificial() >> 4;; int i; for (i = 0; i < number; i++) { if (!now[i]) now[i] = saved[i]; } return NULL; } Cbc-2.8.12/src/CbcNWay.cpp0000644000076600007660000003044312131315050013525 0ustar coincoin// $Id: CbcNWay.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/9/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcNWay.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" //############################################################################## // Default Constructor CbcNWay::CbcNWay () : CbcObject(), numberMembers_(0), members_(NULL), consequence_(NULL) { } // Useful constructor (which are integer indices) CbcNWay::CbcNWay (CbcModel * model, int numberMembers, const int * which, int identifier) : CbcObject(model) { id_ = identifier; numberMembers_ = numberMembers; if (numberMembers_) { members_ = new int[numberMembers_]; memcpy(members_, which, numberMembers_*sizeof(int)); } else { members_ = NULL; } consequence_ = NULL; } // Copy constructor CbcNWay::CbcNWay ( const CbcNWay & rhs) : CbcObject(rhs) { numberMembers_ = rhs.numberMembers_; consequence_ = NULL; if (numberMembers_) { members_ = new int[numberMembers_]; memcpy(members_, rhs.members_, numberMembers_*sizeof(int)); if (rhs.consequence_) { consequence_ = new CbcConsequence * [numberMembers_]; for (int i = 0; i < numberMembers_; i++) { if (rhs.consequence_[i]) consequence_[i] = rhs.consequence_[i]->clone(); else consequence_[i] = NULL; } } } else { members_ = NULL; } } // Clone CbcObject * CbcNWay::clone() const { return new CbcNWay(*this); } // Assignment operator CbcNWay & CbcNWay::operator=( const CbcNWay & rhs) { if (this != &rhs) { CbcObject::operator=(rhs); delete [] members_; numberMembers_ = rhs.numberMembers_; if (consequence_) { for (int i = 0; i < numberMembers_; i++) delete consequence_[i]; delete [] consequence_; consequence_ = NULL; } if (numberMembers_) { members_ = new int[numberMembers_]; memcpy(members_, rhs.members_, numberMembers_*sizeof(int)); } else { members_ = NULL; } if (rhs.consequence_) { consequence_ = new CbcConsequence * [numberMembers_]; for (int i = 0; i < numberMembers_; i++) { if (rhs.consequence_[i]) consequence_[i] = rhs.consequence_[i]->clone(); else consequence_[i] = NULL; } } } return *this; } // Destructor CbcNWay::~CbcNWay () { delete [] members_; if (consequence_) { for (int i = 0; i < numberMembers_; i++) delete consequence_[i]; delete [] consequence_; } } // Set up a consequence for a single member void CbcNWay::setConsequence(int iColumn, const CbcConsequence & consequence) { if (!consequence_) { consequence_ = new CbcConsequence * [numberMembers_]; for (int i = 0; i < numberMembers_; i++) consequence_[i] = NULL; } for (int i = 0; i < numberMembers_; i++) { if (members_[i] == iColumn) { consequence_[i] = consequence.clone(); break; } } } // Applies a consequence for a single member void CbcNWay::applyConsequence(int iSequence, int state) const { assert (state == -9999 || state == 9999); if (consequence_) { CbcConsequence * consequence = consequence_[iSequence]; if (consequence) consequence->applyToSolver(model_->solver(), state); } } double CbcNWay::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { int numberUnsatis = 0; int j; OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double largestValue = 0.0; double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); double distance = CoinMin(value - lower[iColumn], upper[iColumn] - value); if (distance > integerTolerance) { numberUnsatis++; largestValue = CoinMax(distance, largestValue); } } preferredWay = 1; if (numberUnsatis) { return largestValue; } else { return 0.0; // satisfied } } // This looks at solution and sets bounds to contain solution void CbcNWay::feasibleRegion() { int j; OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); if (value >= upper[iColumn] - integerTolerance) { solver->setColLower(iColumn, upper[iColumn]); } else { assert (value <= lower[iColumn] + integerTolerance); solver->setColUpper(iColumn, lower[iColumn]); } } } // Redoes data when sequence numbers change void CbcNWay::redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns) { model_ = model; int n2 = 0; for (int j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; int i; for (i = 0; i < numberColumns; i++) { if (originalColumns[i] == iColumn) break; } if (i < numberColumns) { members_[n2] = i; consequence_[n2++] = consequence_[j]; } else { delete consequence_[j]; } } if (n2 < numberMembers_) { printf("** NWay number of members reduced from %d to %d!\n", numberMembers_, n2); numberMembers_ = n2; } } CbcBranchingObject * CbcNWay::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int /*way*/) { int numberFree = 0; int j; //OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); int * list = new int[numberMembers_]; double * sort = new double[numberMembers_]; for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); if (upper[iColumn] > lower[iColumn]) { double distance = upper[iColumn] - value; list[numberFree] = j; sort[numberFree++] = distance; } } assert (numberFree); // sort CoinSort_2(sort, sort + numberFree, list); // create object CbcBranchingObject * branch; branch = new CbcNWayBranchingObject(model_, this, numberFree, list); branch->setOriginalObject(this); delete [] list; delete [] sort; return branch; } // Default Constructor CbcNWayBranchingObject::CbcNWayBranchingObject() : CbcBranchingObject() { order_ = NULL; object_ = NULL; numberInSet_ = 0; way_ = 0; } // Useful constructor CbcNWayBranchingObject::CbcNWayBranchingObject (CbcModel * model, const CbcNWay * nway, int number, const int * order) : CbcBranchingObject(model, nway->id(), -1, 0.5) { numberBranches_ = number; order_ = new int [number]; object_ = nway; numberInSet_ = number; memcpy(order_, order, number*sizeof(int)); } // Copy constructor CbcNWayBranchingObject::CbcNWayBranchingObject ( const CbcNWayBranchingObject & rhs) : CbcBranchingObject(rhs) { numberInSet_ = rhs.numberInSet_; object_ = rhs.object_; if (numberInSet_) { order_ = new int [numberInSet_]; memcpy(order_, rhs.order_, numberInSet_*sizeof(int)); } else { order_ = NULL; } } // Assignment operator CbcNWayBranchingObject & CbcNWayBranchingObject::operator=( const CbcNWayBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); object_ = rhs.object_; delete [] order_; numberInSet_ = rhs.numberInSet_; if (numberInSet_) { order_ = new int [numberInSet_]; memcpy(order_, rhs.order_, numberInSet_*sizeof(int)); } else { order_ = NULL; } } return *this; } CbcBranchingObject * CbcNWayBranchingObject::clone() const { return (new CbcNWayBranchingObject(*this)); } // Destructor CbcNWayBranchingObject::~CbcNWayBranchingObject () { delete [] order_; } double CbcNWayBranchingObject::branch() { int which = branchIndex_; branchIndex_++; assert (numberBranchesLeft() >= 0); if (which == 0) { // first branch so way_ may mean something assert (way_ == -1 || way_ == 1); if (way_ == -1) which++; } else if (which == 1) { // second branch so way_ may mean something assert (way_ == -1 || way_ == 1); if (way_ == -1) which--; // switch way off way_ = 0; } const double * lower = model_->solver()->getColLower(); const double * upper = model_->solver()->getColUpper(); const int * members = object_->members(); for (int j = 0; j < numberInSet_; j++) { int iSequence = order_[j]; int iColumn = members[iSequence]; if (j != which) { model_->solver()->setColUpper(iColumn, lower[iColumn]); //model_->solver()->setColLower(iColumn,lower[iColumn]); assert (lower[iColumn] > -1.0e20); // apply any consequences object_->applyConsequence(iSequence, -9999); } else { model_->solver()->setColLower(iColumn, upper[iColumn]); //model_->solver()->setColUpper(iColumn,upper[iColumn]); #ifdef FULL_PRINT printf("Up Fix %d to %g\n", iColumn, upper[iColumn]); #endif assert (upper[iColumn] < 1.0e20); // apply any consequences object_->applyConsequence(iSequence, 9999); } } return 0.0; } void CbcNWayBranchingObject::print() { printf("NWay - Up Fix "); const int * members = object_->members(); for (int j = 0; j < way_; j++) { int iColumn = members[order_[j]]; printf("%d ", iColumn); } printf("\n"); } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcNWayBranchingObject::compareOriginalObject (const CbcBranchingObject* /*brObj*/) const { throw("must implement"); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcNWayBranchingObject::compareBranchingObject (const CbcBranchingObject* /*brObj*/, const bool /*replaceIfOverlap*/) { throw("must implement"); } Cbc-2.8.12/src/CbcHeuristicDiveCoefficient.cpp0000644000076600007660000001004112131315050017545 0ustar coincoin/* $Id: CbcHeuristicDiveCoefficient.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif //#define PRINT_DEBUG #include "CbcHeuristicDiveCoefficient.hpp" #include "CbcStrategy.hpp" // Default Constructor CbcHeuristicDiveCoefficient::CbcHeuristicDiveCoefficient() : CbcHeuristicDive() { } // Constructor from model CbcHeuristicDiveCoefficient::CbcHeuristicDiveCoefficient(CbcModel & model) : CbcHeuristicDive(model) { } // Destructor CbcHeuristicDiveCoefficient::~CbcHeuristicDiveCoefficient () { } // Clone CbcHeuristicDiveCoefficient * CbcHeuristicDiveCoefficient::clone() const { return new CbcHeuristicDiveCoefficient(*this); } // Create C++ lines to get to current state void CbcHeuristicDiveCoefficient::generateCpp( FILE * fp) { CbcHeuristicDiveCoefficient other; fprintf(fp, "0#include \"CbcHeuristicDiveCoefficient.hpp\"\n"); fprintf(fp, "3 CbcHeuristicDiveCoefficient heuristicDiveCoefficient(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicDiveCoefficient"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicDiveCoefficient);\n"); } // Copy constructor CbcHeuristicDiveCoefficient::CbcHeuristicDiveCoefficient(const CbcHeuristicDiveCoefficient & rhs) : CbcHeuristicDive(rhs) { } // Assignment operator CbcHeuristicDiveCoefficient & CbcHeuristicDiveCoefficient::operator=( const CbcHeuristicDiveCoefficient & rhs) { if (this != &rhs) { CbcHeuristicDive::operator=(rhs); } return *this; } bool CbcHeuristicDiveCoefficient::selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound) { int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); bestColumn = -1; bestRound = -1; // -1 rounds down, +1 rounds up double bestFraction = COIN_DBL_MAX; int bestLocks = COIN_INT_MAX; bool allTriviallyRoundableSoFar = true; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; double fraction = value - floor(value); int round = 0; if (fabs(floor(value + 0.5) - value) > integerTolerance) { int nDownLocks = downLocks_[i]; int nUpLocks = upLocks_[i]; if (allTriviallyRoundableSoFar || (nDownLocks > 0 && nUpLocks > 0)) { if (allTriviallyRoundableSoFar && nDownLocks > 0 && nUpLocks > 0) { allTriviallyRoundableSoFar = false; bestFraction = COIN_DBL_MAX; bestLocks = COIN_INT_MAX; } // the variable cannot be rounded int nLocks = nDownLocks; if (nDownLocks < nUpLocks) round = -1; else if (nDownLocks > nUpLocks) { round = 1; fraction = 1.0 - fraction; nLocks = nUpLocks; } else if (fraction < 0.5) round = -1; else { round = 1; fraction = 1.0 - fraction; nLocks = nUpLocks; } // if variable is not binary, penalize it if (!solver->isBinary(iColumn)) fraction *= 1000.0; if (nLocks < bestLocks || (nLocks == bestLocks && fraction < bestFraction)) { bestColumn = iColumn; bestLocks = nLocks; bestFraction = fraction; bestRound = round; } } } } return allTriviallyRoundableSoFar; } Cbc-2.8.12/src/Cbc_ampl.cpp0000644000076600007660000015221412334344317013755 0ustar coincoin/* $Id: Cbc_ampl.cpp 2034 2014-05-13 07:25:03Z forrest $ */ /**************************************************************** Copyright (C) 1997-2000 Lucent Technologies Modifications for Coin - Copyright (C) 2006, International Business Machines Corporation and others. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the name of Lucent or any of its entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****************************************************************/ /*! \file Cbc_ampl.cpp Interface routines for AMPL. */ #include "CbcConfig.h" #ifdef COIN_HAS_ASL #ifdef HAVE_UNISTD_H # include "unistd.h" #endif #include "CoinUtilsConfig.h" #include "CoinHelperFunctions.hpp" #include "CoinModel.hpp" #include "CoinSort.hpp" #include "CoinPackedMatrix.hpp" #include "CoinMpsIO.hpp" #include "CoinFloatEqual.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #endif #include "Cbc_ampl.h" extern "C" { # include "getstub.h" # include "asl_pfgh.h" } #include #include /* so decodePhrase and clpCheck can access */ static ampl_info * saveInfo = NULL; // Set to 1 if algorithm found static char algFound[20] = ""; static char* checkPhrase(Option_Info *oi, keyword *kw, char *v) { if (strlen(v)) printf("string %s\n", v); // Say algorithm found strcpy(algFound, kw->desc); return v; } static char* checkPhrase2(Option_Info *oi, keyword *kw, char *v) { if (strlen(v)) printf("string %s\n", v); // put out keyword saveInfo->arguments = (char **) realloc(saveInfo->arguments, (saveInfo->numberArguments + 1) * sizeof(char *)); saveInfo->arguments[saveInfo->numberArguments++] = strdup(kw->desc); return v; } static fint decodePhrase(char * phrase, ftnlen length) { char * blank = strchr(phrase, ' '); if (blank) { /* split arguments */ *blank = '\0'; saveInfo->arguments = (char **) realloc(saveInfo->arguments, (saveInfo->numberArguments + 2) * sizeof(char *)); saveInfo->arguments[saveInfo->numberArguments++] = strdup(phrase); *blank = ' '; phrase = blank + 1; /* move on */ if (strlen(phrase)) saveInfo->arguments[saveInfo->numberArguments++] = strdup(phrase); } else if (strlen(phrase)) { saveInfo->arguments = (char **) realloc(saveInfo->arguments, (saveInfo->numberArguments + 1) * sizeof(char *)); saveInfo->arguments[saveInfo->numberArguments++] = strdup(phrase); } return 0; } static void sos_kludge(int nsos, int *sosbeg, double *sosref, int * sosind) { // Adjust sosref if necessary to make monotonic increasing int i, j, k; // first sort for (i = 0; i < nsos; i++) { k = sosbeg[i]; int end = sosbeg[i+1]; CoinSort_2(sosref + k, sosref + end, sosind + k); } double t, t1; for (i = j = 0; i++ < nsos; ) { k = sosbeg[i]; t = sosref[j]; while (++j < k) { t1 = sosref[j]; t += 1e-10; if (t1 <= t) sosref[j] = t1 = t + 1e-10; t = t1; } } } static char xxxxxx[20]; #define VP (char*) static keyword keywds[] = { /* must be sorted */ { const_cast("barrier"), checkPhrase, (char *) xxxxxx , const_cast("-barrier")}, { const_cast("dual"), checkPhrase, (char *) xxxxxx , const_cast("-dualsimplex")}, { const_cast("help"), checkPhrase2, (char *) xxxxxx , const_cast("-?")}, { const_cast("initial"), checkPhrase, (char *) xxxxxx , const_cast("-initialsolve")}, { const_cast("max"), checkPhrase2, (char *) xxxxxx , const_cast("-maximize")}, { const_cast("maximize"), checkPhrase2, (char *) xxxxxx , const_cast("-maximize")}, { const_cast("primal"), checkPhrase, (char *) xxxxxx , const_cast("-primalsimplex")}, { const_cast("quit"), checkPhrase2, (char *) xxxxxx , const_cast("-quit")}, { const_cast("wantsol"), WS_val, NULL, const_cast("write .sol file (without -AMPL)")} }; static Option_Info Oinfo = { const_cast("cbc"), const_cast("CBC " CBC_VERSION), const_cast("cbc_options"), keywds, nkeywds, 0, 0, 0, decodePhrase, 0, 0, 0, 20130502 }; // strdup used to avoid g++ compiler warning static SufDecl suftab[] = { #ifdef JJF_ZERO { const_cast("current"), 0, ASL_Sufkind_con | ASL_Sufkind_outonly }, { const_cast("current"), 0, ASL_Sufkind_var | ASL_Sufkind_outonly }, { const_cast("direction"), 0, ASL_Sufkind_var }, { const_cast("down"), 0, ASL_Sufkind_con | ASL_Sufkind_outonly }, { const_cast("down"), 0, ASL_Sufkind_var | ASL_Sufkind_outonly }, { const_cast("priority"), 0, ASL_Sufkind_var }, #endif { const_cast("cut"), 0, ASL_Sufkind_con }, { const_cast("direction"), 0, ASL_Sufkind_var }, { const_cast("downPseudocost"), 0, ASL_Sufkind_var | ASL_Sufkind_real }, { const_cast("priority"), 0, ASL_Sufkind_var }, { const_cast("ref"), 0, ASL_Sufkind_var | ASL_Sufkind_real }, { const_cast("sos"), 0, ASL_Sufkind_var }, { const_cast("sos"), 0, ASL_Sufkind_con }, { const_cast("sosno"), 0, ASL_Sufkind_var | ASL_Sufkind_real }, { const_cast("sosref"), 0, ASL_Sufkind_var | ASL_Sufkind_real }, { const_cast("special"), 0, ASL_Sufkind_var }, { const_cast("special"), 0, ASL_Sufkind_con }, /*{ const_cast("special"), 0, ASL_Sufkind_con },*/ { const_cast("sstatus"), 0, ASL_Sufkind_var, 0 }, { const_cast("sstatus"), 0, ASL_Sufkind_con, 0 }, { const_cast("upPseudocost"), 0, ASL_Sufkind_var | ASL_Sufkind_real } #ifdef JJF_ZERO { const_cast("unbdd"), 0, ASL_Sufkind_var | ASL_Sufkind_outonly}, { const_cast("up"), 0, ASL_Sufkind_con | ASL_Sufkind_outonly }, { const_cast("up"), 0, ASL_Sufkind_var | ASL_Sufkind_outonly } #endif }; #include "float.h" #include "limits.h" static ASL *asl = NULL; static FILE *nl = NULL; static void mip_stuff(void) { int i; double *pseudoUp, *pseudoDown; int *priority, *direction; // To label cuts (there will be other uses for special) int *cut; // To label special variables - at present 1= must be >= 1 or <= -1 int * special; SufDesc *dpup, *dpdown, *dpri, *ddir, *dcut, *dspecial; ddir = suf_get("direction", ASL_Sufkind_var); direction = ddir->u.i; dpri = suf_get("priority", ASL_Sufkind_var); priority = dpri->u.i; dspecial = suf_get("special", ASL_Sufkind_con); dcut = suf_get("cut", ASL_Sufkind_con); cut = dcut->u.i; if (!cut) { // try special dcut = suf_get("special", ASL_Sufkind_con); cut = dcut->u.i; } dspecial = suf_get("special", ASL_Sufkind_var); special = dspecial->u.i; dpdown = suf_get("downPseudocost", ASL_Sufkind_var); pseudoDown = dpdown->u.r; dpup = suf_get("upPseudocost", ASL_Sufkind_var); pseudoUp = dpup->u.r; assert(saveInfo); int numberColumns = saveInfo->numberColumns; if (direction) { int baddir = 0; saveInfo->branchDirection = (int *) malloc(numberColumns * sizeof(int)); for (i = 0; i < numberColumns; i++) { int value = direction[i]; if (value < -1 || value > 1) { baddir++; value = 0; } saveInfo->branchDirection[i] = value; } if (baddir) fprintf(Stderr, "Treating %d .direction values outside [-1, 1] as 0.\n", baddir); } if (priority) { int badpri = 0; saveInfo->priorities = (int *) malloc(numberColumns * sizeof(int)); for (i = 0; i < numberColumns; i++) { int value = priority[i]; if (value < 0) { badpri++; value = 0; } saveInfo->priorities[i] = value; } if (badpri) fprintf(Stderr, "Treating %d negative .priority values as 0\n", badpri); } if (special) { int badspecial = 0; saveInfo->special = (int *) malloc(numberColumns * sizeof(int)); for (i = 0; i < numberColumns; i++) { int value = special[i]; if (value < 0) { badspecial++; value = 0; } saveInfo->special[i] = value; } if (badspecial) fprintf(Stderr, "Treating %d negative special values as 0\n", badspecial); } int numberRows = saveInfo->numberRows; if (cut) { int badcut = 0; saveInfo->cut = (int *) malloc(numberRows * sizeof(int)); for (i = 0; i < numberRows; i++) { int value = cut[i]; if (value < 0) { badcut++; value = 0; } saveInfo->cut[i] = value; } if (badcut) fprintf(Stderr, "Treating %d negative cut values as 0\n", badcut); } if (pseudoDown || pseudoUp) { int badpseudo = 0; if (!pseudoDown || !pseudoUp) fprintf(Stderr, "Only one set of pseudocosts - assumed same\n"); saveInfo->pseudoDown = (double *) malloc(numberColumns * sizeof(double)); saveInfo->pseudoUp = (double *) malloc(numberColumns * sizeof(double)); for (i = 0; i < numberColumns; i++) { double valueD = 0.0, valueU = 0.0; if (pseudoDown) { valueD = pseudoDown[i]; if (valueD < 0) { badpseudo++; valueD = 0.0; } } if (pseudoUp) { valueU = pseudoUp[i]; if (valueU < 0) { badpseudo++; valueU = 0.0; } } if (!valueD) valueD = valueU; if (!valueU) valueU = valueD; saveInfo->pseudoDown[i] = valueD; saveInfo->pseudoUp[i] = valueU; } if (badpseudo) fprintf(Stderr, "Treating %d negative pseudoCosts as 0.0\n", badpseudo); } } static void stat_map(int *stat, int n, int *map, int mx, const char *what) { int bad, i, i1 = 0, j, j1 = 0; static char badfmt[] = "Coin driver: %s[%d] = %d\n"; for (i = bad = 0; i < n; i++) { if ((j = stat[i]) >= 0 && j <= mx) stat[i] = map[j]; else { stat[i] = 0; i1 = i; j1 = j; if (!bad++) fprintf(Stderr, badfmt, what, i, j); } } if (bad > 1) { if (bad == 2) fprintf(Stderr, badfmt, what, i1, j1); else fprintf(Stderr, "Coin driver: %d messages about bad %s values suppressed.\n", bad - 1, what); } } int readAmpl(ampl_info * info, int argc, char **argv, void ** coinModel) { char *stub; ograd *og; int i; SufDesc *csd; SufDesc *rsd; /*bool *basis, *lower;*/ /*double *LU, *c, lb, objadj, *rshift, *shift, t, ub, *x, *x0, *x1;*/ char * environment = getenv("cbc_options"); char tempBuffer[20]; double * obj; double * columnLower; double * columnUpper; double * rowLower; double * rowUpper; char ** saveArgv = argv; char fileName[1000]; if (argc > 1) strcpy(fileName, argv[1]); else fileName[0] = '\0'; int nonLinearType = -1; // testosi parameter - if >= 10 then go in through coinModel for (i = 1; i < argc; i++) { if (!strncmp(argv[i], "testosi", 7)) { char * equals = strchr(argv[i], '='); if (equals && atoi(equals + 1) >= 10 && atoi(equals + 1) <= 20) { nonLinearType = atoi(equals + 1); break; } } } int saveArgc = argc; if (info->numberRows != -1234567) memset(info, 0, sizeof(ampl_info)); // overwrite unless magic number set /* save so can be accessed by decodePhrase */ saveInfo = info; info->numberArguments = 0; info->arguments = (char **) malloc(2 * sizeof(char *)); info->arguments[info->numberArguments++] = strdup("ampl"); info->arguments[info->numberArguments++] = strdup("cbc"); asl = ASL_alloc(ASL_read_f); stub = getstub(&argv, &Oinfo); if (!stub) usage_ASL(&Oinfo, 1); nl = jac0dim(stub, 0); suf_declare(suftab, sizeof(suftab) / sizeof(SufDecl)); /* set A_vals to get the constraints column-wise (malloc so can be freed) */ A_vals = (double *) malloc(nzc * sizeof(double)); if (!A_vals) { printf("no memory\n"); return 1; } /* say we want primal solution */ want_xpi0 = 1; /* for basis info */ info->columnStatus = (int *) malloc(n_var * sizeof(int)); for (int i=0;icolumnStatus[i]=3; info->rowStatus = (int *) malloc(n_con * sizeof(int)); for (int i=0;irowStatus[i]=1; csd = suf_iput("sstatus", ASL_Sufkind_var, info->columnStatus); rsd = suf_iput("sstatus", ASL_Sufkind_con, info->rowStatus); if (!(nlvc + nlvo) && nonLinearType < 10) { /* read linear model*/ f_read(nl, 0); // see if any sos if (true) { char *sostype; int nsosnz, *sosbeg, *sosind, * sospri; double *sosref; int nsos; int i = ASL_suf_sos_explict_free; int copri[2], **p_sospri; copri[0] = 0; copri[1] = 0; p_sospri = &sospri; nsos = suf_sos(i, &nsosnz, &sostype, p_sospri, copri, &sosbeg, &sosind, &sosref); if (nsos) { info->numberSos = nsos; info->sosType = (char *) malloc(nsos); info->sosPriority = (int *) malloc(nsos * sizeof(int)); info->sosStart = (int *) malloc((nsos + 1) * sizeof(int)); info->sosIndices = (int *) malloc(nsosnz * sizeof(int)); info->sosReference = (double *) malloc(nsosnz * sizeof(double)); sos_kludge(nsos, sosbeg, sosref, sosind); for (int i = 0; i < nsos; i++) { char ichar = sostype[i]; assert (ichar == '1' || ichar == '2'); info->sosType[i] = static_cast(ichar - '0'); } memcpy(info->sosPriority, sospri, nsos*sizeof(int)); memcpy(info->sosStart, sosbeg, (nsos + 1)*sizeof(int)); memcpy(info->sosIndices, sosind, nsosnz*sizeof(int)); memcpy(info->sosReference, sosref, nsosnz*sizeof(double)); } } /*sos_finish(&specialOrderedInfo, 0, &j, 0, 0, 0, 0, 0);*/ Oinfo.uinfo = tempBuffer; if (getopts(argv, &Oinfo)) return 1; /* objective*/ obj = (double *) malloc(n_var * sizeof(double)); for (i = 0; i < n_var; i++) obj[i] = 0.0; if (n_obj) { for (og = Ograd[0]; og; og = og->next) obj[og->varno] = og->coef; } if (objtype[0]) info->direction = -1.0; else info->direction = 1.0; info->offset = objconst(0); /* Column bounds*/ columnLower = (double *) malloc(n_var * sizeof(double)); columnUpper = (double *) malloc(n_var * sizeof(double)); for (i = 0; i < n_var; i++) { columnLower[i] = LUv[2*i]; if (columnLower[i] <= negInfinity) columnLower[i] = -COIN_DBL_MAX; columnUpper[i] = LUv[2*i+1]; if (columnUpper[i] >= Infinity) columnUpper[i] = COIN_DBL_MAX; } /* Row bounds*/ rowLower = (double *) malloc(n_con * sizeof(double)); rowUpper = (double *) malloc(n_con * sizeof(double)); for (i = 0; i < n_con; i++) { rowLower[i] = LUrhs[2*i]; if (rowLower[i] <= negInfinity) rowLower[i] = -COIN_DBL_MAX; rowUpper[i] = LUrhs[2*i+1]; if (rowUpper[i] >= Infinity) rowUpper[i] = COIN_DBL_MAX; } info->numberRows = n_con; info->numberColumns = n_var; info->numberElements = nzc; info->numberBinary = nbv; info->numberIntegers = niv + nbv; info->objective = obj; info->rowLower = rowLower; info->rowUpper = rowUpper; info->columnLower = columnLower; info->columnUpper = columnUpper; info->starts = A_colstarts; /*A_colstarts=NULL;*/ info->rows = A_rownos; /*A_rownos=NULL;*/ info->elements = A_vals; /*A_vals=NULL;*/ info->primalSolution = NULL; /* put in primalSolution if exists */ if (X0) { info->primalSolution = (double *) malloc(n_var * sizeof(double)); memcpy(info->primalSolution, X0, n_var*sizeof(double)); } info->dualSolution = NULL; if (niv + nbv > 0) mip_stuff(); // get any extra info if ((!(niv + nbv) && (csd->kind & ASL_Sufkind_input)) || (rsd->kind & ASL_Sufkind_input)) { /* convert status - need info on map */ static int map[] = {1, 3, 1, 1, 2, 1, 1}; stat_map(info->columnStatus, n_var, map, 6, "incoming columnStatus"); stat_map(info->rowStatus, n_con, map, 6, "incoming rowStatus"); } else { /* all slack basis */ // leave status for output */ #ifdef JJF_ZERO free(info->rowStatus); info->rowStatus = NULL; free(info->columnStatus); info->columnStatus = NULL; #endif } } else { // QP // Add .nl if not there if (!strstr(fileName, ".nl")) strcat(fileName, ".nl"); CoinModel * model = new CoinModel((nonLinearType > 10) ? 2 : 1, fileName, info); if (model->numberRows() > 0 || model->numberColumns() > 0) *coinModel = (void *) model; Oinfo.uinfo = tempBuffer; if (getopts(argv, &Oinfo)) return 1; Oinfo.wantsol = 1; if (objtype[0]) info->direction = -1.0; else info->direction = 1.0; model->setOptimizationDirection(info->direction); info->offset = objconst(0); info->numberRows = n_con; info->numberColumns = n_var; info->numberElements = nzc; info->numberBinary = nbv; int numberIntegers = niv + nlvci + nlvoi + nbv; if (nlvci + nlvoi + nlvc + nlvo) { // Non linear // No idea if there are overlaps so compute int numberIntegers = 0; for ( i = 0; i < n_var; i++) { if (model->columnIsInteger(i)) numberIntegers++; } } info->numberIntegers = numberIntegers; // Say nonlinear if it is info->nonLinear = nlvc + nlvo; if (numberIntegers > 0) { mip_stuff(); // get any extra info if (info->cut) model->setCutMarker(info->numberRows, info->cut); if (info->priorities) model->setPriorities(info->numberColumns, info->priorities); } } /* add -solve - unless something there already - also check for sleep=yes */ { int found = 0; int foundLog = 0; int foundSleep = 0; const char * something[] = {"solve", "branch", "duals", "primals", "user"}; for (i = 0; i < info->numberArguments; i++) { unsigned int j; const char * argument = info->arguments[i]; for (j = 0; j < sizeof(something) / sizeof(char *); j++) { const char * check = something[j]; if (!strncmp(argument, check, sizeof(check))) { found = (int)(j + 1); } else if (!strncmp(argument, "log", 3)) { foundLog = 1; } else if (!strncmp(argument, "sleep", 5)) { foundSleep = 1; } } } if (foundLog) { /* print options etc */ for (i = 0; i < saveArgc; i++) printf("%s ", saveArgv[i]); printf("\n"); if (environment) printf("env %s\n", environment); /*printf("%d rows %d columns %d elements\n",n_con,n_var,nzc);*/ } if (!found) { if (!strlen(algFound)) { info->arguments = (char **) realloc(info->arguments, (info->numberArguments + 1) * sizeof(char *)); info->arguments[info->numberArguments++] = strdup("-solve"); } else { // use algorithm from keyword info->arguments = (char **) realloc(info->arguments, (info->numberArguments + 1) * sizeof(char *)); info->arguments[info->numberArguments++] = strdup(algFound); } } if (foundSleep) { /* let user copy .nl file */ fprintf(stderr, "You can copy .nl file %s for debug purposes or attach debugger\n", saveArgv[1]); fprintf(stderr, "Type q to quit, anything else to continue\n"); int getChar = getc(stdin); if (getChar == 'q' || getChar == 'Q') exit(1); } } /* add -quit */ info->arguments = (char **) realloc(info->arguments, (info->numberArguments + 1) * sizeof(char *)); info->arguments[info->numberArguments++] = strdup("-quit"); return 0; } void freeArrays1(ampl_info * info) { free(info->objective); info->objective = NULL; free(info->rowLower); info->rowLower = NULL; free(info->rowUpper); info->rowUpper = NULL; free(info->columnLower); info->columnLower = NULL; free(info->columnUpper); info->columnUpper = NULL; /* this one not freed by ASL_free */ free(info->elements); info->elements = NULL; free(info->primalSolution); info->primalSolution = NULL; free(info->dualSolution); info->dualSolution = NULL; /*free(info->rowStatus); info->rowStatus=NULL; free(info->columnStatus); info->columnStatus=NULL;*/ } void freeArrays2(ampl_info * info) { free(info->primalSolution); info->primalSolution = NULL; free(info->dualSolution); info->dualSolution = NULL; free(info->rowStatus); info->rowStatus = NULL; free(info->columnStatus); info->columnStatus = NULL; free(info->priorities); info->priorities = NULL; free(info->branchDirection); info->branchDirection = NULL; free(info->pseudoDown); info->pseudoDown = NULL; free(info->pseudoUp); info->pseudoUp = NULL; free(info->sosType); info->sosType = NULL; free(info->sosPriority); info->sosPriority = NULL; free(info->sosStart); info->sosStart = NULL; free(info->sosIndices); info->sosIndices = NULL; free(info->sosReference); info->sosReference = NULL; free(info->cut); info->cut = NULL; ASL_free(&asl); } void freeArgs(ampl_info * info) { int i; for ( i = 0; i < info->numberArguments; i++) free(info->arguments[i]); free(info->arguments); } int ampl_obj_prec() { int precision = obj_prec(); if (precision<=0) precision=15; return precision; } void writeAmpl(ampl_info * info) { char buf[1000]; typedef struct { const char *msg; int code; int wantObj; } Sol_info; static Sol_info solinfo[] = { { "optimal solution", 000, 1 }, { "infeasible", 200, 1 }, { "unbounded", 300, 0 }, { "iteration limit etc", 400, 1 }, { "solution limit", 401, 1 }, { "ran out of space", 500, 0 }, { "status unknown", 501, 1 }, { "bug!", 502, 0 }, { "best MIP solution so far restored", 101, 1 }, { "failed to restore best MIP solution", 503, 1 }, { "optimal (?) solution", 100, 1 } }; /* convert status - need info on map */ static int map[] = {0, 3, 4, 1}; sprintf(buf, "%s %s", Oinfo.bsname, info->buffer); solve_result_num = solinfo[info->problemStatus].code; if (info->columnStatus) { stat_map(info->columnStatus, n_var, map, 4, "outgoing columnStatus"); stat_map(info->rowStatus, n_con, map, 4, "outgoing rowStatus"); suf_iput("sstatus", ASL_Sufkind_var, info->columnStatus); suf_iput("sstatus", ASL_Sufkind_con, info->rowStatus); } write_sol(buf, info->primalSolution, info->dualSolution, &Oinfo); } /* Read a problem from AMPL nl file */ CoinModel::CoinModel( int nonLinear, const char * fileName, const void * info) : CoinBaseModel(), maximumRows_(0), maximumColumns_(0), numberElements_(0), maximumElements_(0), numberQuadraticElements_(0), maximumQuadraticElements_(0), rowLower_(NULL), rowUpper_(NULL), rowType_(NULL), objective_(NULL), columnLower_(NULL), columnUpper_(NULL), integerType_(NULL), columnType_(NULL), start_(NULL), elements_(NULL), packedMatrix_(NULL), quadraticElements_(NULL), sortIndices_(NULL), sortElements_(NULL), sortSize_(0), sizeAssociated_(0), associated_(NULL), numberSOS_(0), startSOS_(NULL), memberSOS_(NULL), typeSOS_(NULL), prioritySOS_(NULL), referenceSOS_(NULL), priority_(NULL), cut_(NULL), moreInfo_(NULL), type_(-1), noNames_(false), links_(0) { problemName_ = ""; int status = 0; if (!strcmp(fileName, "-") || !strcmp(fileName, "stdin")) { // stdin } else { std::string name = fileName; bool readable = fileCoinReadable(name); if (!readable) { std::cerr << "Unable to open file " << fileName << std::endl; status = -1; } } if (!status) { gdb(nonLinear, fileName, info); } } #ifdef JJF_ZERO static real qterm(ASL *asl, fint *colq, fint *rowq, real *delsq) { double t, t1, *x, *x0, *xe; fint *rq0, *rqe; t = 0.; x0 = x = X0; xe = x + n_var; rq0 = rowq; while (x < xe) { t1 = *x++; rqe = rq0 + *++colq; while (rowq < rqe) t += t1 * x0[*rowq++]**delsq++; } return 0.5 * t; } #endif // stolen from IPopt with changes typedef struct { double obj_sign_; ASL_pfgh * asl_; double * non_const_x_; int * column_; // for jacobian int * rowStart_; double * gradient_; double * constraintValues_; int nz_h_full_; // number of nonzeros in hessian int nerror_; bool objval_called_with_current_x_; bool conval_called_with_current_x_; bool jacval_called_with_current_x_; } CbcAmplInfo; void CoinModel::gdb( int nonLinear, const char * fileName, const void * info) { const ampl_info * amplInfo = (const ampl_info *) info; ograd *og = NULL; int i; SufDesc *csd = NULL; SufDesc *rsd = NULL; /*bool *basis, *lower;*/ /*double *LU, *c, lb, objadj, *rshift, *shift, t, ub, *x, *x0, *x1;*/ //char tempBuffer[20]; double * objective = NULL; double * columnLower = NULL; double * columnUpper = NULL; double * rowLower = NULL; double * rowUpper = NULL; int * columnStatus = NULL; int * rowStatus = NULL; int numberRows = -1; int numberColumns = -1; int numberElements = -1; int numberBinary = -1; int numberIntegers = -1; int numberAllNonLinearBoth = 0; int numberIntegerNonLinearBoth = 0; int numberAllNonLinearConstraints = 0; int numberIntegerNonLinearConstraints = 0; int numberAllNonLinearObjective = 0; int numberIntegerNonLinearObjective = 0; double * primalSolution = NULL; double direction = 1.0; char * stub = strdup(fileName); CoinPackedMatrix matrixByRow; fint ** colqp = NULL; int *z = NULL; if (nonLinear == 0) { // linear asl = ASL_alloc(ASL_read_f); nl = jac0dim(stub, 0); free(stub); suf_declare(suftab, sizeof(suftab) / sizeof(SufDecl)); /* set A_vals to get the constraints column-wise (malloc so can be freed) */ A_vals = (double *) malloc(nzc * sizeof(double)); if (!A_vals) { printf("no memory\n"); return ; } /* say we want primal solution */ want_xpi0 = 1; /* for basis info */ columnStatus = (int *) malloc(n_var * sizeof(int)); rowStatus = (int *) malloc(n_con * sizeof(int)); csd = suf_iput("sstatus", ASL_Sufkind_var, columnStatus); rsd = suf_iput("sstatus", ASL_Sufkind_con, rowStatus); /* read linear model*/ f_read(nl, 0); // see if any sos if (true) { char *sostype; int nsosnz, *sosbeg, *sosind, * sospri; double *sosref; int nsos; int i = ASL_suf_sos_explict_free; int copri[2], **p_sospri; copri[0] = 0; copri[1] = 0; p_sospri = &sospri; nsos = suf_sos(i, &nsosnz, &sostype, p_sospri, copri, &sosbeg, &sosind, &sosref); if (nsos) { abort(); #ifdef JJF_ZERO info->numberSos = nsos; info->sosType = (char *) malloc(nsos); info->sosPriority = (int *) malloc(nsos * sizeof(int)); info->sosStart = (int *) malloc((nsos + 1) * sizeof(int)); info->sosIndices = (int *) malloc(nsosnz * sizeof(int)); info->sosReference = (double *) malloc(nsosnz * sizeof(double)); sos_kludge(nsos, sosbeg, sosref, sosind); for (int i = 0; i < nsos; i++) { int ichar = sostype[i]; assert (ichar == '1' || ichar == '2'); info->sosType[i] = ichar - '0'; } memcpy(info->sosPriority, sospri, nsos*sizeof(int)); memcpy(info->sosStart, sosbeg, (nsos + 1)*sizeof(int)); memcpy(info->sosIndices, sosind, nsosnz*sizeof(int)); memcpy(info->sosReference, sosref, nsosnz*sizeof(double)); #endif } } /*sos_finish(&specialOrderedInfo, 0, &j, 0, 0, 0, 0, 0);*/ //Oinfo.uinfo = tempBuffer; //if (getopts(argv, &Oinfo)) //return 1; /* objective*/ objective = (double *) malloc(n_var * sizeof(double)); for (i = 0; i < n_var; i++) objective[i] = 0.0; if (n_obj) { for (og = Ograd[0]; og; og = og->next) objective[og->varno] = og->coef; } if (objtype[0]) direction = -1.0; else direction = 1.0; objectiveOffset_ = objconst(0); /* Column bounds*/ columnLower = (double *) malloc(n_var * sizeof(double)); columnUpper = (double *) malloc(n_var * sizeof(double)); for (i = 0; i < n_var; i++) { columnLower[i] = LUv[2*i]; if (columnLower[i] <= negInfinity) columnLower[i] = -COIN_DBL_MAX; columnUpper[i] = LUv[2*i+1]; if (columnUpper[i] >= Infinity) columnUpper[i] = COIN_DBL_MAX; } /* Row bounds*/ rowLower = (double *) malloc(n_con * sizeof(double)); rowUpper = (double *) malloc(n_con * sizeof(double)); for (i = 0; i < n_con; i++) { rowLower[i] = LUrhs[2*i]; if (rowLower[i] <= negInfinity) rowLower[i] = -COIN_DBL_MAX; rowUpper[i] = LUrhs[2*i+1]; if (rowUpper[i] >= Infinity) rowUpper[i] = COIN_DBL_MAX; } numberRows = n_con; numberColumns = n_var; numberElements = nzc; numberBinary = nbv; numberIntegers = niv; /* put in primalSolution if exists */ if (X0) { primalSolution = (double *) malloc(n_var * sizeof(double)); memcpy( primalSolution, X0, n_var*sizeof(double)); } //double * dualSolution=NULL; if (niv + nbv > 0) mip_stuff(); // get any extra info if ((!(niv + nbv) && (csd->kind & ASL_Sufkind_input)) || (rsd->kind & ASL_Sufkind_input)) { /* convert status - need info on map */ static int map[] = {1, 3, 1, 1, 2, 1, 1}; stat_map(columnStatus, n_var, map, 6, "incoming columnStatus"); stat_map(rowStatus, n_con, map, 6, "incoming rowStatus"); } else { /* all slack basis */ // leave status for output */ #ifdef JJF_ZERO free(rowStatus); rowStatus = NULL; free(columnStatus); columnStatus = NULL; #endif } CoinPackedMatrix columnCopy(true, numberRows, numberColumns, numberElements, A_vals, A_rownos, A_colstarts, NULL); matrixByRow.reverseOrderedCopyOf(columnCopy); } else if (nonLinear == 1) { // quadratic asl = ASL_alloc(ASL_read_fg); nl = jac0dim(stub, (ftnlen) strlen(stub)); free(stub); suf_declare(suftab, sizeof(suftab) / sizeof(SufDecl)); /* read model*/ X0 = (double*) malloc(n_var * sizeof(double)); CoinZeroN(X0, n_var); qp_read(nl, 0); assert (n_obj == 1); int nz = 1 + n_con; colqp = (fint**) malloc(nz * (2 * sizeof(int*) + sizeof(double*))); fint ** rowqp = colqp + nz; double ** delsqp = (double **)(rowqp + nz); z = (int*) malloc(nz * sizeof(int)); for (i = 0; i <= n_con; i++) { z[i] = nqpcheck(-i, rowqp + i, colqp + i, delsqp + i); } qp_opify(); /* objective*/ objective = (double *) malloc(n_var * sizeof(double)); for (i = 0; i < n_var; i++) objective[i] = 0.0; if (n_obj) { for (og = Ograd[0]; og; og = og->next) objective[og->varno] = og->coef; } if (objtype[0]) direction = -1.0; else direction = 1.0; objectiveOffset_ = objconst(0); /* Column bounds*/ columnLower = (double *) malloc(n_var * sizeof(double)); columnUpper = (double *) malloc(n_var * sizeof(double)); for (i = 0; i < n_var; i++) { columnLower[i] = LUv[2*i]; if (columnLower[i] <= negInfinity) columnLower[i] = -COIN_DBL_MAX; columnUpper[i] = LUv[2*i+1]; if (columnUpper[i] >= Infinity) columnUpper[i] = COIN_DBL_MAX; } // Build by row from scratch //matrixByRow.reserve(n_var,nzc,true); // say row orderded matrixByRow.transpose(); /* Row bounds*/ rowLower = (double *) malloc(n_con * sizeof(double)); rowUpper = (double *) malloc(n_con * sizeof(double)); CoinBigIndex * rowStart = new CoinBigIndex [n_con+1]; int * column = new int [nzc]; double * element = new double [nzc]; rowStart[0] = 0; numberElements = 0; for (i = 0; i < n_con; i++) { rowLower[i] = LUrhs[2*i]; if (rowLower[i] <= negInfinity) rowLower[i] = -COIN_DBL_MAX; rowUpper[i] = LUrhs[2*i+1]; if (rowUpper[i] >= Infinity) rowUpper[i] = COIN_DBL_MAX; for (cgrad * cg = Cgrad[i]; cg; cg = cg->next) { column[numberElements] = cg->varno; element[numberElements++] = cg->coef; } rowStart[i+1] = numberElements; } assert (numberElements == nzc); matrixByRow.appendRows(n_con, rowStart, column, element); delete [] rowStart; delete [] column; delete [] element; numberRows = n_con; numberColumns = n_var; //numberElements=nzc; numberBinary = nbv; numberIntegers = niv; numberAllNonLinearBoth = nlvb; numberIntegerNonLinearBoth = nlvbi; numberAllNonLinearConstraints = nlvc; numberIntegerNonLinearConstraints = nlvci; numberAllNonLinearObjective = nlvo; numberIntegerNonLinearObjective = nlvoi; /* say we want primal solution */ want_xpi0 = 1; //double * dualSolution=NULL; // save asl // Fix memory leak one day CbcAmplInfo * info = new CbcAmplInfo; //amplGamsData_ = info; info->asl_ = NULL; // as wrong form asl; info->nz_h_full_ = -1; // number of nonzeros in hessian info->objval_called_with_current_x_ = false; info->nerror_ = 0; info->obj_sign_ = direction; info->conval_called_with_current_x_ = false; info->non_const_x_ = NULL; info->jacval_called_with_current_x_ = false; info->rowStart_ = NULL; info->column_ = NULL; info->gradient_ = NULL; info->constraintValues_ = NULL; } else if (nonLinear == 2) { // General nonlinear! //ASL_pfgh* asl = (ASL_pfgh*)ASL_alloc(ASL_read_pfgh); asl = ASL_alloc(ASL_read_pfgh); nl = jac0dim(stub, (ftnlen) strlen(stub)); free(stub); suf_declare(suftab, sizeof(suftab) / sizeof(SufDecl)); /* read model*/ X0 = (double*) malloc(n_var * sizeof(double)); CoinZeroN(X0, n_var); // code stolen from Ipopt int retcode = pfgh_read(nl, ASL_return_read_err | ASL_findgroups); switch (retcode) { case ASL_readerr_none : {} break; case ASL_readerr_nofile : { printf( "Cannot open .nl file\n"); exit(-1); } break; case ASL_readerr_nonlin : { assert(false); // this better not be an error! printf( "model involves nonlinearities (ed0read)\n"); exit(-1); } break; case ASL_readerr_argerr : { printf( "user-defined function with bad args\n"); exit(-1); } break; case ASL_readerr_unavail : { printf( "user-defined function not available\n"); exit(-1); } break; case ASL_readerr_corrupt : { printf( "corrupt .nl file\n"); exit(-1); } break; case ASL_readerr_bug : { printf( "bug in .nl reader\n"); exit(-1); } break; case ASL_readerr_CLP : { printf( "ASL error message: \"solver cannot handle CLP extensions\"\n"); exit(-1); } break; default: { printf( "Unknown error in stub file read. retcode = %d\n", retcode); exit(-1); } break; } // see "changes" in solvers directory of ampl code... hesset(1, 0, 1, 0, nlc); assert (n_obj == 1); // find the nonzero structure for the hessian // parameters to sphsetup: int coeff_obj = 1; // coefficient of the objective fn ??? int mult_supplied = 1; // multipliers will be supplied int uptri = 1; // only need the upper triangular part // save asl // Fix memory leak one day CbcAmplInfo * info = new CbcAmplInfo; moreInfo_ = (void *) info; //amplGamsData_ = info; info->asl_ = (ASL_pfgh *) asl; // This is not easy to get from ampl so save info->nz_h_full_ = sphsetup(-1, coeff_obj, mult_supplied, uptri); info->objval_called_with_current_x_ = false; info->nerror_ = 0; info->obj_sign_ = direction; info->conval_called_with_current_x_ = false; info->non_const_x_ = NULL; info->jacval_called_with_current_x_ = false; // Look at nonlinear if (nzc) { n_conjac[1] = nlc; // just nonlinear int * rowStart = new int [nlc+1]; info->rowStart_ = rowStart; // See how many int current_nz = 0; for (int i = 0; i < nlc; i++) { for (cgrad* cg = Cgrad[i]; cg; cg = cg->next) { current_nz++; } } // setup the structure int * column = new int [current_nz]; info->column_ = column; current_nz = 0; rowStart[0] = 0; for (int i = 0; i < nlc; i++) { for (cgrad* cg = Cgrad[i]; cg; cg = cg->next) { cg->goff = current_nz; //iRow[cg->goff] = i ; //jCol[cg->goff] = cg->varno + 1; column[cg->goff] = cg->varno ; current_nz++; } rowStart[i+1] = current_nz; } info->gradient_ = new double [nzc]; info->constraintValues_ = new double [nlc]; } /* objective*/ objective = (double *) malloc(n_var * sizeof(double)); for (i = 0; i < n_var; i++) objective[i] = 0.0; if (n_obj) { for (og = Ograd[0]; og; og = og->next) objective[og->varno] = og->coef; } if (objtype[0]) direction = -1.0; else direction = 1.0; objectiveOffset_ = objconst(0); /* Column bounds*/ columnLower = (double *) malloc(n_var * sizeof(double)); columnUpper = (double *) malloc(n_var * sizeof(double)); for (i = 0; i < n_var; i++) { columnLower[i] = LUv[2*i]; if (columnLower[i] <= negInfinity) columnLower[i] = -COIN_DBL_MAX; columnUpper[i] = LUv[2*i+1]; if (columnUpper[i] >= Infinity) columnUpper[i] = COIN_DBL_MAX; } // Build by row from scratch //matrixByRow.reserve(n_var,nzc,true); // say row orderded matrixByRow.transpose(); CoinBigIndex * rowStart = new CoinBigIndex [n_con+1]; int * column = new int [nzc]; double * element = new double [nzc]; rowStart[0] = 0; numberElements = 0; /* Row bounds*/ rowLower = (double *) malloc(n_con * sizeof(double)); rowUpper = (double *) malloc(n_con * sizeof(double)); for (i = 0; i < n_con; i++) { rowLower[i] = LUrhs[2*i]; if (rowLower[i] <= negInfinity) rowLower[i] = -COIN_DBL_MAX; rowUpper[i] = LUrhs[2*i+1]; if (rowUpper[i] >= Infinity) rowUpper[i] = COIN_DBL_MAX; for (cgrad * cg = Cgrad[i]; cg; cg = cg->next) { column[numberElements] = cg->varno; double value = cg->coef; if (!value) value = -1.2345e-29; element[numberElements++] = value; } rowStart[i+1] = numberElements; } assert (numberElements == nzc); matrixByRow.appendRows(n_con, rowStart, column, element); delete [] rowStart; delete [] column; delete [] element; numberRows = n_con; numberColumns = n_var; numberElements = nzc; numberBinary = nbv; numberIntegers = niv; numberAllNonLinearBoth = nlvb; numberIntegerNonLinearBoth = nlvbi; numberAllNonLinearConstraints = nlvc; numberIntegerNonLinearConstraints = nlvci; numberAllNonLinearObjective = nlvo; numberIntegerNonLinearObjective = nlvoi; /* say we want primal solution */ want_xpi0 = 1; //double * dualSolution=NULL; } else { abort(); } // set problem name problemName_ = "???"; // Build by row from scratch const double * element = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); for (i = 0; i < numberRows; i++) { addRow(rowLength[i], column + rowStart[i], element + rowStart[i], rowLower[i], rowUpper[i]); } // Now do column part for (i = 0; i < numberColumns; i++) { setColumnBounds(i, columnLower[i], columnUpper[i]); setColumnObjective(i, objective[i]); } for ( i = numberColumns - numberBinary - numberIntegers; i < numberColumns; i++) { setColumnIsInteger(i, true); } // and non linear for (i = numberAllNonLinearBoth - numberIntegerNonLinearBoth; i < numberAllNonLinearBoth; i++) { setColumnIsInteger(i, true); } for (i = numberAllNonLinearConstraints - numberIntegerNonLinearConstraints; i < numberAllNonLinearConstraints; i++) { setColumnIsInteger(i, true); } for (i = numberAllNonLinearObjective - numberIntegerNonLinearObjective; i < numberAllNonLinearObjective; i++) { setColumnIsInteger(i, true); } free(columnLower); free(columnUpper); free(rowLower); free(rowUpper); free(objective); // space for building a row char * temp = new char [30*numberColumns_]; // do names int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { char name[9]; sprintf(name, "r%7.7d", iRow); setRowName(iRow, name); } int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { char name[9]; sprintf(name, "c%7.7d", iColumn); setColumnName(iColumn, name); } if (colqp) { // add in quadratic int nz = 1 + n_con; int nOdd = 0; fint ** rowqp = colqp + nz; double ** delsqp = (double **)(rowqp + nz); for (i = 0; i <= n_con; i++) { int nels = z[i]; if (nels) { double * element = delsqp[i]; int * start = (int *) colqp[i]; int * row = (int *) rowqp[i]; if (!element) { // odd row - probably not quadratic nOdd++; continue; } #ifdef JJF_ZERO printf("%d quadratic els\n", nels); for (int j = 0; j < n_var; j++) { for (int k = start[j]; k < start[j+1]; k++) printf("%d %d %g\n", j, row[k], element[k]); } #endif if (i) { int iRow = i - 1; for (int j = 0; j < n_var; j++) { for (int k = start[j]; k < start[j+1]; k++) { int kColumn = row[k]; double value = element[k]; // ampl gives twice with assumed 0.5 if (kColumn < j) continue; else if (kColumn == j) value *= 0.5; const char * expr = getElementAsString(iRow, j); double constant = 0.0; bool linear; if (expr && strcmp(expr, "Numeric")) { linear = false; } else { constant = getElement(iRow, j); linear = true; } char temp2[30]; if (value == 1.0) sprintf(temp2, "c%7.7d", kColumn); else sprintf(temp2, "%g*c%7.7d", value, kColumn); if (linear) { if (!constant) strcpy(temp, temp2); else if (value > 0.0) sprintf(temp, "%g+%s", constant, temp2); else sprintf(temp, "%g%s", constant, temp2); } else { if (value > 0.0) sprintf(temp, "%s+%s", expr, temp2); else sprintf(temp, "%s%s", expr, temp2); } assert (static_cast(strlen(temp)) < 30*numberColumns_); setElement(iRow, j, temp); if (amplInfo->logLevel > 1) printf("el for row %d column c%7.7d is %s\n", iRow, j, temp); } } } else { // objective for (int j = 0; j < n_var; j++) { for (int k = start[j]; k < start[j+1]; k++) { int kColumn = row[k]; double value = element[k]; // ampl gives twice with assumed 0.5 if (kColumn < j) continue; else if (kColumn == j) value *= 0.5; const char * expr = getColumnObjectiveAsString(j); double constant = 0.0; bool linear; if (expr && strcmp(expr, "Numeric")) { linear = false; } else { constant = getColumnObjective(j); linear = true; } char temp2[30]; if (value == 1.0) sprintf(temp2, "c%7.7d", kColumn); else sprintf(temp2, "%g*c%7.7d", value, kColumn); if (linear) { if (!constant) strcpy(temp, temp2); else if (value > 0.0) sprintf(temp, "%g+%s", constant, temp2); else sprintf(temp, "%g%s", constant, temp2); } else { if (value > 0.0) sprintf(temp, "%s+%s", expr, temp2); else sprintf(temp, "%s%s", expr, temp2); } assert (static_cast(strlen(temp)) < 30*numberColumns_); setObjective(j, temp); if (amplInfo->logLevel > 1) printf("el for objective column c%7.7d is %s\n", j, temp); } } } } } if (nOdd) { printf("%d non-linear constraints could not be converted to quadratic\n", nOdd); exit(77); } } delete [] temp; free(colqp); free(z); // see if any sos { char *sostype; int nsosnz, *sosbeg, *sosind, * sospri; double *sosref; int nsos; int i = ASL_suf_sos_explict_free; int copri[2], **p_sospri; copri[0] = 0; copri[1] = 0; p_sospri = &sospri; nsos = suf_sos(i, &nsosnz, &sostype, p_sospri, copri, &sosbeg, &sosind, &sosref); if (nsos) { numberSOS_ = nsos; typeSOS_ = new int [numberSOS_]; prioritySOS_ = new int [numberSOS_]; startSOS_ = new int [numberSOS_+1]; memberSOS_ = new int[nsosnz]; referenceSOS_ = new double [nsosnz]; sos_kludge(nsos, sosbeg, sosref, sosind); for (int i = 0; i < nsos; i++) { int ichar = sostype[i]; assert (ichar == '1' || ichar == '2'); typeSOS_[i] = ichar - '0'; } memcpy(prioritySOS_, sospri, nsos*sizeof(int)); memcpy(startSOS_, sosbeg, (nsos + 1)*sizeof(int)); memcpy(memberSOS_, sosind, nsosnz*sizeof(int)); memcpy(referenceSOS_, sosref, nsosnz*sizeof(double)); } } } #else #include "Cbc_ampl.h" int readAmpl(ampl_info * , int , char **, void ** ) { return 0; } void freeArrays1(ampl_info *) { } void freeArrays2(ampl_info *) { } void freeArgs(ampl_info * ) { } int ampl_obj_prec() { return 0; } void writeAmpl(ampl_info * ) { } #endif Cbc-2.8.12/src/CbcObjectUpdateData.cpp0000644000076600007660000000463612131315050016017 0ustar coincoin// $Id: CbcObjectUpdateData.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/12/2009 carved from CbcBranchBase #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "OsiChooseVariable.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchBase.hpp" #include "CbcObjectUpdateData.hpp" // Default constructor CbcObjectUpdateData::CbcObjectUpdateData() : object_(NULL), way_(0), objectNumber_(-1), change_(0.0), status_(0), intDecrease_(0), branchingValue_(0.0), originalObjective_(COIN_DBL_MAX), cutoff_(COIN_DBL_MAX) { } // Useful constructor CbcObjectUpdateData::CbcObjectUpdateData (CbcObject * object, int way, double change, int status, int intDecrease, double branchingValue) : object_(object), way_(way), objectNumber_(-1), change_(change), status_(status), intDecrease_(intDecrease), branchingValue_(branchingValue), originalObjective_(COIN_DBL_MAX), cutoff_(COIN_DBL_MAX) { } // Destructor CbcObjectUpdateData::~CbcObjectUpdateData () { } // Copy constructor CbcObjectUpdateData::CbcObjectUpdateData ( const CbcObjectUpdateData & rhs) : object_(rhs.object_), way_(rhs.way_), objectNumber_(rhs.objectNumber_), change_(rhs.change_), status_(rhs.status_), intDecrease_(rhs.intDecrease_), branchingValue_(rhs.branchingValue_), originalObjective_(rhs.originalObjective_), cutoff_(rhs.cutoff_) { } // Assignment operator CbcObjectUpdateData & CbcObjectUpdateData::operator=( const CbcObjectUpdateData & rhs) { if (this != &rhs) { object_ = rhs.object_; way_ = rhs.way_; objectNumber_ = rhs.objectNumber_; change_ = rhs.change_; status_ = rhs.status_; intDecrease_ = rhs.intDecrease_; branchingValue_ = rhs.branchingValue_; originalObjective_ = rhs.originalObjective_; cutoff_ = rhs.cutoff_; } return *this; } Cbc-2.8.12/src/CbcLinked.hpp0000644000076600007660000012201112131315050014053 0ustar coincoin/* $Id: CbcLinked.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CglLinked_H #define CglLinked_H /* THIS CONTAINS STUFF THAT SHOULD BE IN OsiSolverLink OsiBranchLink CglTemporary */ #include "CoinModel.hpp" #include "OsiClpSolverInterface.hpp" #include "OsiChooseVariable.hpp" #include "CbcFathom.hpp" class CbcModel; class CoinPackedMatrix; class OsiLinkedBound; class OsiObject; class CglStored; class CglTemporary; /** This is to allow the user to replace initialSolve and resolve This version changes coefficients */ class OsiSolverLink : public CbcOsiSolver { public: //--------------------------------------------------------------------------- /**@name Solve methods */ //@{ /// Solve initial LP relaxation virtual void initialSolve(); /// Resolve an LP relaxation after problem modification virtual void resolve(); /** Problem specific Returns -1 if node fathomed and no solution 0 if did nothing 1 if node fathomed and solution allFixed is true if all LinkedBound variables are fixed */ virtual int fathom(bool allFixed) ; /** Solves nonlinear problem from CoinModel using SLP - may be used as crash for other algorithms when number of iterations small. Also exits if all problematical variables are changing less than deltaTolerance Returns solution array */ double * nonlinearSLP(int numberPasses, double deltaTolerance); /** Solve linearized quadratic objective branch and bound. Return cutoff and OA cut */ double linearizedBAB(CglStored * cut) ; /** Solves nonlinear problem from CoinModel using SLP - and then tries to get heuristic solution Returns solution array mode - 0 just get continuous 1 round and try normal bab 2 use defaultBound_ to bound integer variables near current solution */ double * heuristicSolution(int numberPasses, double deltaTolerance, int mode); /// Do OA cuts int doAOCuts(CglTemporary * cutGen, const double * solution, const double * solution2); //@} /**@name Constructors and destructors */ //@{ /// Default Constructor OsiSolverLink (); /** This creates from a coinModel object if errors.then number of sets is -1 This creates linked ordered sets information. It assumes - for product terms syntax is yy*f(zz) also just f(zz) is allowed and even a constant modelObject not const as may be changed as part of process. */ OsiSolverLink( CoinModel & modelObject); // Other way with existing object void load( CoinModel & modelObject, bool tightenBounds = false, int logLevel = 1); /// Clone virtual OsiSolverInterface * clone(bool copyData = true) const; /// Copy constructor OsiSolverLink (const OsiSolverLink &); /// Assignment operator OsiSolverLink & operator=(const OsiSolverLink& rhs); /// Destructor virtual ~OsiSolverLink (); //@} /**@name Sets and Gets */ //@{ /// Add a bound modifier void addBoundModifier(bool upperBoundAffected, bool useUpperBound, int whichVariable, int whichVariableAffected, double multiplier = 1.0); /// Update coefficients - returns number updated if in updating mode int updateCoefficients(ClpSimplex * solver, CoinPackedMatrix * matrix); /// Analyze constraints to see which are convex (quadratic) void analyzeObjects(); /// Add reformulated bilinear constraints void addTighterConstraints(); /// Objective value of best solution found internally inline double bestObjectiveValue() const { return bestObjectiveValue_; } /// Set objective value of best solution found internally inline void setBestObjectiveValue(double value) { bestObjectiveValue_ = value; } /// Best solution found internally inline const double * bestSolution() const { return bestSolution_; } /// Set best solution found internally void setBestSolution(const double * solution, int numberColumns); /// Set special options inline void setSpecialOptions2(int value) { specialOptions2_ = value; } /// Say convex (should work it out) - if convex false then strictly concave void sayConvex(bool convex); /// Get special options inline int specialOptions2() const { return specialOptions2_; } /** Clean copy of matrix So we can add rows */ CoinPackedMatrix * cleanMatrix() const { return matrix_; } /** Row copy of matrix Just genuine columns and rows Linear part */ CoinPackedMatrix * originalRowCopy() const { return originalRowCopy_; } /// Copy of quadratic model if one ClpSimplex * quadraticModel() const { return quadraticModel_; } /// Gets correct form for a quadratic row - user to delete CoinPackedMatrix * quadraticRow(int rowNumber, double * linear) const; /// Default meshSize inline double defaultMeshSize() const { return defaultMeshSize_; } inline void setDefaultMeshSize(double value) { defaultMeshSize_ = value; } /// Default maximumbound inline double defaultBound() const { return defaultBound_; } inline void setDefaultBound(double value) { defaultBound_ = value; } /// Set integer priority inline void setIntegerPriority(int value) { integerPriority_ = value; } /// Get integer priority inline int integerPriority() const { return integerPriority_; } /// Objective transfer variable if one inline int objectiveVariable() const { return objectiveVariable_; } /// Set biLinear priority inline void setBiLinearPriority(int value) { biLinearPriority_ = value; } /// Get biLinear priority inline int biLinearPriority() const { return biLinearPriority_; } /// Return CoinModel inline const CoinModel * coinModel() const { return &coinModel_; } /// Set all biLinear priorities on x-x variables void setBiLinearPriorities(int value, double meshSize = 1.0); /** Set options and priority on all or some biLinear variables 1 - on I-I 2 - on I-x 4 - on x-x or combinations. -1 means leave (for priority value and strategy value) */ void setBranchingStrategyOnVariables(int strategyValue, int priorityValue = -1, int mode = 7); /// Set all mesh sizes on x-x variables void setMeshSizes(double value); /** Two tier integer problem where when set of variables with priority less than this are fixed the problem becomes an easier integer problem */ void setFixedPriority(int priorityValue); //@} //--------------------------------------------------------------------------- protected: /**@name functions */ //@{ /// Do real work of initialize //void initialize(ClpSimplex * & solver, OsiObject ** & object) const; /// Do real work of delete void gutsOfDestructor(bool justNullify = false); /// Do real work of copy void gutsOfCopy(const OsiSolverLink & rhs) ; //@} /**@name Private member data */ //@{ /** Clean copy of matrix Marked coefficients will be multiplied by L or U */ CoinPackedMatrix * matrix_; /** Row copy of matrix Just genuine columns and rows */ CoinPackedMatrix * originalRowCopy_; /// Copy of quadratic model if one ClpSimplex * quadraticModel_; /// Number of rows with nonLinearities int numberNonLinearRows_; /// Starts of lists int * startNonLinear_; /// Row number for a list int * rowNonLinear_; /** Indicator whether is convex, concave or neither -1 concave, 0 neither, +1 convex */ int * convex_; /// Indices in a list/row int * whichNonLinear_; /// Model in CoinModel format CoinModel coinModel_; /// Number of variables in tightening phase int numberVariables_; /// Information OsiLinkedBound * info_; /** 0 bit (1) - call fathom (may do mini B&B) 1 bit (2) - quadratic only in objective (add OA cuts) 2 bit (4) - convex 3 bit (8) - try adding OA cuts 4 bit (16) - add linearized constraints */ int specialOptions2_; /// Objective transfer row if one int objectiveRow_; /// Objective transfer variable if one int objectiveVariable_; /// Objective value of best solution found internally double bestObjectiveValue_; /// Default mesh double defaultMeshSize_; /// Default maximum bound double defaultBound_; /// Best solution found internally double * bestSolution_; /// Priority for integers int integerPriority_; /// Priority for bilinear int biLinearPriority_; /// Number of variables which when fixed help int numberFix_; /// list of fixed variables int * fixVariables_; //@} }; /** List of bounds which depend on other bounds */ class OsiLinkedBound { public: //--------------------------------------------------------------------------- /**@name Action methods */ //@{ /// Update other bounds void updateBounds(ClpSimplex * solver); //@} /**@name Constructors and destructors */ //@{ /// Default Constructor OsiLinkedBound (); /// Useful Constructor OsiLinkedBound(OsiSolverInterface * model, int variable, int numberAffected, const int * positionL, const int * positionU, const double * multiplier); /// Copy constructor OsiLinkedBound (const OsiLinkedBound &); /// Assignment operator OsiLinkedBound & operator=(const OsiLinkedBound& rhs); /// Destructor ~OsiLinkedBound (); //@} /**@name Sets and Gets */ //@{ /// Get variable inline int variable() const { return variable_; } /// Add a bound modifier void addBoundModifier(bool upperBoundAffected, bool useUpperBound, int whichVariable, double multiplier = 1.0); //@} private: typedef struct { double multiplier; // to use in computation int affected; // variable or element affected /* 0 - LB of variable affected 1 - UB of variable affected 2 - element in position (affected) affected */ unsigned char affect; unsigned char ubUsed; // nonzero if UB of this variable is used /* 0 - use x*multiplier 1 - use multiplier/x 2 - if UB use min of current upper and x*multiplier, if LB use max of current lower and x*multiplier */ unsigned char type; // type of computation } boundElementAction; /**@name Private member data */ //@{ /// Pointer back to model OsiSolverInterface * model_; /// Variable int variable_; /// Number of variables/elements affected int numberAffected_; /// Maximum number of variables/elements affected int maximumAffected_; /// Actions boundElementAction * affected_; //@} }; #include "CbcHeuristic.hpp" /** heuristic - just picks up any good solution */ class CbcHeuristicDynamic3 : public CbcHeuristic { public: // Default Constructor CbcHeuristicDynamic3 (); /* Constructor with model */ CbcHeuristicDynamic3 (CbcModel & model); // Copy constructor CbcHeuristicDynamic3 ( const CbcHeuristicDynamic3 &); // Destructor ~CbcHeuristicDynamic3 (); /// Clone virtual CbcHeuristic * clone() const; /// update model virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) We leave all variables which are at one at this node of the tree to that value and will initially set all others to zero. We then sort all variables in order of their cost divided by the number of entries in rows which are not yet covered. We randomize that value a bit so that ties will be broken in different ways on different runs of the heuristic. We then choose the best one and set it to one and repeat the exercise. */ virtual int solution(double & objectiveValue, double * newSolution); /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// Returns true if can deal with "odd" problems e.g. sos type 2 virtual bool canDealWithOdd() const { return true; } protected: private: /// Illegal Assignment operator CbcHeuristicDynamic3 & operator=(const CbcHeuristicDynamic3& rhs); }; #include "OsiBranchingObject.hpp" /** Define Special Linked Ordered Sets. */ class CoinWarmStartBasis; class OsiOldLink : public OsiSOS { public: // Default Constructor OsiOldLink (); /** Useful constructor - A valid solution is if all variables are zero apart from k*numberLink to (k+1)*numberLink-1 where k is 0 through numberInSet-1. The length of weights array is numberInSet. For this constructor the variables in matrix are the numberInSet*numberLink starting at first. If weights null then 0,1,2.. */ OsiOldLink (const OsiSolverInterface * solver, int numberMembers, int numberLinks, int first, const double * weights, int setNumber); /** Useful constructor - A valid solution is if all variables are zero apart from k*numberLink to (k+1)*numberLink-1 where k is 0 through numberInSet-1. The length of weights array is numberInSet. For this constructor the variables are given by list - grouped. If weights null then 0,1,2.. */ OsiOldLink (const OsiSolverInterface * solver, int numberMembers, int numberLinks, int typeSOS, const int * which, const double * weights, int setNumber); // Copy constructor OsiOldLink ( const OsiOldLink &); /// Clone virtual OsiObject * clone() const; // Assignment operator OsiOldLink & operator=( const OsiOldLink& rhs); // Destructor virtual ~OsiOldLink (); using OsiObject::infeasibility ; /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int & whichWay) const; using OsiObject::feasibleRegion ; /** Set bounds to fix the variable at the current (integer) value. Given an integer value, set the lower and upper bounds to fix the variable. Returns amount it had to move variable. */ virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; /** Creates a branching object The preferred direction is set by \p way, 0 for down, 1 for up. */ virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const; /// Redoes data when sequence numbers change virtual void resetSequenceEtc(int numberColumns, const int * originalColumns); /// Number of links for each member inline int numberLinks() const { return numberLinks_; } /** \brief Return true if object can take part in normal heuristics */ virtual bool canDoHeuristics() const { return false; } /** \brief Return true if branch should only bound variables */ virtual bool boundBranch() const { return false; } private: /// data /// Number of links int numberLinks_; }; /** Branching object for Linked ordered sets */ class OsiOldLinkBranchingObject : public OsiSOSBranchingObject { public: // Default Constructor OsiOldLinkBranchingObject (); // Useful constructor OsiOldLinkBranchingObject (OsiSolverInterface * solver, const OsiOldLink * originalObject, int way, double separator); // Copy constructor OsiOldLinkBranchingObject ( const OsiOldLinkBranchingObject &); // Assignment operator OsiOldLinkBranchingObject & operator=( const OsiOldLinkBranchingObject& rhs); /// Clone virtual OsiBranchingObject * clone() const; // Destructor virtual ~OsiOldLinkBranchingObject (); using OsiBranchingObject::branch ; /// Does next branch and updates state virtual double branch(OsiSolverInterface * solver); using OsiBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(const OsiSolverInterface * solver = NULL); private: /// data }; /** Define data for one link */ class OsiOneLink { public: // Default Constructor OsiOneLink (); /** Useful constructor - */ OsiOneLink (const OsiSolverInterface * solver, int xRow, int xColumn, int xyRow, const char * functionString); // Copy constructor OsiOneLink ( const OsiOneLink &); // Assignment operator OsiOneLink & operator=( const OsiOneLink& rhs); // Destructor virtual ~OsiOneLink (); /// data /// Row which defines x (if -1 then no x) int xRow_; /// Column which defines x int xColumn_; /// Output row int xyRow; /// Function std::string function_; }; /** Define Special Linked Ordered Sets. New style members and weights may be stored in SOS object This is for y and x*f(y) and z*g(y) etc */ class OsiLink : public OsiSOS { public: // Default Constructor OsiLink (); /** Useful constructor - */ OsiLink (const OsiSolverInterface * solver, int yRow, int yColumn, double meshSize); // Copy constructor OsiLink ( const OsiLink &); /// Clone virtual OsiObject * clone() const; // Assignment operator OsiLink & operator=( const OsiLink& rhs); // Destructor virtual ~OsiLink (); using OsiObject::infeasibility ; /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int & whichWay) const; using OsiObject::feasibleRegion ; /** Set bounds to fix the variable at the current (integer) value. Given an integer value, set the lower and upper bounds to fix the variable. Returns amount it had to move variable. */ virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; /** Creates a branching object The preferred direction is set by \p way, 0 for down, 1 for up. */ virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const; /// Redoes data when sequence numbers change virtual void resetSequenceEtc(int numberColumns, const int * originalColumns); /// Number of links for each member inline int numberLinks() const { return numberLinks_; } /** \brief Return true if object can take part in normal heuristics */ virtual bool canDoHeuristics() const { return false; } /** \brief Return true if branch should only bound variables */ virtual bool boundBranch() const { return false; } private: /// data /// Current increment for y points double meshSize_; /// Links OsiOneLink * data_; /// Number of links int numberLinks_; /// Row which defines y int yRow_; /// Column which defines y int yColumn_; }; /** Branching object for Linked ordered sets */ class OsiLinkBranchingObject : public OsiTwoWayBranchingObject { public: // Default Constructor OsiLinkBranchingObject (); // Useful constructor OsiLinkBranchingObject (OsiSolverInterface * solver, const OsiLink * originalObject, int way, double separator); // Copy constructor OsiLinkBranchingObject ( const OsiLinkBranchingObject &); // Assignment operator OsiLinkBranchingObject & operator=( const OsiLinkBranchingObject& rhs); /// Clone virtual OsiBranchingObject * clone() const; // Destructor virtual ~OsiLinkBranchingObject (); using OsiBranchingObject::branch ; /// Does next branch and updates state virtual double branch(OsiSolverInterface * solver); using OsiBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(const OsiSolverInterface * solver = NULL); private: /// data }; /** Define BiLinear objects This models x*y where one or both are integer */ class OsiBiLinear : public OsiObject2 { public: // Default Constructor OsiBiLinear (); /** Useful constructor - This Adds in rows and variables to construct valid Linked Ordered Set Adds extra constraints to match other x/y So note not const solver */ OsiBiLinear (OsiSolverInterface * solver, int xColumn, int yColumn, int xyRow, double coefficient, double xMesh, double yMesh, int numberExistingObjects = 0, const OsiObject ** objects = NULL ); /** Useful constructor - This Adds in rows and variables to construct valid Linked Ordered Set Adds extra constraints to match other x/y So note not const model */ OsiBiLinear (CoinModel * coinModel, int xColumn, int yColumn, int xyRow, double coefficient, double xMesh, double yMesh, int numberExistingObjects = 0, const OsiObject ** objects = NULL ); // Copy constructor OsiBiLinear ( const OsiBiLinear &); /// Clone virtual OsiObject * clone() const; // Assignment operator OsiBiLinear & operator=( const OsiBiLinear& rhs); // Destructor virtual ~OsiBiLinear (); using OsiObject::infeasibility ; /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int & whichWay) const; using OsiObject::feasibleRegion ; /** Set bounds to fix the variable at the current (integer) value. Given an integer value, set the lower and upper bounds to fix the variable. Returns amount it had to move variable. */ virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; /** Creates a branching object The preferred direction is set by \p way, 0 for down, 1 for up. */ virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const; /// Redoes data when sequence numbers change virtual void resetSequenceEtc(int numberColumns, const int * originalColumns); // This does NOT set mutable stuff virtual double checkInfeasibility(const OsiBranchingInformation * info) const; /** \brief Return true if object can take part in normal heuristics */ virtual bool canDoHeuristics() const { return false; } /** \brief Return true if branch should only bound variables */ virtual bool boundBranch() const { return (branchingStrategy_&4) != 0; } /// X column inline int xColumn() const { return xColumn_; } /// Y column inline int yColumn() const { return yColumn_; } /// X row inline int xRow() const { return xRow_; } /// Y row inline int yRow() const { return yRow_; } /// XY row inline int xyRow() const { return xyRow_; } /// Coefficient inline double coefficient() const { return coefficient_; } /// Set coefficient inline void setCoefficient(double value) { coefficient_ = value; } /// First lambda (of 4) inline int firstLambda() const { return firstLambda_; } /// X satisfied if less than this away from mesh inline double xSatisfied() const { return xSatisfied_; } inline void setXSatisfied(double value) { xSatisfied_ = value; } /// Y satisfied if less than this away from mesh inline double ySatisfied() const { return ySatisfied_; } inline void setYSatisfied(double value) { ySatisfied_ = value; } /// X other satisfied if less than this away from mesh inline double xOtherSatisfied() const { return xOtherSatisfied_; } inline void setXOtherSatisfied(double value) { xOtherSatisfied_ = value; } /// Y other satisfied if less than this away from mesh inline double yOtherSatisfied() const { return yOtherSatisfied_; } inline void setYOtherSatisfied(double value) { yOtherSatisfied_ = value; } /// X meshSize inline double xMeshSize() const { return xMeshSize_; } inline void setXMeshSize(double value) { xMeshSize_ = value; } /// Y meshSize inline double yMeshSize() const { return yMeshSize_; } inline void setYMeshSize(double value) { yMeshSize_ = value; } /// XY satisfied if two version differ by less than this inline double xySatisfied() const { return xySatisfied_; } inline void setXYSatisfied(double value) { xySatisfied_ = value; } /// Set sizes and other stuff void setMeshSizes(const OsiSolverInterface * solver, double x, double y); /** branching strategy etc bottom 2 bits 0 branch on either, 1 branch on x, 2 branch on y next bit 4 set to say don't update coefficients next bit 8 set to say don't use in feasible region next bit 16 set to say - Always satisfied !! */ inline int branchingStrategy() const { return branchingStrategy_; } inline void setBranchingStrategy(int value) { branchingStrategy_ = value; } /** Simple quadratic bound marker. 0 no 1 L if coefficient pos, G if negative i.e. value is ub on xy 2 G if coefficient pos, L if negative i.e. value is lb on xy 3 E If bound then real coefficient is 1.0 and coefficient_ is bound */ inline int boundType() const { return boundType_; } inline void setBoundType(int value) { boundType_ = value; } /// Does work of branching void newBounds(OsiSolverInterface * solver, int way, short xOrY, double separator) const; /// Updates coefficients - returns number updated int updateCoefficients(const double * lower, const double * upper, double * objective, CoinPackedMatrix * matrix, CoinWarmStartBasis * basis) const; /// Returns true value of single xyRow coefficient double xyCoefficient(const double * solution) const; /// Get LU coefficients from matrix void getCoefficients(const OsiSolverInterface * solver, double xB[2], double yB[2], double xybar[4]) const; /// Compute lambdas (third entry in each .B is current value) (nonzero if bad) double computeLambdas(const double xB[3], const double yB[3], const double xybar[4], double lambda[4]) const; /// Adds in data for extra row with variable coefficients void addExtraRow(int row, double multiplier); /// Sets infeasibility and other when pseudo shadow prices void getPseudoShadow(const OsiBranchingInformation * info); /// Gets sum of movements to correct value double getMovement(const OsiBranchingInformation * info); protected: /// Compute lambdas if coefficients not changing void computeLambdas(const OsiSolverInterface * solver, double lambda[4]) const; /// data /// Coefficient double coefficient_; /// x mesh double xMeshSize_; /// y mesh double yMeshSize_; /// x satisfied if less than this away from mesh double xSatisfied_; /// y satisfied if less than this away from mesh double ySatisfied_; /// X other satisfied if less than this away from mesh double xOtherSatisfied_; /// Y other satisfied if less than this away from mesh double yOtherSatisfied_; /// xy satisfied if less than this away from true double xySatisfied_; /// value of x or y to branch about mutable double xyBranchValue_; /// x column int xColumn_; /// y column int yColumn_; /// First lambda (of 4) int firstLambda_; /** branching strategy etc bottom 2 bits 0 branch on either, 1 branch on x, 2 branch on y next bit 4 set to say don't update coefficients next bit 8 set to say don't use in feasible region next bit 16 set to say - Always satisfied !! */ int branchingStrategy_; /** Simple quadratic bound marker. 0 no 1 L if coefficient pos, G if negative i.e. value is ub on xy 2 G if coefficient pos, L if negative i.e. value is lb on xy 3 E If bound then real coefficient is 1.0 and coefficient_ is bound */ int boundType_; /// x row int xRow_; /// y row (-1 if x*x) int yRow_; /// Output row int xyRow_; /// Convexity row int convexity_; /// Number of extra rows (coefficients to be modified) int numberExtraRows_; /// Multiplier for coefficient on row double * multiplier_; /// Row number int * extraRow_; /// Which chosen -1 none, 0 x, 1 y mutable short chosen_; }; /** Branching object for BiLinear objects */ class OsiBiLinearBranchingObject : public OsiTwoWayBranchingObject { public: // Default Constructor OsiBiLinearBranchingObject (); // Useful constructor OsiBiLinearBranchingObject (OsiSolverInterface * solver, const OsiBiLinear * originalObject, int way, double separator, int chosen); // Copy constructor OsiBiLinearBranchingObject ( const OsiBiLinearBranchingObject &); // Assignment operator OsiBiLinearBranchingObject & operator=( const OsiBiLinearBranchingObject& rhs); /// Clone virtual OsiBranchingObject * clone() const; // Destructor virtual ~OsiBiLinearBranchingObject (); using OsiBranchingObject::branch ; /// Does next branch and updates state virtual double branch(OsiSolverInterface * solver); using OsiBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(const OsiSolverInterface * solver = NULL); /** \brief Return true if branch should only bound variables */ virtual bool boundBranch() const; private: /// data /// 1 means branch on x, 2 branch on y short chosen_; }; /** Define Continuous BiLinear objects for an == bound This models x*y = b where both are continuous */ class OsiBiLinearEquality : public OsiBiLinear { public: // Default Constructor OsiBiLinearEquality (); /** Useful constructor - This Adds in rows and variables to construct Ordered Set for x*y = b So note not const solver */ OsiBiLinearEquality (OsiSolverInterface * solver, int xColumn, int yColumn, int xyRow, double rhs, double xMesh); // Copy constructor OsiBiLinearEquality ( const OsiBiLinearEquality &); /// Clone virtual OsiObject * clone() const; // Assignment operator OsiBiLinearEquality & operator=( const OsiBiLinearEquality& rhs); // Destructor virtual ~OsiBiLinearEquality (); /// Possible improvement virtual double improvement(const OsiSolverInterface * solver) const; /** change grid if type 0 then use solution and make finer if 1 then back to original returns mesh size */ double newGrid(OsiSolverInterface * solver, int type) const; /// Number of points inline int numberPoints() const { return numberPoints_; } inline void setNumberPoints(int value) { numberPoints_ = value; } private: /// Number of points int numberPoints_; }; /// Define a single integer class - but one where you keep branching until fixed even if satisfied class OsiSimpleFixedInteger : public OsiSimpleInteger { public: /// Default Constructor OsiSimpleFixedInteger (); /// Useful constructor - passed solver index OsiSimpleFixedInteger (const OsiSolverInterface * solver, int iColumn); /// Useful constructor - passed solver index and original bounds OsiSimpleFixedInteger (int iColumn, double lower, double upper); /// Useful constructor - passed simple integer OsiSimpleFixedInteger (const OsiSimpleInteger &); /// Copy constructor OsiSimpleFixedInteger ( const OsiSimpleFixedInteger &); /// Clone virtual OsiObject * clone() const; /// Assignment operator OsiSimpleFixedInteger & operator=( const OsiSimpleFixedInteger& rhs); /// Destructor virtual ~OsiSimpleFixedInteger (); using OsiObject::infeasibility ; /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int & whichWay) const; /** Creates a branching object The preferred direction is set by \p way, 0 for down, 1 for up. */ virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const; protected: /// data }; /** Define a single variable class which is involved with OsiBiLinear objects. This is used so can make better decision on where to branch as it can look at all objects. This version sees if it can re-use code from OsiSimpleInteger even if not an integer variable. If not then need to duplicate code. */ class OsiUsesBiLinear : public OsiSimpleInteger { public: /// Default Constructor OsiUsesBiLinear (); /// Useful constructor - passed solver index OsiUsesBiLinear (const OsiSolverInterface * solver, int iColumn, int type); /// Useful constructor - passed solver index and original bounds OsiUsesBiLinear (int iColumn, double lower, double upper, int type); /// Useful constructor - passed simple integer OsiUsesBiLinear (const OsiSimpleInteger & rhs, int type); /// Copy constructor OsiUsesBiLinear ( const OsiUsesBiLinear & rhs); /// Clone virtual OsiObject * clone() const; /// Assignment operator OsiUsesBiLinear & operator=( const OsiUsesBiLinear& rhs); /// Destructor virtual ~OsiUsesBiLinear (); using OsiObject::infeasibility ; /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int & whichWay) const; /** Creates a branching object The preferred direction is set by \p way, 0 for down, 1 for up. */ virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const; using OsiObject::feasibleRegion ; /** Set bounds to fix the variable at the current value. Given an current value, set the lower and upper bounds to fix the variable. Returns amount it had to move variable. */ virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; /// Add all bi-linear objects void addBiLinearObjects(OsiSolverLink * solver); protected: /// data /// Number of bilinear objects (maybe could be more general) int numberBiLinear_; /// Type of variable - 0 continuous, 1 integer int type_; /// Objects OsiObject ** objects_; }; /** This class chooses a variable to branch on This is just as OsiChooseStrong but it fakes it so only first so many are looked at in this phase */ class OsiChooseStrongSubset : public OsiChooseStrong { public: /// Default Constructor OsiChooseStrongSubset (); /// Constructor from solver (so we can set up arrays etc) OsiChooseStrongSubset (const OsiSolverInterface * solver); /// Copy constructor OsiChooseStrongSubset (const OsiChooseStrongSubset &); /// Assignment operator OsiChooseStrongSubset & operator= (const OsiChooseStrongSubset& rhs); /// Clone virtual OsiChooseVariable * clone() const; /// Destructor virtual ~OsiChooseStrongSubset (); /** Sets up strong list and clears all if initialize is true. Returns number of infeasibilities. If returns -1 then has worked out node is infeasible! */ virtual int setupList ( OsiBranchingInformation *info, bool initialize); /** Choose a variable Returns - -1 Node is infeasible 0 Normal termination - we have a candidate 1 All looks satisfied - no candidate 2 We can change the bound on a variable - but we also have a strong branching candidate 3 We can change the bound on a variable - but we have a non-strong branching candidate 4 We can change the bound on a variable - no other candidates We can pick up branch from bestObjectIndex() and bestWhichWay() We can pick up a forced branch (can change bound) from firstForcedObjectIndex() and firstForcedWhichWay() If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() If fixVariables is true then 2,3,4 are all really same as problem changed */ virtual int chooseVariable( OsiSolverInterface * solver, OsiBranchingInformation *info, bool fixVariables); /// Number of objects to use inline int numberObjectsToUse() const { return numberObjectsToUse_; } /// Set number of objects to use inline void setNumberObjectsToUse(int value) { numberObjectsToUse_ = value; } protected: // Data /// Number of objects to be used (and set in solver) int numberObjectsToUse_; }; #include #include "CglStored.hpp" class CoinWarmStartBasis; /** Stored Temporary Cut Generator Class - destroyed after first use */ class CglTemporary : public CglStored { public: /**@name Generate Cuts */ //@{ /** Generate Mixed Integer Stored cuts for the model of the solver interface, si. Insert the generated cuts into OsiCut, cs. This generator just looks at previously stored cuts and inserts any that are violated by enough */ virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo info = CglTreeInfo()); //@} /**@name Constructors and destructors */ //@{ /// Default constructor CglTemporary (); /// Copy constructor CglTemporary (const CglTemporary & rhs); /// Clone virtual CglCutGenerator * clone() const; /// Assignment operator CglTemporary & operator=(const CglTemporary& rhs); /// Destructor virtual ~CglTemporary (); //@} private: // Private member methods // Private member data }; //############################################################################# /** This is to allow the user to replace initialSolve and resolve */ class OsiSolverLinearizedQuadratic : public OsiClpSolverInterface { public: //--------------------------------------------------------------------------- /**@name Solve methods */ //@{ /// Solve initial LP relaxation virtual void initialSolve(); //@} /**@name Constructors and destructors */ //@{ /// Default Constructor OsiSolverLinearizedQuadratic (); /// Useful constructor (solution should be good) OsiSolverLinearizedQuadratic( ClpSimplex * quadraticModel); /// Clone virtual OsiSolverInterface * clone(bool copyData = true) const; /// Copy constructor OsiSolverLinearizedQuadratic (const OsiSolverLinearizedQuadratic &); /// Assignment operator OsiSolverLinearizedQuadratic & operator=(const OsiSolverLinearizedQuadratic& rhs); /// Destructor virtual ~OsiSolverLinearizedQuadratic (); //@} /**@name Sets and Gets */ //@{ /// Objective value of best solution found internally inline double bestObjectiveValue() const { return bestObjectiveValue_; } /// Best solution found internally const double * bestSolution() const { return bestSolution_; } /// Set special options inline void setSpecialOptions3(int value) { specialOptions3_ = value; } /// Get special options inline int specialOptions3() const { return specialOptions3_; } /// Copy of quadratic model if one ClpSimplex * quadraticModel() const { return quadraticModel_; } //@} //--------------------------------------------------------------------------- protected: /**@name functions */ //@{ /**@name Private member data */ //@{ /// Objective value of best solution found internally double bestObjectiveValue_; /// Copy of quadratic model if one ClpSimplex * quadraticModel_; /// Best solution found internally double * bestSolution_; /** 0 bit (1) - don't do mini B&B 1 bit (2) - quadratic only in objective */ int specialOptions3_; //@} }; class ClpSimplex; /** Return an approximate solution to a CoinModel. Lots of bounds may be odd to force a solution. mode = 0 just tries to get a continuous solution */ ClpSimplex * approximateSolution(CoinModel & coinModel, int numberPasses, double deltaTolerance, int mode = 0); #endif Cbc-2.8.12/src/CbcSolverExpandKnapsack.cpp0000644000076600007660000006201712131315050016737 0ustar coincoin/* $Id: CbcSolverExpandKnapsack.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /*! \file CbcSolverExpandKnapsack.cpp Returns OsiSolverInterface (User should delete) On entry numberKnapsack is maximum number of Total entries Expanding possibilities of x*y, where x*y are both integers, constructing a knapsack constraint. Results in a tighter model. */ #include "CbcConfig.h" #include "CoinPragma.hpp" #include "OsiSolverInterface.hpp" #include "CglStored.hpp" #ifndef COIN_HAS_LINK #define COIN_HAS_LINK #endif #ifdef COIN_HAS_LINK #include "CbcLinked.hpp" #endif #ifdef COIN_HAS_LINK OsiSolverInterface * expandKnapsack(CoinModel & model, int * whichColumn, int * knapsackStart, int * knapsackRow, int &numberKnapsack, CglStored & stored, int logLevel, int fixedPriority, int SOSPriority, CoinModel & tightenedModel) { int maxTotal = numberKnapsack; // load from coin model OsiSolverLink *si = new OsiSolverLink(); OsiSolverInterface * finalModel = NULL; si->setDefaultMeshSize(0.001); // need some relative granularity si->setDefaultBound(100.0); si->setDefaultMeshSize(0.01); si->setDefaultBound(100000.0); si->setIntegerPriority(1000); si->setBiLinearPriority(10000); si->load(model, true, logLevel); // get priorities const int * priorities = model.priorities(); int numberColumns = model.numberColumns(); if (priorities) { OsiObject ** objects = si->objects(); int numberObjects = si->numberObjects(); for (int iObj = 0; iObj < numberObjects; iObj++) { int iColumn = objects[iObj]->columnNumber(); if (iColumn >= 0 && iColumn < numberColumns) { #ifndef NDEBUG OsiSimpleInteger * obj = dynamic_cast (objects[iObj]) ; #endif assert (obj); int iPriority = priorities[iColumn]; if (iPriority > 0) objects[iObj]->setPriority(iPriority); } } if (fixedPriority > 0) { si->setFixedPriority(fixedPriority); } if (SOSPriority < 0) SOSPriority = 100000; } CoinModel coinModel = *si->coinModel(); assert(coinModel.numberRows() > 0); tightenedModel = coinModel; int numberRows = coinModel.numberRows(); // Mark variables int * whichKnapsack = new int [numberColumns]; int iRow, iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) whichKnapsack[iColumn] = -1; int kRow; bool badModel = false; // analyze if (logLevel > 1) { for (iRow = 0; iRow < numberRows; iRow++) { /* Just obvious one at first positive non unit coefficients all integer positive rowUpper for now - linear (but further down in code may use nonlinear) column bounds should be tight */ //double lower = coinModel.getRowLower(iRow); double upper = coinModel.getRowUpper(iRow); if (upper < 1.0e10) { CoinModelLink triple = coinModel.firstInRow(iRow); bool possible = true; int n = 0; int n1 = 0; while (triple.column() >= 0) { int iColumn = triple.column(); const char * el = coinModel.getElementAsString(iRow, iColumn); if (!strcmp("Numeric", el)) { if (coinModel.columnLower(iColumn) == coinModel.columnUpper(iColumn)) { triple = coinModel.next(triple); continue; // fixed } double value = coinModel.getElement(iRow, iColumn); if (value < 0.0) { possible = false; } else { n++; if (value == 1.0) n1++; if (coinModel.columnLower(iColumn) < 0.0) possible = false; if (!coinModel.isInteger(iColumn)) possible = false; if (whichKnapsack[iColumn] >= 0) possible = false; } } else { possible = false; // non linear } triple = coinModel.next(triple); } if (n - n1 > 1 && possible) { double lower = coinModel.getRowLower(iRow); double upper = coinModel.getRowUpper(iRow); CoinModelLink triple = coinModel.firstInRow(iRow); while (triple.column() >= 0) { int iColumn = triple.column(); lower -= coinModel.columnLower(iColumn) * triple.value(); upper -= coinModel.columnLower(iColumn) * triple.value(); triple = coinModel.next(triple); } printf("%d is possible %g <=", iRow, lower); // print triple = coinModel.firstInRow(iRow); while (triple.column() >= 0) { int iColumn = triple.column(); if (coinModel.columnLower(iColumn) != coinModel.columnUpper(iColumn)) printf(" (%d,el %g up %g)", iColumn, triple.value(), coinModel.columnUpper(iColumn) - coinModel.columnLower(iColumn)); triple = coinModel.next(triple); } printf(" <= %g\n", upper); } } } } numberKnapsack = 0; for (kRow = 0; kRow < numberRows; kRow++) { iRow = kRow; /* Just obvious one at first positive non unit coefficients all integer positive rowUpper for now - linear (but further down in code may use nonlinear) column bounds should be tight */ //double lower = coinModel.getRowLower(iRow); double upper = coinModel.getRowUpper(iRow); if (upper < 1.0e10) { CoinModelLink triple = coinModel.firstInRow(iRow); bool possible = true; int n = 0; int n1 = 0; while (triple.column() >= 0) { int iColumn = triple.column(); const char * el = coinModel.getElementAsString(iRow, iColumn); if (!strcmp("Numeric", el)) { if (coinModel.columnLower(iColumn) == coinModel.columnUpper(iColumn)) { triple = coinModel.next(triple); continue; // fixed } double value = coinModel.getElement(iRow, iColumn); if (value < 0.0) { possible = false; } else { n++; if (value == 1.0) n1++; if (coinModel.columnLower(iColumn) < 0.0) possible = false; if (!coinModel.isInteger(iColumn)) possible = false; if (whichKnapsack[iColumn] >= 0) possible = false; } } else { possible = false; // non linear } triple = coinModel.next(triple); } if (n - n1 > 1 && possible) { // try CoinModelLink triple = coinModel.firstInRow(iRow); while (triple.column() >= 0) { int iColumn = triple.column(); if (coinModel.columnLower(iColumn) != coinModel.columnUpper(iColumn)) whichKnapsack[iColumn] = numberKnapsack; triple = coinModel.next(triple); } knapsackRow[numberKnapsack++] = iRow; } } } if (logLevel > 0) printf("%d out of %d candidate rows are possible\n", numberKnapsack, numberRows); // Check whether we can get rid of nonlinearities /* mark rows -2 in knapsack and other variables -1 not involved n only in knapsack n */ int * markRow = new int [numberRows]; for (iRow = 0; iRow < numberRows; iRow++) markRow[iRow] = -1; int canDo = 1; // OK and linear for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinModelLink triple = coinModel.firstInColumn(iColumn); int iKnapsack = whichKnapsack[iColumn]; bool linear = true; // See if quadratic objective const char * expr = coinModel.getColumnObjectiveAsString(iColumn); if (strcmp(expr, "Numeric")) { linear = false; } while (triple.row() >= 0) { int iRow = triple.row(); if (iKnapsack >= 0) { if (markRow[iRow] == -1) { markRow[iRow] = iKnapsack; } else if (markRow[iRow] != iKnapsack) { markRow[iRow] = -2; } } const char * expr = coinModel.getElementAsString(iRow, iColumn); if (strcmp(expr, "Numeric")) { linear = false; } triple = coinModel.next(triple); } if (!linear) { if (whichKnapsack[iColumn] < 0) { canDo = 0; break; } else { canDo = 2; } } } int * markKnapsack = NULL; double * coefficient = NULL; double * linear = NULL; int * whichRow = NULL; int * lookupRow = NULL; badModel = (canDo == 0); if (numberKnapsack && canDo) { /* double check - OK if no nonlinear nonlinear only on columns in knapsack nonlinear only on columns in knapsack * ONE other - same for all in knapsack AND that is only row connected to knapsack (theoretically could split knapsack if two other and small numbers) also ONE could be ONE expression - not just a variable */ int iKnapsack; markKnapsack = new int [numberKnapsack]; coefficient = new double [numberKnapsack]; linear = new double [numberColumns]; for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) markKnapsack[iKnapsack] = -1; if (canDo == 2) { for (iRow = -1; iRow < numberRows; iRow++) { int numberOdd; CoinPackedMatrix * row = coinModel.quadraticRow(iRow, linear, numberOdd); if (row) { // see if valid const double * element = row->getElements(); const int * column = row->getIndices(); const CoinBigIndex * columnStart = row->getVectorStarts(); const int * columnLength = row->getVectorLengths(); int numberLook = row->getNumCols(); for (int i = 0; i < numberLook; i++) { int iKnapsack = whichKnapsack[i]; if (iKnapsack < 0) { // might be able to swap - but for now can't have knapsack in for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iColumn = column[j]; if (whichKnapsack[iColumn] >= 0) { canDo = 0; // no good badModel = true; break; } } } else { // OK if in same knapsack - or maybe just one int marked = markKnapsack[iKnapsack]; for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iColumn = column[j]; if (whichKnapsack[iColumn] != iKnapsack && whichKnapsack[iColumn] >= 0) { canDo = 0; // no good badModel = true; break; } else if (marked == -1) { markKnapsack[iKnapsack] = iColumn; marked = iColumn; coefficient[iKnapsack] = element[j]; coinModel.associateElement(coinModel.columnName(iColumn), 1.0); } else if (marked != iColumn) { badModel = true; canDo = 0; // no good break; } else { // could manage with different coefficients - but for now ... assert(coefficient[iKnapsack] == element[j]); } } } } delete row; } } } if (canDo) { // for any rows which are cuts whichRow = new int [numberRows]; lookupRow = new int [numberRows]; bool someNonlinear = false; double maxCoefficient = 1.0; for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) { if (markKnapsack[iKnapsack] >= 0) { someNonlinear = true; int iColumn = markKnapsack[iKnapsack]; maxCoefficient = CoinMax(maxCoefficient, fabs(coefficient[iKnapsack] * coinModel.columnUpper(iColumn))); } } if (someNonlinear) { // associate all columns to stop possible error messages for (iColumn = 0; iColumn < numberColumns; iColumn++) { coinModel.associateElement(coinModel.columnName(iColumn), 1.0); } } ClpSimplex tempModel; tempModel.loadProblem(coinModel); // Create final model - first without knapsacks int nCol = 0; int nRow = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (markRow[iRow] < 0) { lookupRow[iRow] = nRow; whichRow[nRow++] = iRow; } else { lookupRow[iRow] = -1; } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (whichKnapsack[iColumn] < 0) whichColumn[nCol++] = iColumn; } ClpSimplex finalModelX(&tempModel, nRow, whichRow, nCol, whichColumn, false, false, false); OsiClpSolverInterface finalModelY(&finalModelX, true); finalModel = finalModelY.clone(); finalModelY.releaseClp(); // Put back priorities const int * priorities = model.priorities(); if (priorities) { finalModel->findIntegers(false); OsiObject ** objects = finalModel->objects(); int numberObjects = finalModel->numberObjects(); for (int iObj = 0; iObj < numberObjects; iObj++) { int iColumn = objects[iObj]->columnNumber(); if (iColumn >= 0 && iColumn < nCol) { #ifndef NDEBUG OsiSimpleInteger * obj = dynamic_cast (objects[iObj]) ; #endif assert (obj); int iPriority = priorities[whichColumn[iColumn]]; if (iPriority > 0) objects[iObj]->setPriority(iPriority); } } } for (iRow = 0; iRow < numberRows; iRow++) { whichRow[iRow] = iRow; } int numberOther = finalModel->getNumCols(); int nLargest = 0; int nelLargest = 0; int nTotal = 0; for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) { iRow = knapsackRow[iKnapsack]; int nCreate = maxTotal; int nelCreate = coinModel.expandKnapsack(iRow, nCreate, NULL, NULL, NULL, NULL); if (nelCreate < 0) badModel = true; nTotal += nCreate; nLargest = CoinMax(nLargest, nCreate); nelLargest = CoinMax(nelLargest, nelCreate); } if (nTotal > maxTotal) badModel = true; if (!badModel) { // Now arrays for building nelLargest = CoinMax(nelLargest, nLargest) + 1; double * buildObj = new double [nLargest]; double * buildElement = new double [nelLargest]; int * buildStart = new int[nLargest+1]; int * buildRow = new int[nelLargest]; // alow for integers in knapsacks OsiObject ** object = new OsiObject * [numberKnapsack+nTotal]; int nSOS = 0; int nObj = numberKnapsack; for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) { knapsackStart[iKnapsack] = finalModel->getNumCols(); iRow = knapsackRow[iKnapsack]; int nCreate = 10000; coinModel.expandKnapsack(iRow, nCreate, buildObj, buildStart, buildRow, buildElement); // Redo row numbers for (iColumn = 0; iColumn < nCreate; iColumn++) { for (int j = buildStart[iColumn]; j < buildStart[iColumn+1]; j++) { int jRow = buildRow[j]; jRow = lookupRow[jRow]; assert (jRow >= 0 && jRow < nRow); buildRow[j] = jRow; } } finalModel->addCols(nCreate, buildStart, buildRow, buildElement, NULL, NULL, buildObj); int numberFinal = finalModel->getNumCols(); for (iColumn = numberOther; iColumn < numberFinal; iColumn++) { if (markKnapsack[iKnapsack] < 0) { finalModel->setColUpper(iColumn, maxCoefficient); finalModel->setInteger(iColumn); } else { finalModel->setColUpper(iColumn, maxCoefficient + 1.0); finalModel->setInteger(iColumn); } OsiSimpleInteger * sosObject = new OsiSimpleInteger(finalModel, iColumn); sosObject->setPriority(1000000); object[nObj++] = sosObject; buildRow[iColumn-numberOther] = iColumn; buildElement[iColumn-numberOther] = 1.0; } if (markKnapsack[iKnapsack] < 0) { // convexity row finalModel->addRow(numberFinal - numberOther, buildRow, buildElement, 1.0, 1.0); } else { int iColumn = markKnapsack[iKnapsack]; int n = numberFinal - numberOther; buildRow[n] = iColumn; buildElement[n++] = -fabs(coefficient[iKnapsack]); // convexity row (sort of) finalModel->addRow(n, buildRow, buildElement, 0.0, 0.0); OsiSOS * sosObject = new OsiSOS(finalModel, n - 1, buildRow, NULL, 1); sosObject->setPriority(iKnapsack + SOSPriority); // Say not integral even if is (switch off heuristics) sosObject->setIntegerValued(false); object[nSOS++] = sosObject; } numberOther = numberFinal; } finalModel->addObjects(nObj, object); for (iKnapsack = 0; iKnapsack < nObj; iKnapsack++) delete object[iKnapsack]; delete [] object; // Can we move any rows to cuts const int * cutMarker = coinModel.cutMarker(); if (cutMarker && 0) { printf("AMPL CUTS OFF until global cuts fixed\n"); cutMarker = NULL; } if (cutMarker) { // Row copy const CoinPackedMatrix * matrixByRow = finalModel->getMatrixByRow(); const double * elementByRow = matrixByRow->getElements(); const int * column = matrixByRow->getIndices(); const CoinBigIndex * rowStart = matrixByRow->getVectorStarts(); const int * rowLength = matrixByRow->getVectorLengths(); const double * rowLower = finalModel->getRowLower(); const double * rowUpper = finalModel->getRowUpper(); int nDelete = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (cutMarker[iRow] && lookupRow[iRow] >= 0) { int jRow = lookupRow[iRow]; whichRow[nDelete++] = jRow; int start = rowStart[jRow]; stored.addCut(rowLower[jRow], rowUpper[jRow], rowLength[jRow], column + start, elementByRow + start); } } finalModel->deleteRows(nDelete, whichRow); } knapsackStart[numberKnapsack] = finalModel->getNumCols(); delete [] buildObj; delete [] buildElement; delete [] buildStart; delete [] buildRow; finalModel->writeMps("full"); } } } delete [] whichKnapsack; delete [] markRow; delete [] markKnapsack; delete [] coefficient; delete [] linear; delete [] whichRow; delete [] lookupRow; delete si; si = NULL; if (!badModel && finalModel) { finalModel->setDblParam(OsiObjOffset, coinModel.objectiveOffset()); return finalModel; } else { delete finalModel; printf("can't make knapsacks - did you set fixedPriority (extra1)\n"); return NULL; } } #endif //COIN_HAS_LINK // Fills in original solution (coinModel length) void afterKnapsack(const CoinModel & coinModel2, const int * whichColumn, const int * knapsackStart, const int * knapsackRow, int numberKnapsack, const double * knapsackSolution, double * solution, int logLevel) { CoinModel coinModel = coinModel2; int numberColumns = coinModel.numberColumns(); int iColumn; // associate all columns to stop possible error messages for (iColumn=0;iColumn1.0e-5) { if (k>=0) { printf("Two nonzero values for knapsack %d at (%d,%g) and (%d,%g)\n",iKnapsack, k,knapsackSolution[k],iColumn,knapsackSolution[iColumn]); abort(); } k=iColumn; assert (fabs(floor(knapsackSolution[iColumn]+0.5)-knapsackSolution[iColumn])<1.0e-5); } } if (k>=0) { int iRow = knapsackRow[iKnapsack]; int nCreate = 10000; int nel=coinModel.expandKnapsack(iRow,nCreate,NULL,NULL,buildRow,buildElement,k-knapsackStart[iKnapsack]); assert (nel); if (logLevel>0) printf("expanded column %d in knapsack %d has %d nonzero entries:\n", k-knapsackStart[iKnapsack],iKnapsack,nel); for (int i=0;i0) printf("%d - original %d has value %g\n",i,jColumn,value); solution[jColumn]=value; } } } delete [] buildRow; delete [] buildElement; #if 0 for (iColumn=0;iColumn1.0e-5&&coinModel.isInteger(iColumn)) printf("%d %g\n",iColumn,solution[iColumn]); } #endif } Cbc-2.8.12/src/CbcHeuristicRINS.cpp0000644000076600007660000003073112131315050015302 0ustar coincoin/* $Id: CbcHeuristicRINS.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcHeuristicRINS.hpp" #include "CbcBranchActual.hpp" #include "CbcStrategy.hpp" #include "CglPreProcess.hpp" // Default Constructor CbcHeuristicRINS::CbcHeuristicRINS() : CbcHeuristic() { numberSolutions_ = 0; numberSuccesses_ = 0; numberTries_ = 0; stateOfFixing_ = 0; shallowDepth_ = 0; lastNode_ = -999999; howOften_ = 100; decayFactor_ = 0.5; used_ = NULL; whereFrom_ = 1 + 8 + 16 + 255 * 256; whereFrom_ = 1 + 8 + 255 * 256; } // Constructor with model - assumed before cuts CbcHeuristicRINS::CbcHeuristicRINS(CbcModel & model) : CbcHeuristic(model) { numberSolutions_ = 0; numberSuccesses_ = 0; numberTries_ = 0; stateOfFixing_ = 0; shallowDepth_ = 0; lastNode_ = -999999; howOften_ = 100; decayFactor_ = 0.5; assert(model.solver()); int numberColumns = model.solver()->getNumCols(); used_ = new char[numberColumns]; memset(used_, 0, numberColumns); whereFrom_ = 1 + 8 + 16 + 255 * 256; whereFrom_ = 1 + 8 + 255 * 256; } // Destructor CbcHeuristicRINS::~CbcHeuristicRINS () { delete [] used_; } // Clone CbcHeuristic * CbcHeuristicRINS::clone() const { return new CbcHeuristicRINS(*this); } // Assignment operator CbcHeuristicRINS & CbcHeuristicRINS::operator=( const CbcHeuristicRINS & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); numberSolutions_ = rhs.numberSolutions_; howOften_ = rhs.howOften_; numberSuccesses_ = rhs.numberSuccesses_; numberTries_ = rhs.numberTries_; stateOfFixing_ = rhs.stateOfFixing_; lastNode_ = rhs.lastNode_; delete [] used_; if (model_ && rhs.used_) { int numberColumns = model_->solver()->getNumCols(); used_ = new char[numberColumns]; memcpy(used_, rhs.used_, numberColumns); } else { used_ = NULL; } } return *this; } // Create C++ lines to get to current state void CbcHeuristicRINS::generateCpp( FILE * fp) { CbcHeuristicRINS other; fprintf(fp, "0#include \"CbcHeuristicRINS.hpp\"\n"); fprintf(fp, "3 CbcHeuristicRINS heuristicRINS(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicRINS"); if (howOften_ != other.howOften_) fprintf(fp, "3 heuristicRINS.setHowOften(%d);\n", howOften_); else fprintf(fp, "4 heuristicRINS.setHowOften(%d);\n", howOften_); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicRINS);\n"); } // Copy constructor CbcHeuristicRINS::CbcHeuristicRINS(const CbcHeuristicRINS & rhs) : CbcHeuristic(rhs), numberSolutions_(rhs.numberSolutions_), howOften_(rhs.howOften_), numberSuccesses_(rhs.numberSuccesses_), numberTries_(rhs.numberTries_), stateOfFixing_(rhs.stateOfFixing_), lastNode_(rhs.lastNode_) { if (model_ && rhs.used_) { int numberColumns = model_->solver()->getNumCols(); used_ = new char[numberColumns]; memcpy(used_, rhs.used_, numberColumns); } else { used_ = NULL; } } // Resets stuff if model changes void CbcHeuristicRINS::resetModel(CbcModel * /*model*/) { //CbcHeuristic::resetModel(model); delete [] used_; stateOfFixing_ = 0; if (model_ && used_) { int numberColumns = model_->solver()->getNumCols(); used_ = new char[numberColumns]; memset(used_, 0, numberColumns); } else { used_ = NULL; } } /* First tries setting a variable to better value. If feasible then tries setting others. If not feasible then tries swaps Returns 1 if solution, 0 if not */ int CbcHeuristicRINS::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; int returnCode = 0; const double * bestSolution = model_->bestSolution(); if (!bestSolution) return 0; // No solution found yet if (numberSolutions_ < model_->getSolutionCount()) { // new solution - add info numberSolutions_ = model_->getSolutionCount(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double value = bestSolution[iColumn]; if (value < originalLower) { value = originalLower; } else if (value > originalUpper) { value = originalUpper; } double nearest = floor(value + 0.5); // if away from lower bound mark that fact if (nearest > originalLower) { used_[iColumn] = 1; } } } int numberNodes = model_->getNodeCount(); if (howOften_ == 100) { if (numberNodes < lastNode_ + 12) return 0; // Do at 50 and 100 if ((numberNodes > 40 && numberNodes <= 50) || (numberNodes > 90 && numberNodes < 100)) numberNodes = howOften_; } // Allow for infeasible nodes - so do anyway after a bit if (howOften_ >= 100 && numberNodes >= lastNode_ + 2*howOften_) { numberNodes = howOften_; } if ((numberNodes % howOften_) == 0 && (model_->getCurrentPassNumber() == 1 || model_->getCurrentPassNumber() == 999999)) { lastNode_ = model_->getNodeCount(); OsiSolverInterface * solver = model_->solver(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double * currentSolution = solver->getColSolution(); const int * used = model_->usedInSolution(); OsiSolverInterface * newSolver = cloneBut(3); // was model_->continuousSolver()->clone(); int numberColumns = newSolver->getNumCols(); int numberContinuous = numberColumns - numberIntegers; double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); int i; int nFix = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double valueInt = bestSolution[iColumn]; if (valueInt < originalLower) { valueInt = originalLower; } else if (valueInt > originalUpper) { valueInt = originalUpper; } if (fabs(currentSolution[iColumn] - valueInt) < 10.0*primalTolerance) { double nearest = floor(valueInt + 0.5); /* shallowDepth_ 0 - normal 1 - only fix if at lb 2 - only fix if not at lb 3 - only fix if at lb and !used */ bool fix=false; switch (shallowDepth_) { case 0: fix = true; break; case 1: if (nearest==originalLower) fix = true; break; case 2: if (nearest!=originalLower) fix = true; break; case 3: if (nearest==originalLower && !used[iColumn]) fix = true; break; } if (fix) { newSolver->setColLower(iColumn, nearest); newSolver->setColUpper(iColumn, nearest); nFix++; } } } int divisor = 0; if (5*nFix > numberIntegers) { if (numberContinuous > 2*numberIntegers && ((nFix*10 < numberColumns && !numRuns_ && numberTries_ > 2) || stateOfFixing_)) { #define RINS_FIX_CONTINUOUS #ifdef RINS_FIX_CONTINUOUS const double * colLower = newSolver->getColLower(); //const double * colUpper = newSolver->getColUpper(); int nAtLb = 0; //double sumDj=0.0; const double * dj = newSolver->getReducedCost(); double direction = newSolver->getObjSense(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { double value = bestSolution[iColumn]; if (value < colLower[iColumn] + 1.0e-8) { //double djValue = dj[iColumn]*direction; nAtLb++; //sumDj += djValue; } } } if (nAtLb) { // fix some continuous double * sort = new double[nAtLb]; int * which = new int [nAtLb]; //double threshold = CoinMax((0.01*sumDj)/static_cast(nAtLb),1.0e-6); int nFix2 = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { double value = bestSolution[iColumn]; if (value < colLower[iColumn] + 1.0e-8) { double djValue = dj[iColumn] * direction; if (djValue > 1.0e-6) { sort[nFix2] = -djValue; which[nFix2++] = iColumn; } } } } CoinSort_2(sort, sort + nFix2, which); divisor = 4; if (stateOfFixing_ > 0) divisor = stateOfFixing_; else if (stateOfFixing_ < -1) divisor = (-stateOfFixing_) - 1; nFix2 = CoinMin(nFix2, (numberColumns - nFix) / divisor); for (int i = 0; i < nFix2; i++) { int iColumn = which[i]; newSolver->setColUpper(iColumn, colLower[iColumn]); } delete [] sort; delete [] which; #ifdef CLP_INVESTIGATE2 printf("%d integers have same value, and %d continuous fixed at lb\n", nFix, nFix2); #endif } #endif } //printf("%d integers have same value\n",nFix); returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicRINS"); if (returnCode < 0) { returnCode = 0; // returned on size if (divisor) { stateOfFixing_ = - divisor; // say failed } else if (numberContinuous > 2*numberIntegers && !numRuns_ && numberTries_ > 2) { stateOfFixing_ = -4; //start fixing } } else { numRuns_++; if (divisor) stateOfFixing_ = divisor; // say small enough } if ((returnCode&1) != 0) numberSuccesses_++; //printf("return code %d",returnCode); if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; //printf("could add cut with %d elements (if all 0-1)\n",nFix); } else { //printf("\n"); } } numberTries_++; if ((numberTries_ % 10) == 0 && numberSuccesses_*3 < numberTries_) howOften_ += static_cast (howOften_ * decayFactor_); delete newSolver; } return returnCode; } // update model void CbcHeuristicRINS::setModel(CbcModel * model) { model_ = model; // Get a copy of original matrix assert(model_->solver()); delete [] used_; int numberColumns = model->solver()->getNumCols(); used_ = new char[numberColumns]; memset(used_, 0, numberColumns); } Cbc-2.8.12/src/unitTest.cpp0000644000076600007660000003362311575435606014106 0ustar coincoin/* $Id: unitTest.cpp 1668 2011-06-13 16:32:06Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Test individual classes or groups of classes #include "CbcConfig.h" #include "CoinPragma.hpp" #include #include #include #include #include #include "CoinHelperFunctions.hpp" #include "CoinFileIO.hpp" #ifdef COIN_HAS_CBC #include "OsiCbcSolverInterface.hpp" #endif #ifdef COIN_HAS_OSL #include "OsiOslSolverInterface.hpp" #endif #ifdef COIN_HAS_SPX #include "OsiSpxSolverInterface.hpp" #endif #ifdef COIN_HAS_DYLP #include "OsiDylpSolverInterface.hpp" #endif #ifdef COIN_HAS_GLPK #include "OsiGlpkSolverInterface.hpp" #endif #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #endif #ifdef NDEBUG #undef NDEBUG #endif #include "CoinTime.hpp" // Function Prototypes. Function definitions is in this file. void testingMessage( const char * const msg ); #ifdef COIN_HAS_CBC void CbcMiplibTest (const std::vector & vecEmptySiP, const std::string & mpsDir) { int i ; unsigned int m ; // See if files exist FILE * fp; bool doTest = false; std::string test1 = mpsDir + "p0033"; fp = fopen(test1.c_str(), "r"); if (fp) { doTest = true; fclose(fp); } if (!doTest && CoinFileInput::haveGzipSupport()) { test1 += ".gz"; fp = fopen(test1.c_str(), "r"); if (fp) { doTest = true; fclose(fp); } } if (!doTest) return; /* Vectors to hold test problem names and characteristics. The objective value after optimization (objValue) must agree to the specified tolerance (objValueTol). */ std::vector mpsName ; std::vector nRows ; std::vector nCols ; std::vector objValueC ; std::vector objValue ; std::vector strategy ; /* And a macro to make the vector creation marginally readable. */ #define PUSH_MPS(zz_mpsName_zz,\ zz_nRows_zz,zz_nCols_zz,zz_objValue_zz,zz_objValueC_zz, \ zz_strategy_zz) \ mpsName.push_back(zz_mpsName_zz) ; \ nRows.push_back(zz_nRows_zz) ; \ nCols.push_back(zz_nCols_zz) ; \ objValueC.push_back(zz_objValueC_zz) ; \ strategy.push_back(zz_strategy_zz) ; \ objValue.push_back(zz_objValue_zz) ; /* Load up the problem vector. Note that the row counts here include the objective function. Set HOWMANY to 0 for no test, 1 for some, 2 for many, 3 for all. */ #define HOWMANY 1 #if HOWMANY #if HOWMANY>1 PUSH_MPS("10teams", 230, 2025, 924, 917, 7) #endif PUSH_MPS("air03", 124, 10757, 340160, 338864.25, 7) #if HOWMANY==3 PUSH_MPS("air04", 823, 8904, 56137, 55535.436, 8) PUSH_MPS("air05", 426, 7195, 26374, 25877.609, 8) #endif // PUSH_MPS("arki001",1048,1388,7580813.0459,7579599.80787,7) PUSH_MPS("bell3a", 123, 133, 878430.32, 862578.64, 7) #if HOWMANY>1 PUSH_MPS("bell5", 91, 104, 8966406.49, 8608417.95, 7) #endif PUSH_MPS("blend2", 274, 353, 7.598985, 6.9156751140, 7) #if HOWMANY>1 PUSH_MPS("cap6000", 2176, 6000, -2451377, -2451537.325, 7) #endif // PUSH_MPS("dano3mip",3202,13873,728.1111,576.23162474,7) // PUSH_MPS("danoint",664,521,65.67,62.637280418,7) PUSH_MPS("dcmulti", 290, 548, 188182, 183975.5397, 7) PUSH_MPS("dsbmip", 1182, 1886, -305.19817501, -305.19817501, 7) PUSH_MPS("egout", 98, 141, 568.101, 149.589, 7) PUSH_MPS("enigma", 21, 100, 0.0, 0.0, 7) #if HOWMANY==3 PUSH_MPS("fast0507", 507, 63009, 174, 172.14556668, 7) #endif PUSH_MPS("fiber", 363, 1298, 405935.18000, 156082.51759, 7) #if HOWMANY>1 PUSH_MPS("fixnet6", 478, 878, 3983, 1200.88, 7) #endif PUSH_MPS("flugpl", 18, 18, 1201500, 1167185.7, 7) PUSH_MPS("gen", 780, 870, 112313, 112130.0, 7) #if HOWMANY>1 PUSH_MPS("gesa2", 1392, 1224, 25779856.372, 25476489.678, 7) PUSH_MPS("gesa2_o", 1248, 1224, 25779856.372, 25476489.678, 7) #endif PUSH_MPS("gesa3", 1368, 1152, 27991042.648, 27833632.451, 7) PUSH_MPS("gesa3_o", 1224, 1152, 27991042.648, 27833632.451, 7) PUSH_MPS("gt2", 29, 188, 21166.000, 13460.233074, 7) #if HOWMANY==3 PUSH_MPS("harp2", 112, 2993, -73899798.00, -74353341.502, 7) #endif PUSH_MPS("khb05250", 101, 1350, 106940226, 95919464.0, 7) #if HOWMANY>1 PUSH_MPS("l152lav", 97, 1989, 4722, 4656.36, 7) #endif PUSH_MPS("lseu", 28, 89, 1120, 834.68, 7) PUSH_MPS("misc03", 96, 160, 3360, 1910., 7) PUSH_MPS("misc06", 820, 1808, 12850.8607, 12841.6, 7) #if HOWMANY>1 PUSH_MPS("misc07", 212, 260, 2810, 1415.0, 7) PUSH_MPS("mitre", 2054, 10724, 115155, 114740.5184, 7) #endif PUSH_MPS("mod008", 6, 319, 307, 290.9, 7) PUSH_MPS("mod010", 146, 2655, 6548, 6532.08, 7) #if HOWMANY==3 PUSH_MPS("mod011", 4480, 10958, -54558535, -62121982.55, 7) PUSH_MPS("modglob", 291, 422, 20740508, 20430947., 7) PUSH_MPS("noswot", 182, 128, -43, -43.0, 7) #endif #if HOWMANY>1 PUSH_MPS("nw04", 36, 87482, 16862, 16310.66667, 7) #endif PUSH_MPS("p0033", 16, 33, 3089, 2520.57, 7) PUSH_MPS("p0201", 133, 201, 7615, 6875.0, 7) PUSH_MPS("p0282", 241, 282, 258411, 176867.50, 7) PUSH_MPS("p0548", 176, 548, 8691, 315.29, 7) PUSH_MPS("p2756", 755, 2756, 3124, 2688.75, 7) #if HOWMANY==3 PUSH_MPS("pk1", 45, 86, 11.0, 0.0, 7) #endif #if HOWMANY>1 PUSH_MPS("pp08a", 136, 240, 7350.0, 2748.3452381, 7) PUSH_MPS("pp08aCUTS", 246, 240, 7350.0, 5480.6061563, 7) #endif #if HOWMANY==3 PUSH_MPS("qiu", 1192, 840, -132.873137, -931.638857, 7) #endif PUSH_MPS("qnet1", 503, 1541, 16029.692681, 14274.102667, 7) PUSH_MPS("qnet1_o", 456, 1541, 16029.692681, 12095.571667, 7) PUSH_MPS("rentacar", 6803, 9557, 30356761, 28806137.644, 7) PUSH_MPS("rgn", 24, 180, 82.1999, 48.7999, 7) #if HOWMANY==3 PUSH_MPS("rout", 291, 556, 1077.56, 981.86428571, 7) PUSH_MPS("set1ch", 492, 712, 54537.75, 32007.73, 7) #endif // PUSH_MPS("seymour",4944,1372,423,403.84647413,7) PUSH_MPS("stein27", 118, 27, 18, 13.0, 7) #if HOWMANY>1 PUSH_MPS("stein45", 331, 45, 30, 22.0, 7) #endif PUSH_MPS("vpm1", 234, 378, 20, 15.4167, 7) PUSH_MPS("vpm2", 234, 378, 13.75, 9.8892645972, 7) #endif #undef PUSH_MPS /* Create a vector of solver interfaces that we can use to run the test problems. The strategy is to create a fresh clone of the `empty' solvers from vecEmptySiP for each problem, then proceed in stages: read the MPS file, solve the problem, check the solution. If there are multiple solvers in vecSiP, the results of each solver are compared with its neighbors in the vector. */ int numberSolvers = vecEmptySiP.size(); std::vector vecSiP(numberSolvers) ; // Create vector to store a name for each solver interface // and a count on the number of problems the solver interface solved. std::vector siName; std::vector numProbSolved; std::vector timeTaken; for ( i = 0; i < numberSolvers; i++ ) { std::string name; vecEmptySiP[i]->getStrParam(OsiSolverName, name); siName.push_back(name); numProbSolved.push_back(0); timeTaken.push_back(0.0); } /* Open the main loops. Outer loop steps through MPS problems, inner loop steps through solvers. */ for (m = 0 ; m < mpsName.size() ; m++) { std::cerr << " processing mps file: " << mpsName[m] << " (" << m + 1 << " out of " << mpsName.size() << ")" << std::endl ; for (i = vecSiP.size() - 1 ; i >= 0 ; --i) { vecSiP[i] = vecEmptySiP[i]->clone() ; /* Stage 1: Read the MPS file into the solver interface. As a basic check, make sure the size of the constraint matrix is correct. */ std::string fn = mpsDir + mpsName[m] ; vecSiP[i]->readMps(fn.c_str(), "") ; vecSiP[i]->setObjSense(1.0) ; int nr = vecSiP[i]->getNumRows() ; int nc = vecSiP[i]->getNumCols() ; assert(nr == nRows[m]) ; assert(nc == nCols[m]) ; /* Stage 2: Call the solver to get a solution for the LP relaxation. */ double startTime = CoinCpuTime(); OsiCbcSolverInterface * integerSolver = dynamic_cast(vecSiP[i]) ; assert(integerSolver); integerSolver->initialSolve(); /* Stage 3: Call the solver to perform branch and cut. We call each solver, then check the return code and objective. Limits are 50000 nodes and one hour of time. */ integerSolver->setMaximumNodes(50000); integerSolver->setMaximumSeconds(60*60); integerSolver->getModelPtr()->messageHandler()->setLogLevel(1) ; integerSolver->branchAndBound(); double timeOfSolution = CoinCpuTime() - startTime; if (!integerSolver->status()) { double soln = integerSolver->getObjValue(); CoinRelFltEq eq(1.0e-3) ; if (eq(soln, objValue[m])) { std::cerr << siName[i] << " " << soln << " = " << objValue[m] << " ; okay"; numProbSolved[i]++; } else { std::cerr << siName[i] << " " << soln << " != " << objValue[m] << "; error=" ; std::cerr << fabs(objValue[m] - soln); } } else { std::cerr << "error; too many nodes" ; } std::cerr << " - took " << timeOfSolution << " seconds." << std::endl; timeTaken[i] += timeOfSolution; delete integerSolver; } } const int siName_size = siName.size(); for ( i = 0; i < siName_size; i++ ) { std::cerr << siName[i] << " solved " << numProbSolved[i] << " out of " << objValue.size() << " and took " << timeTaken[i] << " seconds." << std::endl; } } #endif // COIN_HAS_CBC //---------------------------------------------------------------- // unitTest [-miplibDir=V2] // // where: // -miplibDir: directory containing miplib files // Default value V2="./examples/miplib3" // // All parameters are optional. //---------------------------------------------------------------- int mainTest (int argc, const char *argv[]) { int i; // define valid parameter keywords std::set definedKeyWords; definedKeyWords.insert("-miplibDir"); // Create a map of parameter keys and associated data std::map parms; for ( i = 1; i < argc; i++ ) { std::string parm(argv[i]); std::string key, value; unsigned int eqPos = parm.find('='); // Does parm contain and '=' if ( eqPos == std::string::npos ) { //Parm does not contain '=' key = parm; } else { key = parm.substr(0, eqPos); value = parm.substr(eqPos + 1); } // Is specifed key valid? if ( definedKeyWords.find(key) == definedKeyWords.end() ) { // invalid key word. // Write help text std::cerr << "Undefined parameter \"" << key << "\".\n"; std::cerr << "Correct usage: \n"; std::cerr << " unitTest [-miplibDir=V2] \n"; std::cerr << " where:\n"; std::cerr << " -miplibDir: directory containing miplib files\n"; std::cerr << " Default value V2=\"./Data/miplib3\"\n"; return 1; } parms[key] = value; } const char dirsep = CoinFindDirSeparator(); // Set directory containing miplib data files. std::string miplibDir; if (parms.find("-miplibDir") != parms.end()) miplibDir = parms["-miplibDir"] + dirsep; else miplibDir = dirsep == '/' ? "./Data/miplib3/" : ".\\Data\\miplib3\\"; #ifdef COIN_HAS_CBC { // Create vector of solver interfaces std::vector vecSi; CbcStrategyDefault strategy(0); # if COIN_HAS_OSL OsiSolverInterface * oslSi = new OsiOslSolverInterface; vecSi.push_back(new OsiCbcSolverInterface(oslSi, &strategy)); #endif # if COIN_HAS_SPX OsiSolverInterface * spxSi = new OsiSpxSolverInterface; vecSi.push_back(new OsiCbcSolverInterface(spxSi, &strategy)); #endif # if COIN_HAS_CLP OsiSolverInterface *clpSi = new OsiClpSolverInterface ; /* Quiet, already! */ clpSi->setHintParam(OsiDoReducePrint, true, OsiHintDo) ; vecSi.push_back(new OsiCbcSolverInterface(clpSi, &strategy)); #endif # if COIN_HAS_DYLP OsiSolverInterface * dylpSi = new OsiDylpSolverInterface; vecSi.push_back(new OsiCbcSolverInterface(dylpSi, &strategy)); #endif # if COIN_HAS_GLPK OsiSolverInterface * glpkSi = new OsiGlpkSolverInterface; vecSi.push_back(new OsiCbcSolverInterface(glpkSi, &strategy)); #endif testingMessage( "Testing some miplib stuff\n" ); CbcMiplibTest(vecSi, miplibDir); unsigned int i; for (i = 0; i < vecSi.size(); i++) delete vecSi[i]; } #else // COIN_HAS_CBC std::cerr << "cbc has been built without OsiCbc support. To enable the -miplib\n" << "option, you must enable libOsiCbc in Makefile.location, then\n" << "execute the command `make clean cbc' to rebuild the cbc program." << std::endl ; #endif // COIN_HAS_CBC testingMessage( "All tests completed successfully\n" ); return 0; } // Display message on stdout and stderr void testingMessage( const char * const msg ) { std::cerr << msg << std::endl ; // std::cout << msg << std::endl ; } Cbc-2.8.12/src/CbcGenMessages.cpp0000644000076600007660000001264112131315050015050 0ustar coincoin/*! \legal Copyright (C) 2007 Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenMessages.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #include "CbcGenMessages.hpp" #include "CbcGenCtlBlk.hpp" namespace { char svnid[] = "$Id: CbcGenMessages.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } /* Begin file local namespace */ namespace { /* Message definitions. The precise form isn't important here, so long as the method that loads them into a CoinMessages object can come up with values for external ID, detail level, and format string. The use of an enum to provide an internal ID for each message is mainly useful with the internationalisation feature. It makes it easy to slap the same ID on alternate versions of a message. */ typedef struct { CbcGenMsgCode inID ; int exID ; int lvl ; const char *fmt ; } MsgDefn ; static MsgDefn us_en_defns[] = { // informational (0 -- 2999) { CBCGEN_TEST_MSG, 1, 2, "This is the us_en test message, eh." }, { CBCGEN_NEW_SOLVER, 2, 2, "Solver is now \"%s\"." }, // warning (3000 -- 5999) // Non-fatal errors (6000 -- 8999) // Fatal errors (9000 and up) { CBCGEN_CONFUSION, 9001, 1, "Internal confusion, line %d." }, { CBCGEN_DUMMY_END, 999999, 0, "" } } ; /* We seem to need a dummy CoinMessages object to prevent the compiler from complaining that CoinMessages::Language is unintialised. const CoinMessages dummy(0) ; */ /* The author is Canadian, eh. But we'll go with us_en anyways. */ const CoinMessages::Language default_language = CoinMessages::us_en ; } /* End file local namespace */ /*! This function constructs a CoinMessages object filled with a default set of messages, overlaid with whatever is available for the specified language. It is used to establish the initial set of messages, and is also called whenever the language is changed. The latter, because there's no way of guaranteeing that the message sets for alternate languages will all replace the same messages. This approach guarantees that the set of messages is always composed of the default language overlaid with any messages for an alternate language. The default for lang is us_en, specified up in CbcGenCtlBlk.hpp. If you want to change the default language, change the declaration there. That said, you'll also have to provide the necessary message definitions and augment the case statements below. */ void CbcGenCtlBlk::setMessages (CoinMessages::Language lang) { /* If messages exist, in the correct language, we have nothing more to do. */ if (msgs_ && cur_lang_ == lang) { return ; } /* Otherwise, we need to do a wholesale rebuild. Create a new object of the appropriate size. */ CoinMessages *msgs = new CoinMessages(sizeof(us_en_defns) / sizeof(MsgDefn)) ; msgs->setLanguage(lang) ; strcpy(msgs->source_, "CbcG"); /* Yes, this is gloriously redundant, but it's set up in anticipation of future extensions. */ MsgDefn *msgdefn ; switch (lang) { case CoinMessages::us_en: { msgdefn = us_en_defns ; break ; } default: { msgdefn = us_en_defns ; break ; } } /* Open a loop to create and load the messages. */ while (msgdefn->inID != CBCGEN_DUMMY_END) { CoinOneMessage msg(msgdefn->exID, msgdefn->lvl, msgdefn->fmt) ; msgs->addMessage(msgdefn->inID, msg) ; msgdefn++ ; } /* Now, if the local language differs from the default language, load any overrides. Again, useless now, but maybe in the future ... */ if (lang != cur_lang_) { switch (lang) { case CoinMessages::us_en: { msgdefn = us_en_defns ; break; } default: { msgdefn = us_en_defns ; break; } } while (msgdefn->inID != CBCGEN_DUMMY_END) { msgs->replaceMessage(msgdefn->inID, msgdefn->fmt) ; msgdefn++ ; } } /* Each CoinOneMessage has a fixed-length array to hold the message; by default this is 400 chars. Convert to `compressed' CoinOneMessage objects where the array is only as large as necessary. Any attempt to replace a message, or the message text, will automatically trigger a decompress operation before doing the replacement, but the messages will *not* be automatically recompressed. */ msgs->toCompact() ; msgs_ = msgs ; return ; } /* Replaces the current message handler with the handler supplied as a parameter. If ourMsgHandler_ is true, the existing handler is destroyed. */ void CbcGenCtlBlk::passInMessageHandler (CoinMessageHandler *newMsgHandler) { if (msgHandler_ && ourMsgHandler_) { delete msgHandler_ ; } msgHandler_ = newMsgHandler ; ourMsgHandler_ = false ; return ; } /* Start a message. This routine buries the whole business of locating the message handler and messages, getting the log level right, etc. If, by some chance, messages are not yet loaded, do so. */ CoinMessageHandler &CbcGenCtlBlk::message (CbcGenMsgCode inID) { if (!msgs_) { setMessages() ; } msgHandler_->setLogLevel(logLvl_) ; msgHandler_->message(inID, *msgs_) ; return (*msgHandler_) ; } Cbc-2.8.12/src/CbcModel.hpp0000644000076600007660000031267212371443325013740 0ustar coincoin/* $Id: CbcModel.hpp 2055 2014-08-09 16:05:41Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcModel_H #define CbcModel_H #include #include #include "CoinMessageHandler.hpp" #include "OsiSolverInterface.hpp" #include "OsiBranchingObject.hpp" #include "OsiCuts.hpp" #include "CoinWarmStartBasis.hpp" #include "CbcCompareBase.hpp" #include "CbcCountRowCut.hpp" #include "CbcMessage.hpp" #include "CbcEventHandler.hpp" #include "ClpDualRowPivot.hpp" class CbcCutGenerator; class CbcBaseModel; class OsiRowCut; class OsiBabSolver; class OsiRowCutDebugger; class CglCutGenerator; class CglStored; class CbcCutModifier; class CglTreeProbingInfo; class CbcHeuristic; class OsiObject; class CbcThread; class CbcTree; class CbcStrategy; class CbcFeasibilityBase; class CbcStatistics; class CbcFullNodeInfo; class CbcEventHandler ; class CglPreProcess; class OsiClpSolverInterface; class ClpNodeStuff; // #define CBC_CHECK_BASIS 1 //############################################################################# /** Simple Branch and bound class The initialSolve() method solves the initial LP relaxation of the MIP problem. The branchAndBound() method can then be called to finish using a branch and cut algorithm.

Search Tree Traversal

Subproblems (aka nodes) requiring additional evaluation are stored using the CbcNode and CbcNodeInfo objects. Ancestry linkage is maintained in the CbcNodeInfo object. Evaluation of a subproblem within branchAndBound() proceeds as follows:
  • The node representing the most promising parent subproblem is popped from the heap which holds the set of subproblems requiring further evaluation.
  • Using branching instructions stored in the node, and information in its ancestors, the model and solver are adjusted to create the active subproblem.
  • If the parent subproblem will require further evaluation (i.e., there are branches remaining) its node is pushed back on the heap. Otherwise, the node is deleted. This may trigger recursive deletion of ancestors.
  • The newly created subproblem is evaluated.
  • If the subproblem requires further evaluation, a node is created. All information needed to recreate the subproblem (branching information, row and column cuts) is placed in the node and the node is added to the set of subproblems awaiting further evaluation.
Note that there is never a node representing the active subproblem; the model and solver represent the active subproblem.

Row (Constraint) Cut Handling

For a typical subproblem, the sequence of events is as follows:
  • The subproblem is rebuilt for further evaluation: One result of a call to addCuts() is a traversal of ancestors, leaving a list of all cuts used in the ancestors in #addedCuts_. This list is then scanned to construct a basis that includes only tight cuts. Entries for loose cuts are set to NULL.
  • The subproblem is evaluated: One result of a call to solveWithCuts() is the return of a set of newly generated cuts for the subproblem. #addedCuts_ is also kept up-to-date as old cuts become loose.
  • The subproblem is stored for further processing: A call to CbcNodeInfo::addCuts() adds the newly generated cuts to the CbcNodeInfo object associated with this node.
See CbcCountRowCut for details of the bookkeeping associated with cut management. */ class CbcModel { public: enum CbcIntParam { /** The maximum number of nodes before terminating */ CbcMaxNumNode = 0, /** The maximum number of solutions before terminating */ CbcMaxNumSol, /** Fathoming discipline Controls objective function comparisons for purposes of fathoming by bound or determining monotonic variables. If 1, action is taken only when the current objective is strictly worse than the target. Implementation is handled by adding a small tolerance to the target. */ CbcFathomDiscipline, /** Adjusts printout 1 does different node message with number unsatisfied on last branch */ CbcPrinting, /** Number of branches (may be more than number of nodes as may include strong branching) */ CbcNumberBranches, /** Just a marker, so that a static sized array can store parameters. */ CbcLastIntParam }; enum CbcDblParam { /** The maximum amount the value of an integer variable can vary from integer and still be considered feasible. */ CbcIntegerTolerance = 0, /** The objective is assumed to worsen by this amount for each integer infeasibility. */ CbcInfeasibilityWeight, /** The amount by which to tighten the objective function cutoff when a new solution is discovered. */ CbcCutoffIncrement, /** Stop when the gap between the objective value of the best known solution and the best bound on the objective of any solution is less than this. This is an absolute value. Conversion from a percentage is left to the client. */ CbcAllowableGap, /** Stop when the gap between the objective value of the best known solution and the best bound on the objective of any solution is less than this fraction of of the absolute value of best known solution. Code stops if either this test or CbcAllowableGap test succeeds */ CbcAllowableFractionGap, /** \brief The maximum number of seconds before terminating. A double should be adequate! */ CbcMaximumSeconds, /// Cutoff - stored for speed CbcCurrentCutoff, /// Optimization direction - stored for speed CbcOptimizationDirection, /// Current objective value CbcCurrentObjectiveValue, /// Current minimization objective value CbcCurrentMinimizationObjectiveValue, /** \brief The time at start of model. So that other pieces of code can access */ CbcStartSeconds, /** Stop doing heuristics when the gap between the objective value of the best known solution and the best bound on the objective of any solution is less than this. This is an absolute value. Conversion from a percentage is left to the client. */ CbcHeuristicGap, /** Stop doing heuristics when the gap between the objective value of the best known solution and the best bound on the objective of any solution is less than this fraction of of the absolute value of best known solution. Code stops if either this test or CbcAllowableGap test succeeds */ CbcHeuristicFractionGap, /// Smallest non-zero change on a branch CbcSmallestChange, /// Sum of non-zero changes on a branch CbcSumChange, /// Largest non-zero change on a branch CbcLargestChange, /// Small non-zero change on a branch to be used as guess CbcSmallChange, /** Just a marker, so that a static sized array can store parameters. */ CbcLastDblParam }; //--------------------------------------------------------------------------- public: ///@name Solve methods //@{ /** \brief Solve the initial LP relaxation Invoke the solver's %initialSolve() method. */ void initialSolve(); /** \brief Invoke the branch \& cut algorithm The method assumes that initialSolve() has been called to solve the LP relaxation. It processes the root node, then proceeds to explore the branch & cut search tree. The search ends when the tree is exhausted or one of several execution limits is reached. If doStatistics is 1 summary statistics are printed if 2 then also the path to best solution (if found by branching) if 3 then also one line per node */ void branchAndBound(int doStatistics = 0); private: /** \brief Evaluate a subproblem using cutting planes and heuristics The method invokes a main loop which generates cuts, applies heuristics, and reoptimises using the solver's native %resolve() method. It returns true if the subproblem remains feasible at the end of the evaluation. */ bool solveWithCuts(OsiCuts & cuts, int numberTries, CbcNode * node); /** Generate one round of cuts - serial mode returns - 0 - normal 1 - must keep going 2 - set numberTries to zero -1 - infeasible */ int serialCuts(OsiCuts & cuts, CbcNode * node, OsiCuts & slackCuts, int lastNumberCuts); /** Generate one round of cuts - parallel mode returns - 0 - normal 1 - must keep going 2 - set numberTries to zero -1 - infeasible */ int parallelCuts(CbcBaseModel * master, OsiCuts & cuts, CbcNode * node, OsiCuts & slackCuts, int lastNumberCuts); /** Input one node output N nodes to put on tree and optional solution update This should be able to operate in parallel so is given a solver and is const(ish) However we will need to keep an array of solver_ and bases and more status is 0 for normal, 1 if solution Calling code should always push nodes back on tree */ CbcNode ** solveOneNode(int whichSolver, CbcNode * node, int & numberNodesOutput, int & status) ; /// Update size of whichGenerator void resizeWhichGenerator(int numberNow, int numberAfter); public: #ifdef CBC_KEEP_DEPRECATED // See if anyone is using these any more!! /** \brief create a clean model from partially fixed problem The method creates a new model with given bounds and with no tree. */ CbcModel * cleanModel(const double * lower, const double * upper); /** \brief Invoke the branch \& cut algorithm on partially fixed problem The method presolves the given model and does branch and cut. The search ends when the tree is exhausted or maximum nodes is reached. If better solution found then it is saved. Returns 0 if search completed and solution, 1 if not completed and solution, 2 if completed and no solution, 3 if not completed and no solution. Normally okay to do cleanModel immediately followed by subBranchandBound (== other form of subBranchAndBound) but may need to get at model for advanced features. Deletes model2 */ int subBranchAndBound(CbcModel * model2, CbcModel * presolvedModel, int maximumNodes); /** \brief Invoke the branch \& cut algorithm on partially fixed problem The method creates a new model with given bounds, presolves it then proceeds to explore the branch & cut search tree. The search ends when the tree is exhausted or maximum nodes is reached. If better solution found then it is saved. Returns 0 if search completed and solution, 1 if not completed and solution, 2 if completed and no solution, 3 if not completed and no solution. This is just subModel immediately followed by other version of subBranchandBound. */ int subBranchAndBound(const double * lower, const double * upper, int maximumNodes); /** \brief Process root node and return a strengthened model The method assumes that initialSolve() has been called to solve the LP relaxation. It processes the root node and then returns a pointer to the strengthened model (or NULL if infeasible) */ OsiSolverInterface * strengthenedModel(); /** preProcess problem - replacing solver If makeEquality true then <= cliques converted to ==. Presolve will be done numberPasses times. Returns NULL if infeasible If makeEquality is 1 add slacks to get cliques, if 2 add slacks to get sos (but only if looks plausible) and keep sos info */ CglPreProcess * preProcess( int makeEquality = 0, int numberPasses = 5, int tuning = 5); /** Does postprocessing - original solver back. User has to delete process */ void postProcess(CglPreProcess * process); #endif /// Adds an update information object void addUpdateInformation(const CbcObjectUpdateData & data); /** Do one node - broken out for clarity? also for parallel (when baseModel!=this) Returns 1 if solution found node NULL on return if no branches left newNode NULL if no new node created */ int doOneNode(CbcModel * baseModel, CbcNode * & node, CbcNode * & newNode); public: /** \brief Reoptimise an LP relaxation Invoke the solver's %resolve() method. whereFrom - 0 - initial continuous 1 - resolve on branch (before new cuts) 2 - after new cuts 3 - obsolete code or something modified problem in unexpected way 10 - after strong branching has fixed variables at root 11 - after strong branching has fixed variables in tree returns 1 feasible, 0 infeasible, -1 feasible but skip cuts */ int resolve(CbcNodeInfo * parent, int whereFrom, double * saveSolution = NULL, double * saveLower = NULL, double * saveUpper = NULL); /// Make given rows (L or G) into global cuts and remove from lp void makeGlobalCuts(int numberRows, const int * which); /// Make given cut into a global cut void makeGlobalCut(const OsiRowCut * cut); /// Make given cut into a global cut void makeGlobalCut(const OsiRowCut & cut); /// Make given column cut into a global cut void makeGlobalCut(const OsiColCut * cut); /// Make given column cut into a global cut void makeGlobalCut(const OsiColCut & cut); /// Make partial cut into a global cut and save void makePartialCut(const OsiRowCut * cut, const OsiSolverInterface * solver=NULL); /// Make partial cuts into global cuts void makeGlobalCuts(); /// Which cut generator generated this cut inline const int * whichGenerator() const { return whichGenerator_;} //@} /** \name Presolve methods */ //@{ /** Identify cliques and construct corresponding objects. Find cliques with size in the range [\p atLeastThisMany, \p lessThanThis] and construct corresponding CbcClique objects. If \p makeEquality is true then a new model may be returned if modifications had to be made, otherwise \c this is returned. If the problem is infeasible #numberObjects_ is set to -1. A client must use deleteObjects() before a second call to findCliques(). If priorities exist, clique priority is set to the default. */ CbcModel * findCliques(bool makeEquality, int atLeastThisMany, int lessThanThis, int defaultValue = 1000); /** Do integer presolve, creating a new (presolved) model. Returns the new model, or NULL if feasibility is lost. If weak is true then just does a normal presolve \todo It remains to work out the cleanest way of getting a solution to the original problem at the end. So this is very preliminary. */ CbcModel * integerPresolve(bool weak = false); /** Do integer presolve, modifying the current model. Returns true if the model remains feasible after presolve. */ bool integerPresolveThisModel(OsiSolverInterface * originalSolver, bool weak = false); /// Put back information into the original model after integer presolve. void originalModel(CbcModel * presolvedModel, bool weak); /** \brief For variables involved in VUB constraints, see if we can tighten bounds by solving lp's Returns false if feasibility is lost. If CglProbing is available, it will be tried as well to see if it can tighten bounds. This routine is just a front end for tightenVubs(int,const int*,double). If type = -1 all variables are processed (could be very slow). If type = 0 only variables involved in VUBs are processed. If type = n > 0, only the n most expensive VUB variables are processed, where it is assumed that x is at its maximum so delta would have to go to 1 (if x not at bound). If \p allowMultipleBinary is true, then a VUB constraint is a row with one continuous variable and any number of binary variables. If useCutoff < 1.0e30, the original objective is installed as a constraint with \p useCutoff as a bound. */ bool tightenVubs(int type, bool allowMultipleBinary = false, double useCutoff = 1.0e50); /** \brief For variables involved in VUB constraints, see if we can tighten bounds by solving lp's This version is just handed a list of variables to be processed. */ bool tightenVubs(int numberVubs, const int * which, double useCutoff = 1.0e50); /** Analyze problem to find a minimum change in the objective function. */ void analyzeObjective(); /** Add additional integers. */ void AddIntegers(); /** Save copy of the model. */ void saveModel(OsiSolverInterface * saveSolver, double * checkCutoffForRestart, bool * feasible); /** Flip direction of optimization on all models */ void flipModel(); //@} /** \name Object manipulation routines See OsiObject for an explanation of `object' in the context of CbcModel. */ //@{ /// Get the number of objects inline int numberObjects() const { return numberObjects_; } /// Set the number of objects inline void setNumberObjects(int number) { numberObjects_ = number; } /// Get the array of objects inline OsiObject ** objects() const { return object_; } /// Get the specified object const inline OsiObject * object(int which) const { return object_[which]; } /// Get the specified object inline OsiObject * modifiableObject(int which) const { return object_[which]; } void setOptionalInteger(int index); /// Delete all object information (and just back to integers if true) void deleteObjects(bool findIntegers = true); /** Add in object information. Objects are cloned; the owner can delete the originals. */ void addObjects(int numberObjects, OsiObject ** objects); /** Add in object information. Objects are cloned; the owner can delete the originals. */ void addObjects(int numberObjects, CbcObject ** objects); /// Ensure attached objects point to this model. void synchronizeModel() ; /** \brief Identify integer variables and create corresponding objects. Record integer variables and create an CbcSimpleInteger object for each one. If \p startAgain is true, a new scan is forced, overwriting any existing integer variable information. If type > 0 then 1==PseudoCost, 2 new ones low priority */ void findIntegers(bool startAgain, int type = 0); //@} //--------------------------------------------------------------------------- /**@name Parameter set/get methods The set methods return true if the parameter was set to the given value, false if the value of the parameter is out of range. The get methods return the value of the parameter. */ //@{ /// Set an integer parameter inline bool setIntParam(CbcIntParam key, int value) { intParam_[key] = value; return true; } /// Set a double parameter inline bool setDblParam(CbcDblParam key, double value) { dblParam_[key] = value; return true; } /// Get an integer parameter inline int getIntParam(CbcIntParam key) const { return intParam_[key]; } /// Get a double parameter inline double getDblParam(CbcDblParam key) const { return dblParam_[key]; } /*! \brief Set cutoff bound on the objective function. When using strict comparison, the bound is adjusted by a tolerance to avoid accidentally cutting off the optimal solution. */ void setCutoff(double value) ; /// Get the cutoff bound on the objective function - always as minimize inline double getCutoff() const { //double value ; //solver_->getDblParam(OsiDualObjectiveLimit,value) ; //assert( dblParam_[CbcCurrentCutoff]== value * solver_->getObjSense()); return dblParam_[CbcCurrentCutoff]; } /// Set the \link CbcModel::CbcMaxNumNode maximum node limit \endlink inline bool setMaximumNodes( int value) { return setIntParam(CbcMaxNumNode, value); } /// Get the \link CbcModel::CbcMaxNumNode maximum node limit \endlink inline int getMaximumNodes() const { return getIntParam(CbcMaxNumNode); } /** Set the \link CbcModel::CbcMaxNumSol maximum number of solutions \endlink desired. */ inline bool setMaximumSolutions( int value) { return setIntParam(CbcMaxNumSol, value); } /** Get the \link CbcModel::CbcMaxNumSol maximum number of solutions \endlink desired. */ inline int getMaximumSolutions() const { return getIntParam(CbcMaxNumSol); } /// Set the printing mode inline bool setPrintingMode( int value) { return setIntParam(CbcPrinting, value); } /// Get the printing mode inline int getPrintingMode() const { return getIntParam(CbcPrinting); } /** Set the \link CbcModel::CbcMaximumSeconds maximum number of seconds \endlink desired. */ inline bool setMaximumSeconds( double value) { return setDblParam(CbcMaximumSeconds, value); } /** Get the \link CbcModel::CbcMaximumSeconds maximum number of seconds \endlink desired. */ inline double getMaximumSeconds() const { return getDblParam(CbcMaximumSeconds); } /// Current time since start of branchAndbound double getCurrentSeconds() const ; /// Return true if maximum time reached bool maximumSecondsReached() const ; /** Set the \link CbcModel::CbcIntegerTolerance integrality tolerance \endlink */ inline bool setIntegerTolerance( double value) { return setDblParam(CbcIntegerTolerance, value); } /** Get the \link CbcModel::CbcIntegerTolerance integrality tolerance \endlink */ inline double getIntegerTolerance() const { return getDblParam(CbcIntegerTolerance); } /** Set the \link CbcModel::CbcInfeasibilityWeight weight per integer infeasibility \endlink */ inline bool setInfeasibilityWeight( double value) { return setDblParam(CbcInfeasibilityWeight, value); } /** Get the \link CbcModel::CbcInfeasibilityWeight weight per integer infeasibility \endlink */ inline double getInfeasibilityWeight() const { return getDblParam(CbcInfeasibilityWeight); } /** Set the \link CbcModel::CbcAllowableGap allowable gap \endlink between the best known solution and the best possible solution. */ inline bool setAllowableGap( double value) { return setDblParam(CbcAllowableGap, value); } /** Get the \link CbcModel::CbcAllowableGap allowable gap \endlink between the best known solution and the best possible solution. */ inline double getAllowableGap() const { return getDblParam(CbcAllowableGap); } /** Set the \link CbcModel::CbcAllowableFractionGap fraction allowable gap \endlink between the best known solution and the best possible solution. */ inline bool setAllowableFractionGap( double value) { return setDblParam(CbcAllowableFractionGap, value); } /** Get the \link CbcModel::CbcAllowableFractionGap fraction allowable gap \endlink between the best known solution and the best possible solution. */ inline double getAllowableFractionGap() const { return getDblParam(CbcAllowableFractionGap); } /** Set the \link CbcModel::CbcAllowableFractionGap percentage allowable gap \endlink between the best known solution and the best possible solution. */ inline bool setAllowablePercentageGap( double value) { return setDblParam(CbcAllowableFractionGap, value*0.01); } /** Get the \link CbcModel::CbcAllowableFractionGap percentage allowable gap \endlink between the best known solution and the best possible solution. */ inline double getAllowablePercentageGap() const { return 100.0*getDblParam(CbcAllowableFractionGap); } /** Set the \link CbcModel::CbcHeuristicGap heuristic gap \endlink between the best known solution and the best possible solution. */ inline bool setHeuristicGap( double value) { return setDblParam(CbcHeuristicGap, value); } /** Get the \link CbcModel::CbcHeuristicGap heuristic gap \endlink between the best known solution and the best possible solution. */ inline double getHeuristicGap() const { return getDblParam(CbcHeuristicGap); } /** Set the \link CbcModel::CbcHeuristicFractionGap fraction heuristic gap \endlink between the best known solution and the best possible solution. */ inline bool setHeuristicFractionGap( double value) { return setDblParam(CbcHeuristicFractionGap, value); } /** Get the \link CbcModel::CbcHeuristicFractionGap fraction heuristic gap \endlink between the best known solution and the best possible solution. */ inline double getHeuristicFractionGap() const { return getDblParam(CbcHeuristicFractionGap); } /** Set the \link CbcModel::CbcCutoffIncrement \endlink desired. */ inline bool setCutoffIncrement( double value) { return setDblParam(CbcCutoffIncrement, value); } /** Get the \link CbcModel::CbcCutoffIncrement \endlink desired. */ inline double getCutoffIncrement() const { return getDblParam(CbcCutoffIncrement); } /// See if can stop on gap bool canStopOnGap() const; /** Pass in target solution and optional priorities. If priorities then >0 means only branch if incorrect while <0 means branch even if correct. +1 or -1 are highest priority */ void setHotstartSolution(const double * solution, const int * priorities = NULL) ; /// Set the minimum drop to continue cuts inline void setMinimumDrop(double value) { minimumDrop_ = value; } /// Get the minimum drop to continue cuts inline double getMinimumDrop() const { return minimumDrop_; } /** Set the maximum number of cut passes at root node (default 20) Minimum drop can also be used for fine tuning */ inline void setMaximumCutPassesAtRoot(int value) { maximumCutPassesAtRoot_ = value; } /** Get the maximum number of cut passes at root node */ inline int getMaximumCutPassesAtRoot() const { return maximumCutPassesAtRoot_; } /** Set the maximum number of cut passes at other nodes (default 10) Minimum drop can also be used for fine tuning */ inline void setMaximumCutPasses(int value) { maximumCutPasses_ = value; } /** Get the maximum number of cut passes at other nodes (default 10) */ inline int getMaximumCutPasses() const { return maximumCutPasses_; } /** Get current cut pass number in this round of cuts. (1 is first pass) */ inline int getCurrentPassNumber() const { return currentPassNumber_; } /** Set the maximum number of candidates to be evaluated for strong branching. A value of 0 disables strong branching. */ void setNumberStrong(int number); /** Get the maximum number of candidates to be evaluated for strong branching. */ inline int numberStrong() const { return numberStrong_; } /** Set global preferred way to branch -1 down, +1 up, 0 no preference */ inline void setPreferredWay(int value) { preferredWay_ = value; } /** Get the preferred way to branch (default 0) */ inline int getPreferredWay() const { return preferredWay_; } /// Get at which depths to do cuts inline int whenCuts() const { return whenCuts_; } /// Set at which depths to do cuts inline void setWhenCuts(int value) { whenCuts_ = value; } /** Return true if we want to do cuts If allowForTopOfTree zero then just does on multiples of depth if 1 then allows for doing at top of tree if 2 then says if cuts allowed anywhere apart from root */ bool doCutsNow(int allowForTopOfTree) const; /** Set the number of branches before pseudo costs believed in dynamic strong branching. A value of 0 disables dynamic strong branching. */ void setNumberBeforeTrust(int number); /** get the number of branches before pseudo costs believed in dynamic strong branching. */ inline int numberBeforeTrust() const { return numberBeforeTrust_; } /** Set the number of variables for which to compute penalties in dynamic strong branching. A value of 0 disables penalties. */ void setNumberPenalties(int number); /** get the number of variables for which to compute penalties in dynamic strong branching. */ inline int numberPenalties() const { return numberPenalties_; } /// Pointer to top of tree inline const CbcFullNodeInfo * topOfTree() const { return topOfTree_;} /// Number of analyze iterations to do inline void setNumberAnalyzeIterations(int number) { numberAnalyzeIterations_ = number; } inline int numberAnalyzeIterations() const { return numberAnalyzeIterations_; } /** Get scale factor to make penalties match strong. Should/will be computed */ inline double penaltyScaleFactor() const { return penaltyScaleFactor_; } /** Set scale factor to make penalties match strong. Should/will be computed */ void setPenaltyScaleFactor(double value); /** Problem type as set by user or found by analysis. This will be extended 0 - not known 1 - Set partitioning <= 2 - Set partitioning == 3 - Set covering 4 - all +- 1 or all +1 and odd */ void inline setProblemType(int number) { problemType_ = number; } inline int problemType() const { return problemType_; } /// Current depth inline int currentDepth() const { return currentDepth_; } /// Set how often to scan global cuts void setHowOftenGlobalScan(int number); /// Get how often to scan global cuts inline int howOftenGlobalScan() const { return howOftenGlobalScan_; } /// Original columns as created by integerPresolve or preprocessing inline int * originalColumns() const { return originalColumns_; } /// Set original columns as created by preprocessing void setOriginalColumns(const int * originalColumns, int numberGood=COIN_INT_MAX) ; /// Create conflict cut (well - most of) OsiRowCut * conflictCut(const OsiSolverInterface * solver, bool & localCuts); /** Set the print frequency. Controls the number of nodes evaluated between status prints. If number <=0 the print frequency is set to 100 nodes for large problems, 1000 for small problems. Print frequency has very slight overhead if small. */ inline void setPrintFrequency(int number) { printFrequency_ = number; } /// Get the print frequency inline int printFrequency() const { return printFrequency_; } //@} //--------------------------------------------------------------------------- ///@name Methods returning info on how the solution process terminated //@{ /// Are there a numerical difficulties? bool isAbandoned() const; /// Is optimality proven? bool isProvenOptimal() const; /// Is infeasiblity proven (or none better than cutoff)? bool isProvenInfeasible() const; /// Was continuous solution unbounded bool isContinuousUnbounded() const; /// Was continuous solution unbounded bool isProvenDualInfeasible() const; /// Node limit reached? bool isNodeLimitReached() const; /// Time limit reached? bool isSecondsLimitReached() const; /// Solution limit reached? bool isSolutionLimitReached() const; /// Get how many iterations it took to solve the problem. inline int getIterationCount() const { return numberIterations_; } /// Increment how many iterations it took to solve the problem. inline void incrementIterationCount(int value) { numberIterations_ += value; } /// Get how many Nodes it took to solve the problem (including those in complete fathoming B&B inside CLP). inline int getNodeCount() const { return numberNodes_; } /// Increment how many nodes it took to solve the problem. inline void incrementNodeCount(int value) { numberNodes_ += value; } /// Get how many Nodes were enumerated in complete fathoming B&B inside CLP inline int getExtraNodeCount() const { return numberExtraNodes_; } /** Final status of problem Some of these can be found out by is...... functions -1 before branchAndBound 0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found (or check value of best solution) 1 stopped - on maxnodes, maxsols, maxtime 2 difficulties so run was abandoned (5 event user programmed event occurred) */ inline int status() const { return status_; } inline void setProblemStatus(int value) { status_ = value; } /** Secondary status of problem -1 unset (status_ will also be -1) 0 search completed with solution 1 linear relaxation not feasible (or worse than cutoff) 2 stopped on gap 3 stopped on nodes 4 stopped on time 5 stopped on user event 6 stopped on solutions 7 linear relaxation unbounded 8 stopped on iteration limit */ inline int secondaryStatus() const { return secondaryStatus_; } inline void setSecondaryStatus(int value) { secondaryStatus_ = value; } /// Are there numerical difficulties (for initialSolve) ? bool isInitialSolveAbandoned() const ; /// Is optimality proven (for initialSolve) ? bool isInitialSolveProvenOptimal() const ; /// Is primal infeasiblity proven (for initialSolve) ? bool isInitialSolveProvenPrimalInfeasible() const ; /// Is dual infeasiblity proven (for initialSolve) ? bool isInitialSolveProvenDualInfeasible() const ; //@} //--------------------------------------------------------------------------- /**@name Problem information methods These methods call the solver's query routines to return information about the problem referred to by the current object. Querying a problem that has no data associated with it result in zeros for the number of rows and columns, and NULL pointers from the methods that return vectors. Const pointers returned from any data-query method are valid as long as the data is unchanged and the solver is not called. */ //@{ /// Number of rows in continuous (root) problem. inline int numberRowsAtContinuous() const { return numberRowsAtContinuous_; } /// Get number of columns inline int getNumCols() const { return solver_->getNumCols(); } /// Get number of rows inline int getNumRows() const { return solver_->getNumRows(); } /// Get number of nonzero elements inline CoinBigIndex getNumElements() const { return solver_->getNumElements(); } /// Number of integers in problem inline int numberIntegers() const { return numberIntegers_; } // Integer variables inline const int * integerVariable() const { return integerVariable_; } /// Whether or not integer inline char integerType(int i) const { assert (integerInfo_); assert (integerInfo_[i] == 0 || integerInfo_[i] == 1); return integerInfo_[i]; } /// Whether or not integer inline const char * integerType() const { return integerInfo_; } /// Get pointer to array[getNumCols()] of column lower bounds inline const double * getColLower() const { return solver_->getColLower(); } /// Get pointer to array[getNumCols()] of column upper bounds inline const double * getColUpper() const { return solver_->getColUpper(); } /** Get pointer to array[getNumRows()] of row constraint senses.
  • 'L': <= constraint
  • 'E': = constraint
  • 'G': >= constraint
  • 'R': ranged constraint
  • 'N': free constraint
*/ inline const char * getRowSense() const { return solver_->getRowSense(); } /** Get pointer to array[getNumRows()] of rows right-hand sides
  • if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i]
  • if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i]
  • if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i]
  • if rowsense()[i] == 'N' then rhs()[i] == 0.0
*/ inline const double * getRightHandSide() const { return solver_->getRightHandSide(); } /** Get pointer to array[getNumRows()] of row ranges.
  • if rowsense()[i] == 'R' then rowrange()[i] == rowupper()[i] - rowlower()[i]
  • if rowsense()[i] != 'R' then rowrange()[i] is 0.0
*/ inline const double * getRowRange() const { return solver_->getRowRange(); } /// Get pointer to array[getNumRows()] of row lower bounds inline const double * getRowLower() const { return solver_->getRowLower(); } /// Get pointer to array[getNumRows()] of row upper bounds inline const double * getRowUpper() const { return solver_->getRowUpper(); } /// Get pointer to array[getNumCols()] of objective function coefficients inline const double * getObjCoefficients() const { return solver_->getObjCoefficients(); } /// Get objective function sense (1 for min (default), -1 for max) inline double getObjSense() const { //assert (dblParam_[CbcOptimizationDirection]== solver_->getObjSense()); return dblParam_[CbcOptimizationDirection]; } /// Return true if variable is continuous inline bool isContinuous(int colIndex) const { return solver_->isContinuous(colIndex); } /// Return true if variable is binary inline bool isBinary(int colIndex) const { return solver_->isBinary(colIndex); } /** Return true if column is integer. Note: This function returns true if the the column is binary or a general integer. */ inline bool isInteger(int colIndex) const { return solver_->isInteger(colIndex); } /// Return true if variable is general integer inline bool isIntegerNonBinary(int colIndex) const { return solver_->isIntegerNonBinary(colIndex); } /// Return true if variable is binary and not fixed at either bound inline bool isFreeBinary(int colIndex) const { return solver_->isFreeBinary(colIndex) ; } /// Get pointer to row-wise copy of matrix inline const CoinPackedMatrix * getMatrixByRow() const { return solver_->getMatrixByRow(); } /// Get pointer to column-wise copy of matrix inline const CoinPackedMatrix * getMatrixByCol() const { return solver_->getMatrixByCol(); } /// Get solver's value for infinity inline double getInfinity() const { return solver_->getInfinity(); } /// Get pointer to array[getNumCols()] (for speed) of column lower bounds inline const double * getCbcColLower() const { return cbcColLower_; } /// Get pointer to array[getNumCols()] (for speed) of column upper bounds inline const double * getCbcColUpper() const { return cbcColUpper_; } /// Get pointer to array[getNumRows()] (for speed) of row lower bounds inline const double * getCbcRowLower() const { return cbcRowLower_; } /// Get pointer to array[getNumRows()] (for speed) of row upper bounds inline const double * getCbcRowUpper() const { return cbcRowUpper_; } /// Get pointer to array[getNumCols()] (for speed) of primal solution vector inline const double * getCbcColSolution() const { return cbcColSolution_; } /// Get pointer to array[getNumRows()] (for speed) of dual prices inline const double * getCbcRowPrice() const { return cbcRowPrice_; } /// Get a pointer to array[getNumCols()] (for speed) of reduced costs inline const double * getCbcReducedCost() const { return cbcReducedCost_; } /// Get pointer to array[getNumRows()] (for speed) of row activity levels. inline const double * getCbcRowActivity() const { return cbcRowActivity_; } //@} /**@name Methods related to querying the solution */ //@{ /// Holds solution at continuous (after cuts if branchAndBound called) inline double * continuousSolution() const { return continuousSolution_; } /** Array marked whenever a solution is found if non-zero. Code marks if heuristic returns better so heuristic need only mark if it wants to on solutions which are worse than current */ inline int * usedInSolution() const { return usedInSolution_; } /// Increases usedInSolution for nonzeros void incrementUsed(const double * solution); /// Record a new incumbent solution and update objectiveValue void setBestSolution(CBC_Message how, double & objectiveValue, const double *solution, int fixVariables = 0); /// Just update objectiveValue void setBestObjectiveValue( double objectiveValue); /// Deals with event handler and solution CbcEventHandler::CbcAction dealWithEventHandler(CbcEventHandler::CbcEvent event, double objValue, const double * solution); /** Call this to really test if a valid solution can be feasible Solution is number columns in size. If fixVariables true then bounds of continuous solver updated. Returns objective value (worse than cutoff if not feasible) Previously computed objective value is now passed in (in case user does not do solve) virtual so user can override */ virtual double checkSolution(double cutoff, double * solution, int fixVariables, double originalObjValue); /** Test the current solution for feasiblility. Scan all objects for indications of infeasibility. This is broken down into simple integer infeasibility (\p numberIntegerInfeasibilities) and all other reports of infeasibility (\p numberObjectInfeasibilities). */ bool feasibleSolution(int & numberIntegerInfeasibilities, int & numberObjectInfeasibilities) const; /** Solution to the most recent lp relaxation. The solver's solution to the most recent lp relaxation. */ inline double * currentSolution() const { return currentSolution_; } /** For testing infeasibilities - will point to currentSolution_ or solver-->getColSolution() */ inline const double * testSolution() const { return testSolution_; } inline void setTestSolution(const double * solution) { testSolution_ = solution; } /// Make sure region there and optionally copy solution void reserveCurrentSolution(const double * solution = NULL); /// Get pointer to array[getNumCols()] of primal solution vector inline const double * getColSolution() const { return solver_->getColSolution(); } /// Get pointer to array[getNumRows()] of dual prices inline const double * getRowPrice() const { return solver_->getRowPrice(); } /// Get a pointer to array[getNumCols()] of reduced costs inline const double * getReducedCost() const { return solver_->getReducedCost(); } /// Get pointer to array[getNumRows()] of row activity levels. inline const double * getRowActivity() const { return solver_->getRowActivity(); } /// Get current objective function value inline double getCurrentObjValue() const { return dblParam_[CbcCurrentObjectiveValue]; } /// Get current minimization objective function value inline double getCurrentMinimizationObjValue() const { return dblParam_[CbcCurrentMinimizationObjectiveValue]; } /// Get best objective function value as minimization inline double getMinimizationObjValue() const { return bestObjective_; } /// Set best objective function value as minimization inline void setMinimizationObjValue(double value) { bestObjective_ = value; } /// Get best objective function value inline double getObjValue() const { return bestObjective_ * solver_->getObjSense() ; } /** Get best possible objective function value. This is better of best possible left on tree and best solution found. If called from within branch and cut may be optimistic. */ double getBestPossibleObjValue() const; /// Set best objective function value inline void setObjValue(double value) { bestObjective_ = value * solver_->getObjSense() ; } /// Get solver objective function value (as minimization) inline double getSolverObjValue() const { return solver_->getObjValue() * solver_->getObjSense() ; } /** The best solution to the integer programming problem. The best solution to the integer programming problem found during the search. If no solution is found, the method returns null. */ inline double * bestSolution() const { return bestSolution_; } /** User callable setBestSolution. If check false does not check valid If true then sees if feasible and warns if objective value worse than given (so just set to COIN_DBL_MAX if you don't care). If check true then does not save solution if not feasible */ void setBestSolution(const double * solution, int numberColumns, double objectiveValue, bool check = false); /// Get number of solutions inline int getSolutionCount() const { return numberSolutions_; } /// Set number of solutions (so heuristics will be different) inline void setSolutionCount(int value) { numberSolutions_ = value; } /// Number of saved solutions (including best) int numberSavedSolutions() const; /// Maximum number of extra saved solutions inline int maximumSavedSolutions() const { return maximumSavedSolutions_; } /// Set maximum number of extra saved solutions void setMaximumSavedSolutions(int value); /// Return a saved solution (0==best) - NULL if off end const double * savedSolution(int which) const; /// Return a saved solution objective (0==best) - COIN_DBL_MAX if off end double savedSolutionObjective(int which) const; /// Delete a saved solution and move others up void deleteSavedSolution(int which); /** Current phase (so heuristics etc etc can find out). 0 - initial solve 1 - solve with cuts at root 2 - solve with cuts 3 - other e.g. strong branching 4 - trying to validate a solution 5 - at end of search */ inline int phase() const { return phase_; } /// Get number of heuristic solutions inline int getNumberHeuristicSolutions() const { return numberHeuristicSolutions_; } /// Set number of heuristic solutions inline void setNumberHeuristicSolutions(int value) { numberHeuristicSolutions_ = value; } /// Set objective function sense (1 for min (default), -1 for max,) inline void setObjSense(double s) { dblParam_[CbcOptimizationDirection] = s; solver_->setObjSense(s); } /// Value of objective at continuous inline double getContinuousObjective() const { return originalContinuousObjective_; } inline void setContinuousObjective(double value) { originalContinuousObjective_ = value; } /// Number of infeasibilities at continuous inline int getContinuousInfeasibilities() const { return continuousInfeasibilities_; } inline void setContinuousInfeasibilities(int value) { continuousInfeasibilities_ = value; } /// Value of objective after root node cuts added inline double rootObjectiveAfterCuts() const { return continuousObjective_; } /// Sum of Changes to objective by first solve inline double sumChangeObjective() const { return sumChangeObjective1_; } /** Number of times global cuts violated. When global cut pool then this should be kept for each cut and type of cut */ inline int numberGlobalViolations() const { return numberGlobalViolations_; } inline void clearNumberGlobalViolations() { numberGlobalViolations_ = 0; } /// Whether to force a resolve after takeOffCuts inline bool resolveAfterTakeOffCuts() const { return resolveAfterTakeOffCuts_; } inline void setResolveAfterTakeOffCuts(bool yesNo) { resolveAfterTakeOffCuts_ = yesNo; } /// Maximum number of rows inline int maximumRows() const { return maximumRows_; } /// Work basis for temporary use inline CoinWarmStartBasis & workingBasis() { return workingBasis_; } /// Get number of "iterations" to stop after inline int getStopNumberIterations() const { return stopNumberIterations_; } /// Set number of "iterations" to stop after inline void setStopNumberIterations(int value) { stopNumberIterations_ = value; } /// A pointer to model from CbcHeuristic inline CbcModel * heuristicModel() const { return heuristicModel_;} /// Set a pointer to model from CbcHeuristic inline void setHeuristicModel(CbcModel * model) { heuristicModel_ = model;} //@} /** \name Node selection */ //@{ // Comparison functions (which may be overridden by inheritance) inline CbcCompareBase * nodeComparison() const { return nodeCompare_; } void setNodeComparison(CbcCompareBase * compare); void setNodeComparison(CbcCompareBase & compare); //@} /** \name Problem feasibility checking */ //@{ // Feasibility functions (which may be overridden by inheritance) inline CbcFeasibilityBase * problemFeasibility() const { return problemFeasibility_; } void setProblemFeasibility(CbcFeasibilityBase * feasibility); void setProblemFeasibility(CbcFeasibilityBase & feasibility); //@} /** \name Tree methods and subtree methods */ //@{ /// Tree method e.g. heap (which may be overridden by inheritance) inline CbcTree * tree() const { return tree_; } /// For modifying tree handling (original is cloned) void passInTreeHandler(CbcTree & tree); /** For passing in an CbcModel to do a sub Tree (with derived tree handlers). Passed in model must exist for duration of branch and bound */ void passInSubTreeModel(CbcModel & model); /** For retrieving a copy of subtree model with given OsiSolver. If no subtree model will use self (up to user to reset cutoff etc). If solver NULL uses current */ CbcModel * subTreeModel(OsiSolverInterface * solver = NULL) const; /// Returns number of times any subtree stopped on nodes, time etc inline int numberStoppedSubTrees() const { return numberStoppedSubTrees_; } /// Says a sub tree was stopped inline void incrementSubTreeStopped() { numberStoppedSubTrees_++; } /** Whether to automatically do presolve before branch and bound (subTrees). 0 - no 1 - ordinary presolve 2 - integer presolve (dodgy) */ inline int typePresolve() const { return presolve_; } inline void setTypePresolve(int value) { presolve_ = value; } //@} /** \name Branching Decisions See the CbcBranchDecision class for additional information. */ //@{ /// Get the current branching decision method. inline CbcBranchDecision * branchingMethod() const { return branchingMethod_; } /// Set the branching decision method. inline void setBranchingMethod(CbcBranchDecision * method) { delete branchingMethod_; branchingMethod_ = method->clone(); } /** Set the branching method \overload */ inline void setBranchingMethod(CbcBranchDecision & method) { delete branchingMethod_; branchingMethod_ = method.clone(); } /// Get the current cut modifier method inline CbcCutModifier * cutModifier() const { return cutModifier_; } /// Set the cut modifier method void setCutModifier(CbcCutModifier * modifier); /** Set the cut modifier method \overload */ void setCutModifier(CbcCutModifier & modifier); //@} /** \name Row (constraint) and Column (variable) cut generation */ //@{ /** State of search 0 - no solution 1 - only heuristic solutions 2 - branched to a solution 3 - no solution but many nodes */ inline int stateOfSearch() const { return stateOfSearch_; } inline void setStateOfSearch(int state) { stateOfSearch_ = state; } /// Strategy worked out - mainly at root node for use by CbcNode inline int searchStrategy() const { return searchStrategy_; } /// Set strategy worked out - mainly at root node for use by CbcNode inline void setSearchStrategy(int value) { searchStrategy_ = value; } /// Stong branching strategy inline int strongStrategy() const { return strongStrategy_; } /// Set strong branching strategy inline void setStrongStrategy(int value) { strongStrategy_ = value; } /// Get the number of cut generators inline int numberCutGenerators() const { return numberCutGenerators_; } /// Get the list of cut generators inline CbcCutGenerator ** cutGenerators() const { return generator_; } ///Get the specified cut generator inline CbcCutGenerator * cutGenerator(int i) const { return generator_[i]; } ///Get the specified cut generator before any changes inline CbcCutGenerator * virginCutGenerator(int i) const { return virginGenerator_[i]; } /** Add one generator - up to user to delete generators. howoften affects how generator is used. 0 or 1 means always, >1 means every that number of nodes. Negative values have same meaning as positive but they may be switched off (-> -100) by code if not many cuts generated at continuous. -99 is just done at root. Name is just for printout. If depth >0 overrides how often generator is called (if howOften==-1 or >0). */ void addCutGenerator(CglCutGenerator * generator, int howOften = 1, const char * name = NULL, bool normal = true, bool atSolution = false, bool infeasible = false, int howOftenInSub = -100, int whatDepth = -1, int whatDepthInSub = -1); //@} /** \name Strategy and sub models See the CbcStrategy class for additional information. */ //@{ /// Get the current strategy inline CbcStrategy * strategy() const { return strategy_; } /// Set the strategy. Clones void setStrategy(CbcStrategy & strategy); /// Set the strategy. assigns inline void setStrategy(CbcStrategy * strategy) { strategy_ = strategy; } /// Get the current parent model inline CbcModel * parentModel() const { return parentModel_; } /// Set the parent model inline void setParentModel(CbcModel & parentModel) { parentModel_ = &parentModel; } //@} /** \name Heuristics and priorities */ //@{ /*! \brief Add one heuristic - up to user to delete The name is just used for print messages. */ void addHeuristic(CbcHeuristic * generator, const char *name = NULL, int before = -1); ///Get the specified heuristic inline CbcHeuristic * heuristic(int i) const { return heuristic_[i]; } /// Get the number of heuristics inline int numberHeuristics() const { return numberHeuristics_; } /// Set the number of heuristics inline void setNumberHeuristics(int value) { numberHeuristics_ = value; } /// Pointer to heuristic solver which found last solution (or NULL) inline CbcHeuristic * lastHeuristic() const { return lastHeuristic_; } /// set last heuristic which found a solution inline void setLastHeuristic(CbcHeuristic * last) { lastHeuristic_ = last; } /** Pass in branching priorities. If ifClique then priorities are on cliques otherwise priorities are on integer variables. Other type (if exists set to default) 1 is highest priority. (well actually -INT_MAX is but that's ugly) If hotstart > 0 then branches are created to force the variable to the value given by best solution. This enables a sort of hot start. The node choice should be greatest depth and hotstart should normally be switched off after a solution. If ifNotSimpleIntegers true then appended to normal integers This is now deprecated except for simple usage. If user creates Cbcobjects then set priority in them \internal Added for Kurt Spielberg. */ void passInPriorities(const int * priorities, bool ifNotSimpleIntegers); /// Returns priority level for an object (or 1000 if no priorities exist) inline int priority(int sequence) const { return object_[sequence]->priority(); } /*! \brief Set an event handler A clone of the handler passed as a parameter is stored in CbcModel. */ void passInEventHandler(const CbcEventHandler *eventHandler) ; /*! \brief Retrieve a pointer to the event handler */ inline CbcEventHandler* getEventHandler() const { return (eventHandler_) ; } //@} /**@name Setting/Accessing application data */ //@{ /** Set application data. This is a pointer that the application can store into and retrieve from the solver interface. This field is available for the application to optionally define and use. */ void setApplicationData (void * appData); /// Get application data void * getApplicationData() const; /** For advanced applications you may wish to modify the behavior of Cbc e.g. if the solver is a NLP solver then you may not have an exact optimum solution at each step. Information could be built into OsiSolverInterface but this is an alternative so that that interface does not have to be changed. If something similar is useful to enough solvers then it could be migrated You can also pass in by using solver->setAuxiliaryInfo. You should do that if solver is odd - if solver is normal simplex then use this. NOTE - characteristics are not cloned */ void passInSolverCharacteristics(OsiBabSolver * solverCharacteristics); /// Get solver characteristics inline const OsiBabSolver * solverCharacteristics() const { return solverCharacteristics_; } //@} //--------------------------------------------------------------------------- /**@name Message handling etc */ //@{ /// Pass in Message handler (not deleted at end) void passInMessageHandler(CoinMessageHandler * handler); /// Set language void newLanguage(CoinMessages::Language language); inline void setLanguage(CoinMessages::Language language) { newLanguage(language); } /// Return handler inline CoinMessageHandler * messageHandler() const { return handler_; } /// Return messages inline CoinMessages & messages() { return messages_; } /// Return pointer to messages inline CoinMessages * messagesPointer() { return &messages_; } /// Set log level void setLogLevel(int value); /// Get log level inline int logLevel() const { return handler_->logLevel(); } /** Set flag to say if handler_ is the default handler. The default handler is deleted when the model is deleted. Other handlers (supplied by the client) will not be deleted. */ inline void setDefaultHandler(bool yesNo) { defaultHandler_ = yesNo; } /// Check default handler inline bool defaultHandler() const { return defaultHandler_; } //@} //--------------------------------------------------------------------------- ///@name Specialized //@{ /** Set special options 0 bit (1) - check if cuts valid (if on debugger list) 1 bit (2) - use current basis to check integer solution (rather than all slack) 2 bit (4) - don't check integer solution (by solving LP) 3 bit (8) - fast analyze 4 bit (16) - non-linear model - so no well defined CoinPackedMatrix 5 bit (32) - keep names 6 bit (64) - try for dominated columns 7 bit (128) - SOS type 1 but all declared integer 8 bit (256) - Set to say solution just found, unset by doing cuts 9 bit (512) - Try reduced model after 100 nodes 10 bit (1024) - Switch on some heuristics even if seems unlikely 11 bit (2048) - Mark as in small branch and bound 12 bit (4096) - Funny cuts so do slow way (in some places) 13 bit (8192) - Funny cuts so do slow way (in other places) 14 bit (16384) - Use Cplex! for fathoming 15 bit (32768) - Try reduced model after 0 nodes 16 bit (65536) - Original model had integer bounds 17 bit (131072) - Perturbation switched off 18 bit (262144) - donor CbcModel 19 bit (524288) - recipient CbcModel 20 bit (1048576) - waiting for sub model to return 22 bit (4194304) - do not initialize random seed in solver (user has) 23 bit (8388608) - leave solver_ with cuts */ inline void setSpecialOptions(int value) { specialOptions_ = value; } /// Get special options inline int specialOptions() const { return specialOptions_; } /// Set random seed inline void setRandomSeed(int value) { randomSeed_ = value; } /// Get random seed inline int getRandomSeed() const { return randomSeed_; } /// Set multiple root tries inline void setMultipleRootTries(int value) { multipleRootTries_ = value; } /// Get multiple root tries inline int getMultipleRootTries() const { return multipleRootTries_; } /// Tell model to stop on event inline void sayEventHappened() { eventHappened_=true;} /// Says if normal solver i.e. has well defined CoinPackedMatrix inline bool normalSolver() const { return (specialOptions_&16) == 0; } /** Says if model is sitting there waiting for mini branch and bound to finish This is because an event handler may only have access to parent model in mini branch and bound */ inline bool waitingForMiniBranchAndBound() const { return (specialOptions_&1048576) != 0; } /** Set more special options at present bottom 6 bits used for shadow price mode 1024 for experimental hotstart 2048,4096 breaking out of cuts 8192 slowly increase minimum drop 16384 gomory 32768 more heuristics in sub trees 65536 no cuts in preprocessing 131072 Time limits elapsed 18 bit (262144) - Perturb fathom nodes 19 bit (524288) - No limit on fathom nodes 20 bit (1048576) - Reduce sum of infeasibilities before cuts 21 bit (2097152) - Reduce sum of infeasibilities after cuts 22 bit (4194304) - Conflict analysis 23 bit (8388608) - Conflict analysis - temporary bit 24 bit (16777216) - Add cutoff as LP constraint (out) 25 bit (33554432) - diving/reordering 26 bit (67108864) - load global cuts from file 27 bit (134217728) - append binding global cuts to file 28 bit (268435456) - idiot branching 29 bit (536870912) - don't make fake objective 30 bit (1073741824) - Funny SOS or similar - be careful */ inline void setMoreSpecialOptions(int value) { moreSpecialOptions_ = value; } /// Get more special options inline int moreSpecialOptions() const { return moreSpecialOptions_; } /// Set cutoff as constraint inline void setCutoffAsConstraint(bool yesNo) { cutoffRowNumber_ = (yesNo) ? -2 : -1; } /// Set time method inline void setUseElapsedTime(bool yesNo) { if (yesNo) moreSpecialOptions_ |= 131072; else moreSpecialOptions_ &= ~131072; } /// Get time method inline bool useElapsedTime() const { return (moreSpecialOptions_&131072)!=0; } /// Get useful temporary pointer inline void * temporaryPointer() const { return temporaryPointer_;} /// Set useful temporary pointer inline void setTemporaryPointer(void * pointer) { temporaryPointer_=pointer;} /// Go to dantzig pivot selection if easy problem (clp only) void goToDantzig(int numberNodes, ClpDualRowPivot *& savePivotMethod); /// Now we may not own objects - just point to solver's objects inline bool ownObjects() const { return ownObjects_; } /// Check original model before it gets messed up void checkModel(); //@} //--------------------------------------------------------------------------- ///@name Constructors and destructors etc //@{ /// Default Constructor CbcModel(); /// Constructor from solver CbcModel(const OsiSolverInterface &); /** Assign a solver to the model (model assumes ownership) On return, \p solver will be NULL. If deleteSolver then current solver deleted (if model owned) \note Parameter settings in the outgoing solver are not inherited by the incoming solver. */ void assignSolver(OsiSolverInterface *&solver, bool deleteSolver = true); /** \brief Set ownership of solver A parameter of false tells CbcModel it does not own the solver and should not delete it. Once you claim ownership of the solver, you're responsible for eventually deleting it. Note that CbcModel clones solvers with abandon. Unless you have a deep understanding of the workings of CbcModel, the only time you want to claim ownership is when you're about to delete the CbcModel object but want the solver to continue to exist (as, for example, when branchAndBound has finished and you want to hang on to the answer). */ inline void setModelOwnsSolver (bool ourSolver) { ownership_ = ourSolver ? (ownership_ | 0x80000000) : (ownership_ & (~0x80000000)) ; } /*! \brief Get ownership of solver A return value of true means that CbcModel owns the solver and will take responsibility for deleting it when that becomes necessary. */ inline bool modelOwnsSolver () { return ((ownership_&0x80000000) != 0) ; } /** Copy constructor . If cloneHandler is true then message handler is cloned */ CbcModel(const CbcModel & rhs, bool cloneHandler = false); /** Clone */ virtual CbcModel *clone (bool cloneHandler); /// Assignment operator CbcModel & operator=(const CbcModel& rhs); /// Destructor virtual ~CbcModel (); /// Returns solver - has current state inline OsiSolverInterface * solver() const { return solver_; } /// Returns current solver - sets new one inline OsiSolverInterface * swapSolver(OsiSolverInterface * solver) { OsiSolverInterface * returnSolver = solver_; solver_ = solver; return returnSolver; } /// Returns solver with continuous state inline OsiSolverInterface * continuousSolver() const { return continuousSolver_; } /// Create solver with continuous state inline void createContinuousSolver() { continuousSolver_ = solver_->clone(); } /// Clear solver with continuous state inline void clearContinuousSolver() { delete continuousSolver_; continuousSolver_ = NULL; } /// A copy of the solver, taken at constructor or by saveReferenceSolver inline OsiSolverInterface * referenceSolver() const { return referenceSolver_; } /// Save a copy of the current solver so can be reset to void saveReferenceSolver(); /** Uses a copy of reference solver to be current solver. Because of possible mismatches all exotic integer information is loat (apart from normal information in OsiSolverInterface) so SOS etc and priorities will have to be redone */ void resetToReferenceSolver(); /// Clears out as much as possible (except solver) void gutsOfDestructor(); /** Clears out enough to reset CbcModel as if no branch and bound done */ void gutsOfDestructor2(); /** Clears out enough to reset CbcModel cutoff etc */ void resetModel(); /** Most of copy constructor mode - 0 copy but don't delete before 1 copy and delete before 2 copy and delete before (but use virgin generators) */ void gutsOfCopy(const CbcModel & rhs, int mode = 0); /// Move status, nodes etc etc across void moveInfo(const CbcModel & rhs); //@} ///@name Multithreading //@{ /// Indicates whether Cbc library has been compiled with multithreading support static bool haveMultiThreadSupport(); /// Get pointer to masterthread CbcThread * masterThread() const { return masterThread_; } /// Get pointer to walkback CbcNodeInfo ** walkback() const { return walkback_; } /// Get number of threads inline int getNumberThreads() const { return numberThreads_; } /// Set number of threads inline void setNumberThreads(int value) { numberThreads_ = value; } /// Get thread mode inline int getThreadMode() const { return threadMode_; } /** Set thread mode always use numberThreads for branching 1 set then deterministic 2 set then use numberThreads for root cuts 4 set then use numberThreads in root mini branch and bound 8 set and numberThreads - do heuristics numberThreads at a time 8 set and numberThreads==0 do all heuristics at once default is 0 */ inline void setThreadMode(int value) { threadMode_ = value; } /** Return -2 if deterministic threaded and main thread -1 if deterministic threaded and serial thread 0 if serial 1 if opportunistic threaded */ inline int parallelMode() const { if (!numberThreads_) { if ((threadMode_&1) == 0) return 0; else return -1; return 0; } else { if ((threadMode_&1) == 0) return 1; else return -2; } } /// Thread stuff for master inline CbcBaseModel * master() const { return master_;} /// From here to end of section - code in CbcThread.cpp until class changed /// Returns true if locked bool isLocked() const; #ifdef CBC_THREAD /** Locks a thread if parallel so that stuff like cut pool can be updated and/or used. */ void lockThread(); /** Unlocks a thread if parallel to say cut pool stuff not needed */ void unlockThread(); #else inline void lockThread() {} inline void unlockThread() {} #endif /** Set information in a child -3 pass pointer to child thread info -2 just stop -1 delete simple child stuff 0 delete opportunistic child stuff 1 delete deterministic child stuff */ void setInfoInChild(int type, CbcThread * info); /** Move/copy information from one model to another -1 - initialization 0 - from base model 1 - to base model (and reset) 2 - add in final statistics etc (and reset so can do clean destruction) */ void moveToModel(CbcModel * baseModel, int mode); /// Split up nodes int splitModel(int numberModels, CbcModel ** model, int numberNodes); /// Start threads void startSplitModel(int numberIterations); /// Merge models void mergeModels(int numberModel, CbcModel ** model, int numberNodes); //@} ///@name semi-private i.e. users should not use //@{ /// Get how many Nodes it took to solve the problem. int getNodeCount2() const { return numberNodes2_; } /// Set pointers for speed void setPointers(const OsiSolverInterface * solver); /** Perform reduced cost fixing Fixes integer variables at their current value based on reduced cost penalties. Returns number fixed */ int reducedCostFix() ; /** Makes all handlers same. If makeDefault 1 then makes top level default and rest point to that. If 2 then each is copy */ void synchronizeHandlers(int makeDefault); /// Save a solution to saved list void saveExtraSolution(const double * solution, double objectiveValue); /// Save a solution to best and move current to saved void saveBestSolution(const double * solution, double objectiveValue); /// Delete best and saved solutions void deleteSolutions(); /// Encapsulates solver resolve int resolve(OsiSolverInterface * solver); #ifdef CLP_RESOLVE /// Special purpose resolve int resolveClp(OsiClpSolverInterface * solver, int type); #endif /** Encapsulates choosing a variable - anyAction -2, infeasible (-1 round again), 0 done */ int chooseBranch(CbcNode * & newNode, int numberPassesLeft, CbcNode * oldNode, OsiCuts & cuts, bool & resolved, CoinWarmStartBasis *lastws, const double * lowerBefore, const double * upperBefore, OsiSolverBranch * & branches); int chooseBranch(CbcNode * newNode, int numberPassesLeft, bool & resolved); /** Return an empty basis object of the specified size A useful utility when constructing a basis for a subproblem from scratch. The object returned will be of the requested capacity and appropriate for the solver attached to the model. */ CoinWarmStartBasis *getEmptyBasis(int ns = 0, int na = 0) const ; /** Remove inactive cuts from the model An OsiSolverInterface is expected to maintain a valid basis, but not a valid solution, when loose cuts are deleted. Restoring a valid solution requires calling the solver to reoptimise. If it's certain the solution will not be required, set allowResolve to false to suppress reoptimisation. If saveCuts then slack cuts will be saved On input current cuts are cuts and newCuts on exit current cuts will be correct. Returns number dropped */ int takeOffCuts(OsiCuts &cuts, bool allowResolve, OsiCuts * saveCuts, int numberNewCuts = 0, const OsiRowCut ** newCuts = NULL) ; /** Determine and install the active cuts that need to be added for the current subproblem The whole truth is a bit more complicated. The first action is a call to addCuts1(). addCuts() then sorts through the list, installs the tight cuts in the model, and does bookkeeping (adjusts reference counts). The basis returned from addCuts1() is adjusted accordingly. If it turns out that the node should really be fathomed by bound, addCuts() simply treats all the cuts as loose as it does the bookkeeping. canFix true if extra information being passed */ int addCuts(CbcNode * node, CoinWarmStartBasis *&lastws, bool canFix); /** Traverse the tree from node to root and prep the model addCuts1() begins the job of prepping the model to match the current subproblem. The model is stripped of all cuts, and the search tree is traversed from node to root to determine the changes required. Appropriate bounds changes are installed, a list of cuts is collected but not installed, and an appropriate basis (minus the cuts, but big enough to accommodate them) is constructed. Returns true if new problem similar to old \todo addCuts1() is called in contexts where it's known in advance that all that's desired is to determine a list of cuts and do the bookkeeping (adjust the reference counts). The work of installing bounds and building a basis goes to waste. */ bool addCuts1(CbcNode * node, CoinWarmStartBasis *&lastws); /** Returns bounds just before where - initially original bounds. Also sets downstream nodes (lower if force 1, upper if 2) */ void previousBounds (CbcNode * node, CbcNodeInfo * where, int iColumn, double & lower, double & upper, int force); /** Set objective value in a node. This is separated out so that odd solvers can use. It may look at extra information in solverCharacteriscs_ and will also use bound from parent node */ void setObjectiveValue(CbcNode * thisNode, const CbcNode * parentNode) const; /** If numberBeforeTrust >0 then we are going to use CbcBranchDynamic. Scan and convert CbcSimpleInteger objects */ void convertToDynamic(); /// Set numberBeforeTrust in all objects void synchronizeNumberBeforeTrust(int type = 0); /// Zap integer information in problem (may leave object info) void zapIntegerInformation(bool leaveObjects = true); /// Use cliques for pseudocost information - return nonzero if infeasible int cliquePseudoCosts(int doStatistics); /// Fill in useful estimates void pseudoShadow(int type); /** Return pseudo costs If not all integers or not pseudo costs - returns all zero Length of arrays are numberIntegers() and entries correspond to integerVariable()[i] User must allocate arrays before call */ void fillPseudoCosts(double * downCosts, double * upCosts, int * priority = NULL, int * numberDown = NULL, int * numberUp = NULL, int * numberDownInfeasible = NULL, int * numberUpInfeasible = NULL) const; /** Do heuristics at root. 0 - don't delete 1 - delete 2 - just delete - don't even use */ void doHeuristicsAtRoot(int deleteHeuristicsAfterwards = 0); /// Adjust heuristics based on model void adjustHeuristics(); /// Get the hotstart solution inline const double * hotstartSolution() const { return hotstartSolution_; } /// Get the hotstart priorities inline const int * hotstartPriorities() const { return hotstartPriorities_; } /// Return the list of cuts initially collected for this subproblem inline CbcCountRowCut ** addedCuts() const { return addedCuts_; } /// Number of entries in the list returned by #addedCuts() inline int currentNumberCuts() const { return currentNumberCuts_; } /// Global cuts inline CbcRowCuts * globalCuts() { return &globalCuts_; } /// Copy and set a pointer to a row cut which will be added instead of normal branching. void setNextRowCut(const OsiRowCut & cut); /// Get a pointer to current node (be careful) inline CbcNode * currentNode() const { return currentNode_; } /// Get a pointer to probing info inline CglTreeProbingInfo * probingInfo() const { return probingInfo_; } /// Thread specific random number generator inline CoinThreadRandom * randomNumberGenerator() { return &randomNumberGenerator_; } /// Set the number of iterations done in strong branching. inline void setNumberStrongIterations(int number) { numberStrongIterations_ = number; } /// Get the number of iterations done in strong branching. inline int numberStrongIterations() const { return numberStrongIterations_; } /// Get maximum number of iterations (designed to be used in heuristics) inline int maximumNumberIterations() const { return maximumNumberIterations_; } /// Set maximum number of iterations (designed to be used in heuristics) inline void setMaximumNumberIterations(int value) { maximumNumberIterations_ = value; } /// Set depth for fast nodes inline void setFastNodeDepth(int value) { fastNodeDepth_ = value; } /// Get depth for fast nodes inline int fastNodeDepth() const { return fastNodeDepth_; } /// Get anything with priority >= this can be treated as continuous inline int continuousPriority() const { return continuousPriority_; } /// Set anything with priority >= this can be treated as continuous inline void setContinuousPriority(int value) { continuousPriority_ = value; } inline void incrementExtra(int nodes, int iterations) { numberExtraNodes_ += nodes; numberExtraIterations_ += iterations; } /// Number of extra iterations inline int numberExtraIterations() const { return numberExtraIterations_; } /// Increment strong info void incrementStrongInfo(int numberTimes, int numberIterations, int numberFixed, bool ifInfeasible); /// Return strong info inline const int * strongInfo() const { return strongInfo_; } /// Return mutable strong info inline int * mutableStrongInfo() { return strongInfo_; } /// Get stored row cuts for donor/recipient CbcModel CglStored * storedRowCuts() const { return storedRowCuts_; } /// Set stored row cuts for donor/recipient CbcModel void setStoredRowCuts(CglStored * cuts) { storedRowCuts_ = cuts; } /// Says whether all dynamic integers inline bool allDynamic () const { return ((ownership_&0x40000000) != 0) ; } /// Create C++ lines to get to current state void generateCpp( FILE * fp, int options); /// Generate an OsiBranchingInformation object OsiBranchingInformation usefulInformation() const; /** Warm start object produced by heuristic or strong branching If get a valid integer solution outside branch and bound then it can take a reasonable time to solve LP which produces clean solution. If this object has any size then it will be used in solve. */ inline void setBestSolutionBasis(const CoinWarmStartBasis & bestSolutionBasis) { bestSolutionBasis_ = bestSolutionBasis; } /// Redo walkback arrays void redoWalkBack(); //@} //--------------------------------------------------------------------------- private: ///@name Private member data //@{ /// The solver associated with this model. OsiSolverInterface * solver_; /** Ownership of objects and other stuff 0x80000000 model owns solver 0x40000000 all variables CbcDynamicPseudoCost */ unsigned int ownership_ ; /// A copy of the solver, taken at the continuous (root) node. OsiSolverInterface * continuousSolver_; /// A copy of the solver, taken at constructor or by saveReferenceSolver OsiSolverInterface * referenceSolver_; /// Message handler CoinMessageHandler * handler_; /** Flag to say if handler_ is the default handler. The default handler is deleted when the model is deleted. Other handlers (supplied by the client) will not be deleted. */ bool defaultHandler_; /// Cbc messages CoinMessages messages_; /// Array for integer parameters int intParam_[CbcLastIntParam]; /// Array for double parameters double dblParam_[CbcLastDblParam]; /** Pointer to an empty warm start object It turns out to be useful to have this available as a base from which to build custom warm start objects. This is typed as CoinWarmStart rather than CoinWarmStartBasis to allow for the possibility that a client might want to apply a solver that doesn't use a basis-based warm start. See getEmptyBasis for an example of how this field can be used. */ mutable CoinWarmStart *emptyWarmStart_ ; /// Best objective double bestObjective_; /// Best possible objective double bestPossibleObjective_; /// Sum of Changes to objective by first solve double sumChangeObjective1_; /// Sum of Changes to objective by subsequent solves double sumChangeObjective2_; /// Array holding the incumbent (best) solution. double * bestSolution_; /// Arrays holding other solutions. double ** savedSolutions_; /** Array holding the current solution. This array is used more as a temporary. */ double * currentSolution_; /** For testing infeasibilities - will point to currentSolution_ or solver-->getColSolution() */ mutable const double * testSolution_; /** Warm start object produced by heuristic or strong branching If get a valid integer solution outside branch and bound then it can take a reasonable time to solve LP which produces clean solution. If this object has any size then it will be used in solve. */ CoinWarmStartBasis bestSolutionBasis_ ; /// Global cuts CbcRowCuts globalCuts_; /// Global conflict cuts CbcRowCuts * globalConflictCuts_; /// Minimum degradation in objective value to continue cut generation double minimumDrop_; /// Number of solutions int numberSolutions_; /// Number of saved solutions int numberSavedSolutions_; /// Maximum number of saved solutions int maximumSavedSolutions_; /** State of search 0 - no solution 1 - only heuristic solutions 2 - branched to a solution 3 - no solution but many nodes */ int stateOfSearch_; /// At which depths to do cuts int whenCuts_; /// Hotstart solution double * hotstartSolution_; /// Hotstart priorities int * hotstartPriorities_; /// Number of heuristic solutions int numberHeuristicSolutions_; /// Cumulative number of nodes int numberNodes_; /** Cumulative number of nodes for statistics. Must fix to match up */ int numberNodes2_; /// Cumulative number of iterations int numberIterations_; /// Cumulative number of solves int numberSolves_; /// Status of problem - 0 finished, 1 stopped, 2 difficulties int status_; /** Secondary status of problem -1 unset (status_ will also be -1) 0 search completed with solution 1 linear relaxation not feasible (or worse than cutoff) 2 stopped on gap 3 stopped on nodes 4 stopped on time 5 stopped on user event 6 stopped on solutions */ int secondaryStatus_; /// Number of integers in problem int numberIntegers_; /// Number of rows at continuous int numberRowsAtContinuous_; /** -1 - cutoff as constraint not activated -2 - waiting to activate >=0 - activated */ int cutoffRowNumber_; /// Maximum number of cuts int maximumNumberCuts_; /** Current phase (so heuristics etc etc can find out). 0 - initial solve 1 - solve with cuts at root 2 - solve with cuts 3 - other e.g. strong branching 4 - trying to validate a solution 5 - at end of search */ int phase_; /// Number of entries in #addedCuts_ int currentNumberCuts_; /** Current limit on search tree depth The allocated size of #walkback_. Increased as needed. */ int maximumDepth_; /** Array used to assemble the path between a node and the search tree root The array is resized when necessary. #maximumDepth_ is the current allocated size. */ CbcNodeInfo ** walkback_; CbcNodeInfo ** lastNodeInfo_; const OsiRowCut ** lastCut_; int lastDepth_; int lastNumberCuts2_; int maximumCuts_; int * lastNumberCuts_; /** The list of cuts initially collected for this subproblem When the subproblem at this node is rebuilt, a set of cuts is collected for inclusion in the constraint system. If any of these cuts are subsequently removed because they have become loose, the corresponding entry is set to NULL. */ CbcCountRowCut ** addedCuts_; /** A pointer to a row cut which will be added instead of normal branching. After use it should be set to NULL. */ OsiRowCut * nextRowCut_; /// Current node so can be used elsewhere CbcNode * currentNode_; /// Indices of integer variables int * integerVariable_; /// Whether of not integer char * integerInfo_; /// Holds solution at continuous (after cuts) double * continuousSolution_; /// Array marked whenever a solution is found if non-zero int * usedInSolution_; /** Special options 0 bit (1) - check if cuts valid (if on debugger list) 1 bit (2) - use current basis to check integer solution (rather than all slack) 2 bit (4) - don't check integer solution (by solving LP) 3 bit (8) - fast analyze 4 bit (16) - non-linear model - so no well defined CoinPackedMatrix 5 bit (32) - keep names 6 bit (64) - try for dominated columns 7 bit (128) - SOS type 1 but all declared integer 8 bit (256) - Set to say solution just found, unset by doing cuts 9 bit (512) - Try reduced model after 100 nodes 10 bit (1024) - Switch on some heuristics even if seems unlikely 11 bit (2048) - Mark as in small branch and bound 12 bit (4096) - Funny cuts so do slow way (in some places) 13 bit (8192) - Funny cuts so do slow way (in other places) 14 bit (16384) - Use Cplex! for fathoming 15 bit (32768) - Try reduced model after 0 nodes 16 bit (65536) - Original model had integer bounds 17 bit (131072) - Perturbation switched off 18 bit (262144) - donor CbcModel 19 bit (524288) - recipient CbcModel */ int specialOptions_; /** More special options at present bottom 6 bits used for shadow price mode 1024 for experimental hotstart 2048,4096 breaking out of cuts 8192 slowly increase minimum drop 16384 gomory 32768 more heuristics in sub trees 65536 no cuts in preprocessing 131072 Time limits elapsed 18 bit (262144) - Perturb fathom nodes 19 bit (524288) - No limit on fathom nodes 20 bit (1048576) - Reduce sum of infeasibilities before cuts 21 bit (2097152) - Reduce sum of infeasibilities after cuts */ int moreSpecialOptions_; /// User node comparison function CbcCompareBase * nodeCompare_; /// User feasibility function (see CbcFeasibleBase.hpp) CbcFeasibilityBase * problemFeasibility_; /// Tree CbcTree * tree_; /// Pointer to top of tree CbcFullNodeInfo * topOfTree_; /// A pointer to model to be used for subtrees CbcModel * subTreeModel_; /// A pointer to model from CbcHeuristic CbcModel * heuristicModel_; /// Number of times any subtree stopped on nodes, time etc int numberStoppedSubTrees_; /// Variable selection function CbcBranchDecision * branchingMethod_; /// Cut modifier function CbcCutModifier * cutModifier_; /// Strategy CbcStrategy * strategy_; /// Parent model CbcModel * parentModel_; /** Whether to automatically do presolve before branch and bound. 0 - no 1 - ordinary presolve 2 - integer presolve (dodgy) */ /// Pointer to array[getNumCols()] (for speed) of column lower bounds const double * cbcColLower_; /// Pointer to array[getNumCols()] (for speed) of column upper bounds const double * cbcColUpper_; /// Pointer to array[getNumRows()] (for speed) of row lower bounds const double * cbcRowLower_; /// Pointer to array[getNumRows()] (for speed) of row upper bounds const double * cbcRowUpper_; /// Pointer to array[getNumCols()] (for speed) of primal solution vector const double * cbcColSolution_; /// Pointer to array[getNumRows()] (for speed) of dual prices const double * cbcRowPrice_; /// Get a pointer to array[getNumCols()] (for speed) of reduced costs const double * cbcReducedCost_; /// Pointer to array[getNumRows()] (for speed) of row activity levels. const double * cbcRowActivity_; /// Pointer to user-defined data structure void * appData_; /// Presolve for CbcTreeLocal int presolve_; /** Maximum number of candidates to consider for strong branching. To disable strong branching, set this to 0. */ int numberStrong_; /** \brief The number of branches before pseudo costs believed in dynamic strong branching. A value of 0 is off. */ int numberBeforeTrust_; /** \brief The number of variables for which to compute penalties in dynamic strong branching. */ int numberPenalties_; /// For threads - stop after this many "iterations" int stopNumberIterations_; /** Scale factor to make penalties match strong. Should/will be computed */ double penaltyScaleFactor_; /// Number of analyze iterations to do int numberAnalyzeIterations_; /// Arrays with analysis results double * analyzeResults_; /// Useful temporary pointer void * temporaryPointer_; /// Number of nodes infeasible by normal branching (before cuts) int numberInfeasibleNodes_; /** Problem type as set by user or found by analysis. This will be extended 0 - not known 1 - Set partitioning <= 2 - Set partitioning == 3 - Set covering */ int problemType_; /// Print frequency int printFrequency_; /// Number of cut generators int numberCutGenerators_; // Cut generators CbcCutGenerator ** generator_; // Cut generators before any changes CbcCutGenerator ** virginGenerator_; /// Number of heuristics int numberHeuristics_; /// Heuristic solvers CbcHeuristic ** heuristic_; /// Pointer to heuristic solver which found last solution (or NULL) CbcHeuristic * lastHeuristic_; /// Depth for fast nodes int fastNodeDepth_; /*! Pointer to the event handler */ # ifdef CBC_ONLY_CLP ClpEventHandler *eventHandler_ ; # else CbcEventHandler *eventHandler_ ; # endif /// Total number of objects int numberObjects_; /** \brief Integer and Clique and ... information \note The code assumes that the first objects on the list will be SimpleInteger objects for each integer variable, followed by Clique objects. Portions of the code that understand Clique objects will fail if they do not immediately follow the SimpleIntegers. Large chunks of the code will fail if the first objects are not SimpleInteger. As of 2003.08, SimpleIntegers and Cliques are the only objects. */ OsiObject ** object_; /// Now we may not own objects - just point to solver's objects bool ownObjects_; /// Original columns as created by integerPresolve or preprocessing int * originalColumns_; /// How often to scan global cuts int howOftenGlobalScan_; /** Number of times global cuts violated. When global cut pool then this should be kept for each cut and type of cut */ int numberGlobalViolations_; /// Number of extra iterations in fast lp int numberExtraIterations_; /// Number of extra nodes in fast lp int numberExtraNodes_; /** Value of objective at continuous (Well actually after initial round of cuts) */ double continuousObjective_; /** Value of objective before root node cuts added */ double originalContinuousObjective_; /// Number of infeasibilities at continuous int continuousInfeasibilities_; /// Maximum number of cut passes at root int maximumCutPassesAtRoot_; /// Maximum number of cut passes int maximumCutPasses_; /// Preferred way of branching int preferredWay_; /// Current cut pass number int currentPassNumber_; /// Maximum number of cuts (for whichGenerator_) int maximumWhich_; /// Maximum number of rows int maximumRows_; /// Random seed int randomSeed_; /// Multiple root tries int multipleRootTries_; /// Current depth int currentDepth_; /// Thread specific random number generator mutable CoinThreadRandom randomNumberGenerator_; /// Work basis for temporary use CoinWarmStartBasis workingBasis_; /// Which cut generator generated this cut int * whichGenerator_; /// Maximum number of statistics int maximumStatistics_; /// statistics CbcStatistics ** statistics_; /// Maximum depth reached int maximumDepthActual_; /// Number of reduced cost fixings double numberDJFixed_; /// Probing info CglTreeProbingInfo * probingInfo_; /// Number of fixed by analyze at root int numberFixedAtRoot_; /// Number fixed by analyze so far int numberFixedNow_; /// Whether stopping on gap bool stoppedOnGap_; /// Whether event happened mutable bool eventHappened_; /// Number of long strong goes int numberLongStrong_; /// Number of old active cuts int numberOldActiveCuts_; /// Number of new cuts int numberNewCuts_; /// Strategy worked out - mainly at root node int searchStrategy_; /** Strategy for strong branching 0 - normal when to do all fractional 1 - root node 2 - depth less than modifier 4 - if objective == best possible 6 - as 2+4 when to do all including satisfied 10 - root node etc. If >=100 then do when depth <= strategy/100 (otherwise 5) */ int strongStrategy_; /// Number of iterations in strong branching int numberStrongIterations_; /** 0 - number times strong branching done, 1 - number fixed, 2 - number infeasible Second group of three is a snapshot at node [6] */ int strongInfo_[7]; /** For advanced applications you may wish to modify the behavior of Cbc e.g. if the solver is a NLP solver then you may not have an exact optimum solution at each step. This gives characteristics - just for one BAB. For actually saving/restoring a solution you need the actual solver one. */ OsiBabSolver * solverCharacteristics_; /// Whether to force a resolve after takeOffCuts bool resolveAfterTakeOffCuts_; /// Maximum number of iterations (designed to be used in heuristics) int maximumNumberIterations_; /// Anything with priority >= this can be treated as continuous int continuousPriority_; /// Number of outstanding update information items int numberUpdateItems_; /// Maximum number of outstanding update information items int maximumNumberUpdateItems_; /// Update items CbcObjectUpdateData * updateItems_; /// Stored row cuts for donor/recipient CbcModel CglStored * storedRowCuts_; /** Parallel 0 - off 1 - testing 2-99 threads other special meanings */ int numberThreads_; /** thread mode always use numberThreads for branching 1 set then deterministic 2 set then use numberThreads for root cuts 4 set then use numberThreads in root mini branch and bound default is 0 */ int threadMode_; /// Thread stuff for master CbcBaseModel * master_; /// Pointer to masterthread CbcThread * masterThread_; //@} }; /// So we can use osiObject or CbcObject during transition void getIntegerInformation(const OsiObject * object, double & originalLower, double & originalUpper) ; // So we can call from other programs // Real main program class OsiClpSolverInterface; int CbcMain (int argc, const char *argv[], OsiClpSolverInterface & solver, CbcModel ** babSolver); int CbcMain (int argc, const char *argv[], CbcModel & babSolver); // four ways of calling int callCbc(const char * input2, OsiClpSolverInterface& solver1); int callCbc(const char * input2); int callCbc(const std::string input2, OsiClpSolverInterface& solver1); int callCbc(const std::string input2) ; // When we want to load up CbcModel with options first void CbcMain0 (CbcModel & babSolver); int CbcMain1 (int argc, const char *argv[], CbcModel & babSolver); // two ways of calling int callCbc(const char * input2, CbcModel & babSolver); int callCbc(const std::string input2, CbcModel & babSolver); // And when CbcMain0 already called to initialize int callCbc1(const char * input2, CbcModel & babSolver); int callCbc1(const std::string input2, CbcModel & babSolver); // And when CbcMain0 already called to initialize (with call back) (see CbcMain1 for whereFrom) int callCbc1(const char * input2, CbcModel & babSolver, int (CbcModel * currentSolver, int whereFrom)); int callCbc1(const std::string input2, CbcModel & babSolver, int (CbcModel * currentSolver, int whereFrom)); int CbcMain1 (int argc, const char *argv[], CbcModel & babSolver, int (CbcModel * currentSolver, int whereFrom)); // For uniform setting of cut and heuristic options void setCutAndHeuristicOptions(CbcModel & model); #endif Cbc-2.8.12/src/CbcHeuristicDiveGuided.hpp0000644000076600007660000000320412131315050016540 0ustar coincoin/* $Id: CbcHeuristicDiveGuided.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicDiveGuided_H #define CbcHeuristicDiveGuided_H #include "CbcHeuristicDive.hpp" /** DiveGuided class */ class CbcHeuristicDiveGuided : public CbcHeuristicDive { public: // Default Constructor CbcHeuristicDiveGuided (); // Constructor with model - assumed before cuts CbcHeuristicDiveGuided (CbcModel & model); // Copy constructor CbcHeuristicDiveGuided ( const CbcHeuristicDiveGuided &); // Destructor ~CbcHeuristicDiveGuided (); /// Clone virtual CbcHeuristicDiveGuided * clone() const; /// Assignment operator CbcHeuristicDiveGuided & operator=(const CbcHeuristicDiveGuided& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Tests if the heuristic can run virtual bool canHeuristicRun(); /// Selects the next variable to branch on /** Returns true if all the fractional variables can be trivially rounded. Returns false, if there is at least one fractional variable that is not trivially roundable. In this case, the bestColumn returned will not be trivially roundable. */ virtual bool selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound); }; #endif Cbc-2.8.12/src/CbcPartialNodeInfo.hpp0000644000076600007660000000643712131315050015700 0ustar coincoin// $Id: CbcPartialNodeInfo.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/24/09 carved from CbcNode #ifndef CbcPartialNodeInfo_H #define CbcPartialNodeInfo_H #include #include #include "CoinWarmStartBasis.hpp" #include "CoinSearchTree.hpp" #include "CbcBranchBase.hpp" #include "CbcNodeInfo.hpp" class OsiSolverInterface; class OsiSolverBranch; class OsiCuts; class OsiRowCut; class OsiRowCutDebugger; class CoinWarmStartBasis; class CbcCountRowCut; class CbcModel; class CbcNode; class CbcSubProblem; class CbcGeneralBranchingObject; /** \brief Holds information for recreating a subproblem by incremental change from the parent. A CbcPartialNodeInfo object contains changes to the bounds and basis, and additional cuts, required to recreate a subproblem by modifying and augmenting the parent subproblem. */ class CbcPartialNodeInfo : public CbcNodeInfo { public: /** \brief Modify model according to information at node The routine modifies the model according to bound and basis change information at node and adds any cuts to the addCuts array. */ virtual void applyToModel (CbcModel *model, CoinWarmStartBasis *&basis, CbcCountRowCut **addCuts, int ¤tNumberCuts) const ; /// Just apply bounds to one variable - force means overwrite by lower,upper (1=>infeasible) virtual int applyBounds(int iColumn, double & lower, double & upper, int force) ; /** Builds up row basis backwards (until original model). Returns NULL or previous one to apply . Depends on Free being 0 and impossible for cuts */ virtual CbcNodeInfo * buildRowBasis(CoinWarmStartBasis & basis ) const ; // Default Constructor CbcPartialNodeInfo (); // Constructor from current state CbcPartialNodeInfo (CbcNodeInfo * parent, CbcNode * owner, int numberChangedBounds, const int * variables, const double * boundChanges, const CoinWarmStartDiff *basisDiff) ; // Copy constructor CbcPartialNodeInfo ( const CbcPartialNodeInfo &); // Destructor ~CbcPartialNodeInfo (); /// Clone virtual CbcNodeInfo * clone() const; /// Basis diff information inline const CoinWarmStartDiff *basisDiff() const { return basisDiff_ ; } /// Which variable (top bit if upper bound changing) inline const int * variables() const { return variables_; } // New bound inline const double * newBounds() const { return newBounds_; } /// Number of bound changes inline int numberChangedBounds() const { return numberChangedBounds_; } protected: /* Data values */ /// Basis diff information CoinWarmStartDiff *basisDiff_ ; /// Which variable (top bit if upper bound changing) int * variables_; // New bound double * newBounds_; /// Number of bound changes int numberChangedBounds_; private: /// Illegal Assignment operator CbcPartialNodeInfo & operator=(const CbcPartialNodeInfo& rhs); }; #endif //CbcPartialNodeInfo_H Cbc-2.8.12/src/CbcBranchDecision.cpp0000644000076600007660000000532612131315050015524 0ustar coincoin// $Id: CbcBranchDecision.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/12/2009 carved from CbcBranchBase #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "OsiChooseVariable.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchBase.hpp" #include "CbcBranchDecision.hpp" // Default Constructor CbcBranchDecision::CbcBranchDecision () : object_(NULL), model_(NULL), chooseMethod_(NULL) { } // Copy Constructor CbcBranchDecision::CbcBranchDecision (const CbcBranchDecision &rhs) : object_(NULL), model_(rhs.model_), chooseMethod_(NULL) { if (rhs.chooseMethod_) chooseMethod_ = rhs.chooseMethod_->clone(); } CbcBranchDecision::~CbcBranchDecision() { delete object_; delete chooseMethod_; } /* Compare N branching objects. Return index of best and sets way of branching in chosen object. This routine is used only after strong branching. This is reccommended version as it can be more sophisticated */ int CbcBranchDecision::bestBranch (CbcBranchingObject ** objects, int numberObjects, int /*numberUnsatisfied*/, double * changeUp, int * numberInfeasibilitiesUp, double * changeDown, int * numberInfeasibilitiesDown, double /*objectiveValue*/) { int bestWay = 0; int whichObject = -1; if (numberObjects) { initialize(objects[0]->model()); CbcBranchingObject * bestObject = NULL; for (int i = 0 ; i < numberObjects ; i++) { int betterWay = betterBranch(objects[i], bestObject, changeUp[i], numberInfeasibilitiesUp [i], changeDown[i], numberInfeasibilitiesDown[i] ); if (betterWay) { bestObject = objects[i]; bestWay = betterWay; whichObject = i; } } // set way in best if (whichObject >= 0) objects[whichObject]->way(bestWay); } return whichObject; } // Set (clone) chooseMethod void CbcBranchDecision::setChooseMethod(const OsiChooseVariable & method) { delete chooseMethod_; chooseMethod_ = method.clone(); } Cbc-2.8.12/src/config_cbc_default.h0000644000076600007660000000110512377521104015470 0ustar coincoin /***************************************************************************/ /* HERE DEFINE THE PROJECT SPECIFIC PUBLIC MACROS */ /* These are only in effect in a setting that doesn't use configure */ /***************************************************************************/ /* Version number of project */ #define CBC_VERSION "2.8.12" /* Major Version number of project */ #define CBC_VERSION_MAJOR 2 /* Minor Version number of project */ #define CBC_VERSION_MINOR 8 /* Release Version number of project */ #define CBC_VERSION_RELEASE 12 Cbc-2.8.12/src/CbcCutModifier.hpp0000644000076600007660000000251112131315050015061 0ustar coincoin// $Id: CbcCutModifier.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2003, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCutGenerator #ifndef CbcCutModifier_H #define CbcCutModifier_H #include "OsiSolverInterface.hpp" #include "OsiCuts.hpp" #include "CglCutGenerator.hpp" class CbcModel; class OsiRowCut; class OsiRowCutDebugger; /** Abstract cut modifier base class In exotic circumstances - cuts may need to be modified a) strengthened - changed b) weakened - changed c) deleted - set to NULL d) unchanged */ class CbcCutModifier { public: /// Default Constructor CbcCutModifier (); // Copy constructor CbcCutModifier ( const CbcCutModifier &); /// Destructor virtual ~CbcCutModifier(); /// Assignment CbcCutModifier & operator=(const CbcCutModifier& rhs); /// Clone virtual CbcCutModifier * clone() const = 0; /** Returns 0 unchanged 1 strengthened 2 weakened 3 deleted */ virtual int modify(const OsiSolverInterface * solver, OsiRowCut & cut) = 0; /// Create C++ lines to get to current state virtual void generateCpp( FILE * ) {} protected: }; #endif //CbcCutModifier_H Cbc-2.8.12/src/CbcBranchDefaultDecision.cpp0000644000076600007660000004077012131315050017033 0ustar coincoin// $Id: CbcBranchDefaultDecision.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchDefaultDecision.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" //############################################################################## // Default Constructor CbcBranchDefaultDecision::CbcBranchDefaultDecision() : CbcBranchDecision() { bestCriterion_ = 0.0; bestChangeUp_ = 0.0; bestNumberUp_ = 0; bestChangeDown_ = 0.0; bestObject_ = NULL; bestNumberDown_ = 0; } // Copy constructor CbcBranchDefaultDecision::CbcBranchDefaultDecision ( const CbcBranchDefaultDecision & rhs) : CbcBranchDecision(rhs) { bestCriterion_ = rhs.bestCriterion_; bestChangeUp_ = rhs.bestChangeUp_; bestNumberUp_ = rhs.bestNumberUp_; bestChangeDown_ = rhs.bestChangeDown_; bestNumberDown_ = rhs.bestNumberDown_; bestObject_ = rhs.bestObject_; model_ = rhs.model_; } CbcBranchDefaultDecision::~CbcBranchDefaultDecision() { } // Clone CbcBranchDecision * CbcBranchDefaultDecision::clone() const { return new CbcBranchDefaultDecision(*this); } // Initialize i.e. before start of choosing at a node void CbcBranchDefaultDecision::initialize(CbcModel * model) { bestCriterion_ = 0.0; bestChangeUp_ = 0.0; bestNumberUp_ = 0; bestChangeDown_ = 0.0; bestNumberDown_ = 0; bestObject_ = NULL; model_ = model; } /* Simple default decision algorithm. Compare based on infeasibility (numInfUp, numInfDn) until a solution is found by search, then switch to change in objective (changeUp, changeDn). Note that bestSoFar is remembered in bestObject_, so the parameter bestSoFar is unused. */ int CbcBranchDefaultDecision::betterBranch(CbcBranchingObject * thisOne, CbcBranchingObject * /*bestSoFar*/, double changeUp, int numInfUp, double changeDn, int numInfDn) { bool beforeSolution = cbcModel()->getSolutionCount() == cbcModel()->getNumberHeuristicSolutions();; int betterWay = 0; if (beforeSolution) { if (!bestObject_) { bestNumberUp_ = COIN_INT_MAX; bestNumberDown_ = COIN_INT_MAX; } // before solution - choose smallest number // could add in depth as well int bestNumber = CoinMin(bestNumberUp_, bestNumberDown_); if (numInfUp < numInfDn) { if (numInfUp < bestNumber) { betterWay = 1; } else if (numInfUp == bestNumber) { if (changeUp < bestCriterion_) betterWay = 1; } } else if (numInfUp > numInfDn) { if (numInfDn < bestNumber) { betterWay = -1; } else if (numInfDn == bestNumber) { if (changeDn < bestCriterion_) betterWay = -1; } } else { // up and down have same number bool better = false; if (numInfUp < bestNumber) { better = true; } else if (numInfUp == bestNumber) { if (CoinMin(changeUp, changeDn) < bestCriterion_) better = true;; } if (better) { // see which way if (changeUp <= changeDn) betterWay = 1; else betterWay = -1; } } } else { if (!bestObject_) { bestCriterion_ = -1.0; } // got a solution if (changeUp <= changeDn) { if (changeUp > bestCriterion_) betterWay = 1; } else { if (changeDn > bestCriterion_) betterWay = -1; } } if (betterWay) { bestCriterion_ = CoinMin(changeUp, changeDn); bestChangeUp_ = changeUp; bestNumberUp_ = numInfUp; bestChangeDown_ = changeDn; bestNumberDown_ = numInfDn; bestObject_ = thisOne; // See if user is overriding way if (thisOne->object() && thisOne->object()->preferredWay()) betterWay = thisOne->object()->preferredWay(); } return betterWay; } /* Sets or gets best criterion so far */ void CbcBranchDefaultDecision::setBestCriterion(double value) { bestCriterion_ = value; } double CbcBranchDefaultDecision::getBestCriterion() const { return bestCriterion_; } /* Compare N branching objects. Return index of best and sets way of branching in chosen object. This routine is used only after strong branching. */ int CbcBranchDefaultDecision::bestBranch (CbcBranchingObject ** objects, int numberObjects, int numberUnsatisfied, double * changeUp, int * numberInfeasibilitiesUp, double * changeDown, int * numberInfeasibilitiesDown, double objectiveValue) { int bestWay = 0; int whichObject = -1; if (numberObjects) { CbcModel * model = cbcModel(); // at continuous //double continuousObjective = model->getContinuousObjective(); //int continuousInfeasibilities = model->getContinuousInfeasibilities(); // average cost to get rid of infeasibility //double averageCostPerInfeasibility = //(objectiveValue-continuousObjective)/ //(double) (abs(continuousInfeasibilities-numberUnsatisfied)+1); /* beforeSolution is : 0 - before any solution n - n heuristic solutions but no branched one -1 - branched solution found */ int numberSolutions = model->getSolutionCount(); double cutoff = model->getCutoff(); int method = 0; int i; if (numberSolutions) { int numberHeuristic = model->getNumberHeuristicSolutions(); if (numberHeuristic < numberSolutions) { method = 1; } else { method = 2; // look further for ( i = 0 ; i < numberObjects ; i++) { int numberNext = numberInfeasibilitiesUp[i]; if (numberNext < numberUnsatisfied) { int numberUp = numberUnsatisfied - numberInfeasibilitiesUp[i]; double perUnsatisfied = changeUp[i] / static_cast (numberUp); double estimatedObjective = objectiveValue + numberUnsatisfied * perUnsatisfied; if (estimatedObjective < cutoff) method = 3; } numberNext = numberInfeasibilitiesDown[i]; if (numberNext < numberUnsatisfied) { int numberDown = numberUnsatisfied - numberInfeasibilitiesDown[i]; double perUnsatisfied = changeDown[i] / static_cast (numberDown); double estimatedObjective = objectiveValue + numberUnsatisfied * perUnsatisfied; if (estimatedObjective < cutoff) method = 3; } } } method = 2; } else { method = 0; } // Uncomment next to force method 4 //method=4; // FIXME This should be an enum. It will be easier to // understand in the code than numbers. /* Methods : 0 - fewest infeasibilities 1 - largest min change in objective 2 - as 1 but use sum of changes if min close 3 - predicted best solution 4 - take cheapest up branch if infeasibilities same */ int bestNumber = COIN_INT_MAX; double bestCriterion = -1.0e50; double alternativeCriterion = -1.0; double bestEstimate = 1.0e100; switch (method) { case 0: // could add in depth as well for ( i = 0 ; i < numberObjects ; i++) { int thisNumber = CoinMin(numberInfeasibilitiesUp[i], numberInfeasibilitiesDown[i]); if (thisNumber <= bestNumber) { int betterWay = 0; if (numberInfeasibilitiesUp[i] < numberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesUp[i] < bestNumber) { betterWay = 1; } else { if (changeUp[i] < bestCriterion) betterWay = 1; } } else if (numberInfeasibilitiesUp[i] > numberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesDown[i] < bestNumber) { betterWay = -1; } else { if (changeDown[i] < bestCriterion) betterWay = -1; } } else { // up and down have same number bool better = false; if (numberInfeasibilitiesUp[i] < bestNumber) { better = true; } else if (numberInfeasibilitiesUp[i] == bestNumber) { if (CoinMin(changeUp[i], changeDown[i]) < bestCriterion) better = true;; } if (better) { // see which way if (changeUp[i] <= changeDown[i]) betterWay = 1; else betterWay = -1; } } if (betterWay) { bestCriterion = CoinMin(changeUp[i], changeDown[i]); bestNumber = thisNumber; whichObject = i; bestWay = betterWay; } } } break; case 1: for ( i = 0 ; i < numberObjects ; i++) { int betterWay = 0; if (changeUp[i] <= changeDown[i]) { if (changeUp[i] > bestCriterion) betterWay = 1; } else { if (changeDown[i] > bestCriterion) betterWay = -1; } if (betterWay) { bestCriterion = CoinMin(changeUp[i], changeDown[i]); whichObject = i; bestWay = betterWay; } } break; case 2: for ( i = 0 ; i < numberObjects ; i++) { double change = CoinMin(changeUp[i], changeDown[i]); double sum = changeUp[i] + changeDown[i]; bool take = false; if (change > 1.1*bestCriterion) take = true; else if (change > 0.9*bestCriterion && sum + change > bestCriterion + alternativeCriterion) take = true; if (take) { if (changeUp[i] <= changeDown[i]) { if (changeUp[i] > bestCriterion) bestWay = 1; } else { if (changeDown[i] > bestCriterion) bestWay = -1; } bestCriterion = change; alternativeCriterion = sum; whichObject = i; } } break; case 3: for ( i = 0 ; i < numberObjects ; i++) { int numberNext = numberInfeasibilitiesUp[i]; if (numberNext < numberUnsatisfied) { int numberUp = numberUnsatisfied - numberInfeasibilitiesUp[i]; double perUnsatisfied = changeUp[i] / static_cast (numberUp); double estimatedObjective = objectiveValue + numberUnsatisfied * perUnsatisfied; if (estimatedObjective < bestEstimate) { bestEstimate = estimatedObjective; bestWay = 1; whichObject = i; } } numberNext = numberInfeasibilitiesDown[i]; if (numberNext < numberUnsatisfied) { int numberDown = numberUnsatisfied - numberInfeasibilitiesDown[i]; double perUnsatisfied = changeDown[i] / static_cast (numberDown); double estimatedObjective = objectiveValue + numberUnsatisfied * perUnsatisfied; if (estimatedObjective < bestEstimate) { bestEstimate = estimatedObjective; bestWay = -1; whichObject = i; } } } break; case 4: // if number infeas same then cheapest up // first get best number or when going down // now choose smallest change up amongst equal number infeas for ( i = 0 ; i < numberObjects ; i++) { int thisNumber = CoinMin(numberInfeasibilitiesUp[i], numberInfeasibilitiesDown[i]); if (thisNumber <= bestNumber) { int betterWay = 0; if (numberInfeasibilitiesUp[i] < numberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesUp[i] < bestNumber) { betterWay = 1; } else { if (changeUp[i] < bestCriterion) betterWay = 1; } } else if (numberInfeasibilitiesUp[i] > numberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesDown[i] < bestNumber) { betterWay = -1; } else { if (changeDown[i] < bestCriterion) betterWay = -1; } } else { // up and down have same number bool better = false; if (numberInfeasibilitiesUp[i] < bestNumber) { better = true; } else if (numberInfeasibilitiesUp[i] == bestNumber) { if (CoinMin(changeUp[i], changeDown[i]) < bestCriterion) better = true;; } if (better) { // see which way if (changeUp[i] <= changeDown[i]) betterWay = 1; else betterWay = -1; } } if (betterWay) { bestCriterion = CoinMin(changeUp[i], changeDown[i]); bestNumber = thisNumber; whichObject = i; bestWay = betterWay; } } } bestCriterion = 1.0e50; for ( i = 0 ; i < numberObjects ; i++) { int thisNumber = numberInfeasibilitiesUp[i]; if (thisNumber == bestNumber && changeUp) { if (changeUp[i] < bestCriterion) { bestCriterion = changeUp[i]; whichObject = i; bestWay = 1; } } } break; } // set way in best if (whichObject >= 0) { CbcBranchingObject * bestObject = objects[whichObject]; if (bestObject->object() && bestObject->object()->preferredWay()) bestWay = bestObject->object()->preferredWay(); bestObject->way(bestWay); } else { COIN_DETAIL_PRINT(printf("debug\n")); } } return whichObject; } Cbc-2.8.12/src/CbcFullNodeInfo.hpp0000644000076600007660000001257212131315050015203 0ustar coincoin// $Id: CbcFullNodeInfo.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/24/09 carved from CbcNode #ifndef CbcFullNodeInfo_H #define CbcFullNodeInfo_H #include #include #include "CoinWarmStartBasis.hpp" #include "CoinSearchTree.hpp" #include "CbcBranchBase.hpp" #include "CbcNodeInfo.hpp" class OsiSolverInterface; class OsiSolverBranch; class OsiCuts; class OsiRowCut; class OsiRowCutDebugger; class CoinWarmStartBasis; class CbcCountRowCut; class CbcModel; class CbcNode; class CbcSubProblem; class CbcGeneralBranchingObject; //############################################################################# /** Information required to recreate the subproblem at this node When a subproblem is initially created, it is represented by a CbcNode object and an attached CbcNodeInfo object. The CbcNode contains information needed while the subproblem remains live. The CbcNode is deleted when the last branch arm has been evaluated. The CbcNodeInfo contains information required to maintain the branch-and-cut search tree structure (links and reference counts) and to recreate the subproblem for this node (basis, variable bounds, cutting planes). A CbcNodeInfo object remains in existence until all nodes have been pruned from the subtree rooted at this node. The principle used to maintain the reference count is that the reference count is always the sum of all potential and actual children of the node. Specifically,
  • Once it's determined how the node will branch, the reference count is set to the number of potential children (i.e., the number of arms of the branch).
  • As each child is created by CbcNode::branch() (converting a potential child to the active subproblem), the reference count is decremented.
  • If the child survives and will become a node in the search tree (converting the active subproblem into an actual child), increment the reference count.
Notice that the active subproblem lives in a sort of limbo, neither a potential or an actual node in the branch-and-cut tree. CbcNodeInfo objects come in two flavours. A CbcFullNodeInfo object contains a full record of the information required to recreate a subproblem. A CbcPartialNodeInfo object expresses this information in terms of differences from the parent. */ /** \brief Holds complete information for recreating a subproblem. A CbcFullNodeInfo object contains all necessary information (bounds, basis, and cuts) required to recreate a subproblem. \todo While there's no explicit statement, the code often makes the implicit assumption that an CbcFullNodeInfo structure will appear only at the root node of the search tree. Things will break if this assumption is violated. */ class CbcFullNodeInfo : public CbcNodeInfo { public: /** \brief Modify model according to information at node The routine modifies the model according to bound information at node, creates a new basis according to information at node, but with the size passed in through basis, and adds any cuts to the addCuts array. \note The basis passed in via basis is solely a vehicle for passing in the desired basis size. It will be deleted and a new basis returned. */ virtual void applyToModel (CbcModel *model, CoinWarmStartBasis *&basis, CbcCountRowCut **addCuts, int ¤tNumberCuts) const ; /// Just apply bounds to one variable - force means overwrite by lower,upper (1=>infeasible) virtual int applyBounds(int iColumn, double & lower, double & upper, int force) ; /** Builds up row basis backwards (until original model). Returns NULL or previous one to apply . Depends on Free being 0 and impossible for cuts */ virtual CbcNodeInfo * buildRowBasis(CoinWarmStartBasis & basis) const ; // Default Constructor CbcFullNodeInfo (); /** Constructor from continuous or satisfied */ CbcFullNodeInfo (CbcModel * model, int numberRowsAtContinuous); // Copy constructor CbcFullNodeInfo ( const CbcFullNodeInfo &); // Destructor ~CbcFullNodeInfo (); /// Clone virtual CbcNodeInfo * clone() const; /// Lower bounds inline const double * lower() const { return lower_; } /// Set a bound inline void setColLower(int sequence, double value) { lower_[sequence]=value;} /// Mutable lower bounds inline double * mutableLower() const { return lower_; } /// Upper bounds inline const double * upper() const { return upper_; } /// Set a bound inline void setColUpper(int sequence, double value) { upper_[sequence]=value;} /// Mutable upper bounds inline double * mutableUpper() const { return upper_; } protected: // Data /** Full basis This MUST BE A POINTER to avoid cutting extra information in derived warm start classes. */ CoinWarmStartBasis *basis_; int numberIntegers_; // Bounds stored in full double * lower_; double * upper_; private: /// Illegal Assignment operator CbcFullNodeInfo & operator=(const CbcFullNodeInfo& rhs); }; #endif //CbcFullNodeInfo_H Cbc-2.8.12/src/CbcMessage.hpp0000644000076600007660000000366211764413376014270 0ustar coincoin/* $Id: CbcMessage.hpp 1791 2012-06-08 15:15:10Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcMessage_H #define CbcMessage_H #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif /** This deals with Cbc messages (as against Clp messages etc). CoinMessageHandler.hpp is the general part of message handling. All it has are enum's for the various messages. CbcMessage.cpp has text in various languages. It is trivial to use the .hpp and .cpp file as a basis for messages for other components. */ #include "CoinMessageHandler.hpp" enum CBC_Message { CBC_END_GOOD, CBC_MAXNODES, CBC_MAXTIME, CBC_MAXSOLS, CBC_EVENT, CBC_MAXITERS, CBC_SOLUTION, CBC_END_SOLUTION, CBC_SOLUTION2, CBC_END, CBC_INFEAS, CBC_STRONG, CBC_SOLINDIVIDUAL, CBC_INTEGERINCREMENT, CBC_STATUS, CBC_GAP, CBC_ROUNDING, CBC_TREE_SOL, CBC_ROOT, CBC_GENERATOR, CBC_BRANCH, CBC_STRONGSOL, CBC_NOINT, CBC_VUB_PASS, CBC_VUB_END, CBC_NOTFEAS1, CBC_NOTFEAS2, CBC_NOTFEAS3, CBC_CUTOFF_WARNING1, CBC_ITERATE_STRONG, CBC_PRIORITY, CBC_WARNING_STRONG, CBC_START_SUB, CBC_END_SUB, CBC_THREAD_STATS, CBC_CUTS_STATS, CBC_STRONG_STATS, CBC_UNBOUNDED, CBC_OTHER_STATS, CBC_HEURISTICS_OFF, CBC_STATUS2, CBC_FPUMP1, CBC_FPUMP2, CBC_STATUS3, CBC_OTHER_STATS2, CBC_RELAXED1, CBC_RELAXED2, CBC_RESTART, CBC_GENERAL, CBC_ROOT_DETAIL, #ifndef NO_FATHOM_PRINT CBC_FATHOM_CHANGE, #endif CBC_DUMMY_END }; class CbcMessage : public CoinMessages { public: /**@name Constructors etc */ //@{ /** Constructor */ CbcMessage(Language language = us_en); //@} }; #endif Cbc-2.8.12/src/CbcDummyBranchingObject.cpp0000644000076600007660000000547112131315050016710 0ustar coincoin// $Id: CbcDummyBranchingObject.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcDummyBranchingObject.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" //############################################################################## // Default Constructor CbcDummyBranchingObject::CbcDummyBranchingObject(CbcModel * model) : CbcBranchingObject(model, 0, 0, 0.5) { setNumberBranchesLeft(1); } // Copy constructor CbcDummyBranchingObject::CbcDummyBranchingObject ( const CbcDummyBranchingObject & rhs) : CbcBranchingObject(rhs) { } // Assignment operator CbcDummyBranchingObject & CbcDummyBranchingObject::operator=( const CbcDummyBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); } return *this; } CbcBranchingObject * CbcDummyBranchingObject::clone() const { return (new CbcDummyBranchingObject(*this)); } // Destructor CbcDummyBranchingObject::~CbcDummyBranchingObject () { } /* Perform a dummy branch */ double CbcDummyBranchingObject::branch() { decrementNumberBranchesLeft(); return 0.0; } // Print what would happen void CbcDummyBranchingObject::print() { printf("Dummy branch\n"); } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcDummyBranchingObject::compareOriginalObject (const CbcBranchingObject* /*brObj*/) const { throw("must implement"); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcDummyBranchingObject::compareBranchingObject (const CbcBranchingObject* /*brObj*/, const bool /*replaceIfOverlap*/) { throw("must implement"); } Cbc-2.8.12/src/CbcHeuristicDiveFractional.cpp0000644000076600007660000000661612131315050017426 0ustar coincoin/* $Id: CbcHeuristicDiveFractional.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcHeuristicDiveFractional.hpp" #include "CbcStrategy.hpp" // Default Constructor CbcHeuristicDiveFractional::CbcHeuristicDiveFractional() : CbcHeuristicDive() { } // Constructor from model CbcHeuristicDiveFractional::CbcHeuristicDiveFractional(CbcModel & model) : CbcHeuristicDive(model) { } // Destructor CbcHeuristicDiveFractional::~CbcHeuristicDiveFractional () { } // Clone CbcHeuristicDiveFractional * CbcHeuristicDiveFractional::clone() const { return new CbcHeuristicDiveFractional(*this); } // Create C++ lines to get to current state void CbcHeuristicDiveFractional::generateCpp( FILE * fp) { CbcHeuristicDiveFractional other; fprintf(fp, "0#include \"CbcHeuristicDiveFractional.hpp\"\n"); fprintf(fp, "3 CbcHeuristicDiveFractional heuristicDiveFractional(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicDiveFractional"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicDiveFractional);\n"); } // Copy constructor CbcHeuristicDiveFractional::CbcHeuristicDiveFractional(const CbcHeuristicDiveFractional & rhs) : CbcHeuristicDive(rhs) { } // Assignment operator CbcHeuristicDiveFractional & CbcHeuristicDiveFractional::operator=( const CbcHeuristicDiveFractional & rhs) { if (this != &rhs) { CbcHeuristicDive::operator=(rhs); } return *this; } bool CbcHeuristicDiveFractional::selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound) { int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); bestColumn = -1; bestRound = -1; // -1 rounds down, +1 rounds up double bestFraction = COIN_DBL_MAX; bool allTriviallyRoundableSoFar = true; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; double fraction = value - floor(value); int round = 0; if (fabs(floor(value + 0.5) - value) > integerTolerance) { if (allTriviallyRoundableSoFar || (downLocks_[i] > 0 && upLocks_[i] > 0)) { if (allTriviallyRoundableSoFar && downLocks_[i] > 0 && upLocks_[i] > 0) { allTriviallyRoundableSoFar = false; bestFraction = COIN_DBL_MAX; } // the variable cannot be rounded if (fraction < 0.5) round = -1; else { round = 1; fraction = 1.0 - fraction; } // if variable is not binary, penalize it if (!solver->isBinary(iColumn)) fraction *= 1000.0; if (fraction < bestFraction) { bestColumn = iColumn; bestFraction = fraction; bestRound = round; } } } } return allTriviallyRoundableSoFar; } Cbc-2.8.12/src/CbcBranchDecision.hpp0000644000076600007660000001060112131315050015521 0ustar coincoin// $Id: CbcBranchDecision.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/12/2009 carved from CbcBranchBase #ifndef CbcBranchDecision_H #define CbcBranchDecision_H #include "CbcBranchBase.hpp" /** Abstract branching decision base class In the abstract, an CbcBranchDecision object is expected to be able to compare two possible branching choices. The #betterBranch() method is the crucial routine. It is expected to be able to compare two \link CbcBranchingObject CbcBranchingObjects \endlink. See CbcObject for an overview of the three classes (CbcObject, CbcBranchingObject, and CbcBranchDecision) which make up cbc's branching model. */ class CbcModel; class OsiChooseVariable; class CbcBranchDecision { public: /// Default Constructor CbcBranchDecision (); // Copy constructor CbcBranchDecision ( const CbcBranchDecision &); /// Destructor virtual ~CbcBranchDecision(); /// Clone virtual CbcBranchDecision * clone() const = 0; /// Initialize e.g. before starting to choose a branch at a node virtual void initialize(CbcModel * model) = 0; /** \brief Compare two branching objects. Return nonzero if branching using \p thisOne is better than branching using \p bestSoFar. If \p bestSoFar is NULL, the routine should return a nonzero value. This routine is used only after strong branching. Either this or bestBranch is used depending which user wants. */ virtual int betterBranch (CbcBranchingObject * thisOne, CbcBranchingObject * bestSoFar, double changeUp, int numberInfeasibilitiesUp, double changeDown, int numberInfeasibilitiesDown) = 0 ; /** \brief Compare N branching objects. Return index of best and sets way of branching in chosen object. Either this or betterBranch is used depending which user wants. */ virtual int bestBranch (CbcBranchingObject ** objects, int numberObjects, int numberUnsatisfied, double * changeUp, int * numberInfeasibilitiesUp, double * changeDown, int * numberInfeasibilitiesDown, double objectiveValue) ; /** Says whether this method can handle both methods - 1 better, 2 best, 3 both */ virtual int whichMethod() { return 2; } /** Saves a clone of current branching object. Can be used to update information on object causing branch - after branch */ virtual void saveBranchingObject(OsiBranchingObject * ) {} /** Pass in information on branch just done. assumes object can get information from solver */ virtual void updateInformation(OsiSolverInterface * , const CbcNode * ) {} /** Sets or gets best criterion so far */ virtual void setBestCriterion(double ) {} virtual double getBestCriterion() const { return 0.0; } /// Create C++ lines to get to current state virtual void generateCpp( FILE * ) {} /// Model inline CbcModel * cbcModel() const { return model_; } /* If chooseMethod_ id non-null then the rest is fairly pointless as choosemethod_ will be doing all work This comment makes more sense if you realise that there's a conversion in process from the Cbc branching classes to Osi branching classes. The test for use of the Osi branching classes is CbcModel::branchingMethod_ non-null (i.e., it points to one of these CbcBranchDecision objects) and that branch decision object has an OsiChooseVariable method set. In which case, we'll use it, rather than the choose[*]Variable methods defined in CbcNode. */ OsiChooseVariable * chooseMethod() const { return chooseMethod_; } /// Set (clone) chooseMethod void setChooseMethod(const OsiChooseVariable & method); protected: // Clone of branching object CbcBranchingObject * object_; /// Pointer to model CbcModel * model_; /* If chooseMethod_ id non-null then the rest is fairly pointless as choosemethod_ will be doing all work */ OsiChooseVariable * chooseMethod_; private: /// Assignment is illegal CbcBranchDecision & operator=(const CbcBranchDecision& rhs); }; #endif Cbc-2.8.12/src/CbcNodeInfo.cpp0000644000076600007660000003400612131315050014347 0ustar coincoin// $Id: CbcNodeInfo.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/24/09 carved from CbcNode #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" #include //#define CBC_DEBUG 1 //#define CHECK_CUT_COUNTS //#define CHECK_NODE //#define CBC_CHECK_BASIS #include #include #define CUTS #include "OsiSolverInterface.hpp" #include "OsiChooseVariable.hpp" #include "OsiAuxInfo.hpp" #include "OsiSolverBranch.hpp" #include "CoinWarmStartBasis.hpp" #include "CoinTime.hpp" #include "CbcModel.hpp" #include "CbcNode.hpp" #include "CbcStatistics.hpp" #include "CbcStrategy.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchDynamic.hpp" #include "OsiRowCut.hpp" #include "OsiRowCutDebugger.hpp" #include "OsiCuts.hpp" #include "CbcCountRowCut.hpp" #include "CbcFeasibilityBase.hpp" #include "CbcMessage.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #include "ClpSimplexOther.hpp" #endif using namespace std; #include "CglCutGenerator.hpp" #include "CbcNodeInfo.hpp" // Default Constructor CbcNodeInfo::CbcNodeInfo () : numberPointingToThis_(0), parent_(NULL), parentBranch_(NULL), owner_(NULL), numberCuts_(0), nodeNumber_(0), cuts_(NULL), numberRows_(0), numberBranchesLeft_(0), active_(7) { #ifdef CHECK_NODE printf("CbcNodeInfo %x Constructor\n", this); #endif } void CbcNodeInfo::setParentBasedData() { if (parent_) { numberRows_ = parent_->numberRows_ + parent_->numberCuts_; //parent_->increment(); if (parent_->owner()) { const OsiBranchingObject* br = parent_->owner()->branchingObject(); assert(br); parentBranch_ = br->clone(); } } } void CbcNodeInfo::unsetParentBasedData() { if (parent_) { numberRows_ = 0; if (parent_->owner()) { delete parentBranch_; parentBranch_ = NULL; } } } #ifdef JJF_ZERO // Constructor given parent CbcNodeInfo::CbcNodeInfo (CbcNodeInfo * parent) : numberPointingToThis_(2), parent_(parent), parentBranch_(NULL), owner_(NULL), numberCuts_(0), nodeNumber_(0), cuts_(NULL), numberRows_(0), numberBranchesLeft_(2), active_(7) { #ifdef CHECK_NODE printf("CbcNodeInfo %x Constructor from parent %x\n", this, parent_); #endif //setParentBasedData(); } #endif // Copy Constructor CbcNodeInfo::CbcNodeInfo (const CbcNodeInfo & rhs) : numberPointingToThis_(rhs.numberPointingToThis_), parent_(rhs.parent_), parentBranch_(NULL), owner_(rhs.owner_), numberCuts_(rhs.numberCuts_), nodeNumber_(rhs.nodeNumber_), cuts_(NULL), numberRows_(rhs.numberRows_), numberBranchesLeft_(rhs.numberBranchesLeft_), active_(rhs.active_) { #ifdef CHECK_NODE printf("CbcNodeInfo %x Copy constructor\n", this); #endif if (numberCuts_) { cuts_ = new CbcCountRowCut * [numberCuts_]; int n = 0; for (int i = 0; i < numberCuts_; i++) { CbcCountRowCut * thisCut = rhs.cuts_[i]; if (thisCut) { // I think this is correct - new one should take priority thisCut->setInfo(this, n); thisCut->increment(numberBranchesLeft_); cuts_[n++] = thisCut; } } numberCuts_ = n; } if (rhs.parentBranch_) { parentBranch_ = rhs.parentBranch_->clone(); } } // Constructor given parent and owner CbcNodeInfo::CbcNodeInfo (CbcNodeInfo * parent, CbcNode * owner) : numberPointingToThis_(2), parent_(parent), parentBranch_(NULL), owner_(owner), numberCuts_(0), nodeNumber_(0), cuts_(NULL), numberRows_(0), numberBranchesLeft_(2), active_(7) { #ifdef CHECK_NODE printf("CbcNodeInfo %x Constructor from parent %x\n", this, parent_); #endif //setParentBasedData(); } /** Take care to detach from the owning CbcNode and decrement the reference count in the parent. If this is the last nodeInfo object pointing to the parent, make a recursive call to delete the parent. */ CbcNodeInfo::~CbcNodeInfo() { #ifdef CHECK_NODE printf("CbcNodeInfo %x Destructor parent %x\n", this, parent_); #endif assert(!numberPointingToThis_); // But there may be some left (max nodes?) for (int i = 0; i < numberCuts_; i++) { if (cuts_[i]) { #ifndef GLOBAL_CUTS_JUST_POINTERS delete cuts_[i]; #else if (cuts_[i]->globallyValidAsInteger() != 2) delete cuts_[i]; #endif } } delete [] cuts_; if (owner_) owner_->nullNodeInfo(); if (parent_) { int numberLinks = parent_->decrement(); if (!numberLinks) delete parent_; } delete parentBranch_; } //#define ALLCUTS void CbcNodeInfo::decrementCuts(int change) { int i; // get rid of all remaining if negative int changeThis; if (change < 0) changeThis = numberBranchesLeft_; else changeThis = change; // decrement cut counts for (i = 0; i < numberCuts_; i++) { if (cuts_[i]) { int number = cuts_[i]->decrement(changeThis); if (!number) { //printf("info %x del cut %d %x\n",this,i,cuts_[i]); #ifndef GLOBAL_CUTS_JUST_POINTERS delete cuts_[i]; #else if (cuts_[i]->globallyValidAsInteger() != 2) delete cuts_[i]; #endif cuts_[i] = NULL; } } } } void CbcNodeInfo::incrementCuts(int change) { int i; assert (change > 0); // increment cut counts for (i = 0; i < numberCuts_; i++) { if (cuts_[i]) cuts_[i]->increment(change); } } void CbcNodeInfo::decrementParentCuts(CbcModel * model, int change) { if (parent_) { // get rid of all remaining if negative int changeThis; if (change < 0) changeThis = numberBranchesLeft_; else changeThis = change; int i; // Get over-estimate of space needed for basis CoinWarmStartBasis & dummy = model->workingBasis(); dummy.setSize(0, numberRows_ + numberCuts_); buildRowBasis(dummy); /* everything is zero (i.e. free) so we can use to see if latest basis */ CbcNodeInfo * thisInfo = parent_; while (thisInfo) thisInfo = thisInfo->buildRowBasis(dummy); // decrement cut counts thisInfo = parent_; int numberRows = numberRows_; while (thisInfo) { for (i = thisInfo->numberCuts_ - 1; i >= 0; i--) { CoinWarmStartBasis::Status status = dummy.getArtifStatus(--numberRows); #ifdef ALLCUTS status = CoinWarmStartBasis::isFree; #endif if (thisInfo->cuts_[i]) { int number = 1; if (status != CoinWarmStartBasis::basic) { // tight - drop 1 or 2 if (change < 0) number = thisInfo->cuts_[i]->decrement(changeThis); else number = thisInfo->cuts_[i]->decrement(change); } if (!number) { #ifndef GLOBAL_CUTS_JUST_POINTERS delete thisInfo->cuts_[i]; #else if (thisInfo->cuts_[i]->globallyValidAsInteger() != 2) delete thisInfo->cuts_[i]; #endif thisInfo->cuts_[i] = NULL; } } } thisInfo = thisInfo->parent_; } } } #ifdef JJF_ZERO void CbcNodeInfo::incrementParentCuts(CbcModel * model, int change) { if (parent_) { int i; // Get over-estimate of space needed for basis CoinWarmStartBasis & dummy = model->workingBasis(); dummy.setSize(0, numberRows_ + numberCuts_); /* everything is zero (i.e. free) so we can use to see if latest basis */ buildRowBasis(dummy); CbcNodeInfo * thisInfo = parent_; while (thisInfo) thisInfo = thisInfo->buildRowBasis(dummy); // increment cut counts thisInfo = parent_; int numberRows = numberRows_; while (thisInfo) { for (i = thisInfo->numberCuts_ - 1; i >= 0; i--) { CoinWarmStartBasis::Status status = dummy.getArtifStatus(--numberRows); #ifdef ALLCUTS status = CoinWarmStartBasis::isFree; #endif if (thisInfo->cuts_[i] && status != CoinWarmStartBasis::basic) { thisInfo->cuts_[i]->increment(change); } } thisInfo = thisInfo->parent_; } } } #endif /* Append cuts to the cuts_ array in a nodeInfo. The initial reference count is set to numberToBranchOn, which will normally be the number of arms defined for the CbcBranchingObject attached to the CbcNode that owns this CbcNodeInfo. */ void CbcNodeInfo::addCuts (OsiCuts & cuts, int numberToBranchOn, /*int * whichGenerator,*/int numberPointingToThis) { int numberCuts = cuts.sizeRowCuts(); if (numberCuts) { int i; if (!numberCuts_) { cuts_ = new CbcCountRowCut * [numberCuts]; } else { CbcCountRowCut ** temp = new CbcCountRowCut * [numberCuts+numberCuts_]; memcpy(temp, cuts_, numberCuts_*sizeof(CbcCountRowCut *)); delete [] cuts_; cuts_ = temp; } for (i = 0; i < numberCuts; i++) { CbcCountRowCut * thisCut = new CbcCountRowCut(*cuts.rowCutPtr(i), this, numberCuts_, -1, numberPointingToThis); thisCut->increment(numberToBranchOn); cuts_[numberCuts_++] = thisCut; #ifdef CBC_DEBUG #if CBC_DEBUG>1 int n = thisCut->row().getNumElements(); printf("Cut %d has %d entries, rhs %g %g =>", i, n, thisCut->lb(), thisCut->ub()); int j; const int * index = thisCut->row().getIndices(); const double * element = thisCut->row().getElements(); for (j = 0; j < n; j++) { printf(" (%d,%g)", index[j], element[j]); assert(fabs(element[j]) > 1.00e-12); } printf("\n"); #else int n = thisCut->row().getNumElements(); int j; const double * element = thisCut->row().getElements(); for (j = 0; j < n; j++) { assert(fabs(element[j]) > 1.00e-12); } #endif #endif } } } void CbcNodeInfo::addCuts(int numberCuts, CbcCountRowCut ** cut, int numberToBranchOn) { if (numberCuts) { int i; if (!numberCuts_) { cuts_ = new CbcCountRowCut * [numberCuts]; } else { CbcCountRowCut ** temp = new CbcCountRowCut * [numberCuts+numberCuts_]; memcpy(temp, cuts_, numberCuts_*sizeof(CbcCountRowCut *)); delete [] cuts_; cuts_ = temp; } for (i = 0; i < numberCuts; i++) { CbcCountRowCut * thisCut = cut[i]; thisCut->setInfo(this, numberCuts_); //printf("info %x cut %d %x\n",this,i,thisCut); thisCut->increment(numberToBranchOn); cuts_[numberCuts_++] = thisCut; #ifdef CBC_DEBUG int n = thisCut->row().getNumElements(); #if CBC_DEBUG>1 printf("Cut %d has %d entries, rhs %g %g =>", i, n, thisCut->lb(), thisCut->ub()); #endif int j; #if CBC_DEBUG>1 const int * index = thisCut->row().getIndices(); #endif const double * element = thisCut->row().getElements(); for (j = 0; j < n; j++) { #if CBC_DEBUG>1 printf(" (%d,%g)", index[j], element[j]); #endif assert(fabs(element[j]) > 1.00e-12); } printf("\n"); #endif } } } // delete cuts void CbcNodeInfo::deleteCuts(int numberToDelete, CbcCountRowCut ** cuts) { int i; int j; int last = -1; for (i = 0; i < numberToDelete; i++) { CbcCountRowCut * next = cuts[i]; for (j = last + 1; j < numberCuts_; j++) { if (next == cuts_[j]) break; } if (j == numberCuts_) { // start from beginning for (j = 0; j < last; j++) { if (next == cuts_[j]) break; } assert(j < last); } last = j; int number = cuts_[j]->decrement(); if (!number) { #ifndef GLOBAL_CUTS_JUST_POINTERS delete cuts_[j]; #else if (cuts_[j]->globallyValidAsInteger() != 2) delete cuts_[j]; #endif } cuts_[j] = NULL; } j = 0; for (i = 0; i < numberCuts_; i++) { if (cuts_[i]) cuts_[j++] = cuts_[i]; } numberCuts_ = j; } // delete cuts void CbcNodeInfo::deleteCuts(int numberToDelete, int * which) { int i; for (i = 0; i < numberToDelete; i++) { int iCut = which[i]; int number = cuts_[iCut]->decrement(); if (!number) { #ifndef GLOBAL_CUTS_JUST_POINTERS delete cuts_[iCut]; #else if (cuts_[iCut]->globallyValidAsInteger() != 2) delete cuts_[iCut]; #endif } cuts_[iCut] = NULL; } int j = 0; for (i = 0; i < numberCuts_; i++) { if (cuts_[i]) cuts_[j++] = cuts_[i]; } numberCuts_ = j; } // Really delete a cut void CbcNodeInfo::deleteCut(int whichOne) { assert(whichOne < numberCuts_); cuts_[whichOne] = NULL; } /* Deactivate node information. 1 - bounds 2 - cuts 4 - basis! */ void CbcNodeInfo::deactivate(int mode) { active_ &= (~mode); } Cbc-2.8.12/src/CbcGenMessages.hpp0000644000076600007660000000151212131315050015050 0ustar coincoin/* Copyright (C) 2007 Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). */ /* This file is part of cbc-generic. */ #ifndef CbcGenMessages_H #define CbcGenMessages_H /*! \file This file contains the enum that defines symbolic names for for cbc-generic messages. */ /* $Id: CbcGenMessages.hpp 1902 2013-04-10 16:58:16Z stefan $ */ /* There's arguably not enough content here to justify a separate file, but it maintains the common pattern for COIN code. */ /*! \brief Symbolic names for cbc-generic messages These are the `internal IDs' for cbc-generic messages. */ typedef enum { CBCGEN_TEST_MSG = 1, CBCGEN_NEW_SOLVER, CBCGEN_CONFUSION, CBCGEN_DUMMY_END } CbcGenMsgCode ; #endif Cbc-2.8.12/src/CbcSolverHeuristics.hpp0000644000076600007660000000264112131315050016170 0ustar coincoin/* $Id: CbcSolverHeuristics.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /*! \file CbcSolverHeuristics.hpp \brief Routines for doing heuristics. */ #ifndef CbcSolverHeuristics_H #define CbcSolverHeuristics_H void crunchIt(ClpSimplex * model); /* On input doAction - 0 just fix in original and return NULL 1 return fixed non-presolved solver 2 as one but use presolve Inside this 3 use presolve and fix ones with large cost ? do heuristics and set best solution ? do BAB and just set best solution 10+ then use lastSolution and relax a few -2 cleanup afterwards if using 2 On output - number fixed */ OsiClpSolverInterface * fixVubs(CbcModel & model, int skipZero2, int & doAction, CoinMessageHandler * /*generalMessageHandler*/, const double * lastSolution, double dextra[6], int extra[5]); /** 1 - add heuristics to model 2 - do heuristics (and set cutoff and best solution) 3 - for miplib test so skip some (out model later) */ int doHeuristics(CbcModel * model, int type, CbcOrClpParam *parameters_, int numberParameters_,int noPrinting_,int initialPumpTune) ; #endif //CbcSolverHeuristics_H Cbc-2.8.12/src/CbcHeuristicDiveCoefficient.hpp0000644000076600007660000000317112131315050017560 0ustar coincoin/* $Id: CbcHeuristicDiveCoefficient.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicDiveCoefficient_H #define CbcHeuristicDiveCoefficient_H #include "CbcHeuristicDive.hpp" /** DiveCoefficient class */ class CbcHeuristicDiveCoefficient : public CbcHeuristicDive { public: // Default Constructor CbcHeuristicDiveCoefficient (); // Constructor with model - assumed before cuts CbcHeuristicDiveCoefficient (CbcModel & model); // Copy constructor CbcHeuristicDiveCoefficient ( const CbcHeuristicDiveCoefficient &); // Destructor ~CbcHeuristicDiveCoefficient (); /// Clone virtual CbcHeuristicDiveCoefficient * clone() const; /// Assignment operator CbcHeuristicDiveCoefficient & operator=(const CbcHeuristicDiveCoefficient& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Selects the next variable to branch on /** Returns true if all the fractional variables can be trivially rounded. Returns false, if there is at least one fractional variable that is not trivially roundable. In this case, the bestColumn returned will not be trivially roundable. */ virtual bool selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound); }; #endif Cbc-2.8.12/src/CbcCompareDepth.cpp0000644000076600007660000000340612131315050015221 0ustar coincoin// $Id: CbcCompareDepth.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/24/09 carved out of CbcCompareActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CbcMessage.hpp" #include "CbcModel.hpp" #include "CbcTree.hpp" #include "CbcCompareActual.hpp" #include "CoinError.hpp" #include "CbcCompareDepth.hpp" /** Default Constructor */ CbcCompareDepth::CbcCompareDepth () : CbcCompareBase() { test_ = this; } // Copy constructor CbcCompareDepth::CbcCompareDepth ( const CbcCompareDepth & rhs) : CbcCompareBase(rhs) { } // Clone CbcCompareBase * CbcCompareDepth::clone() const { return new CbcCompareDepth(*this); } // Assignment operator CbcCompareDepth & CbcCompareDepth::operator=( const CbcCompareDepth & rhs) { if (this != &rhs) { CbcCompareBase::operator=(rhs); } return *this; } // Destructor CbcCompareDepth::~CbcCompareDepth () { } // Returns true if y better than x bool CbcCompareDepth::test (CbcNode * x, CbcNode * y) { int testX = x->depth(); int testY = y->depth(); if (testX != testY) return testX < testY; else return equalityTest(x, y); // so ties will be broken in consistent manner } // Create C++ lines to get to current state void CbcCompareDepth::generateCpp( FILE * fp) { fprintf(fp, "0#include \"CbcCompareActual.hpp\"\n"); fprintf(fp, "3 CbcCompareDepth compare;\n"); fprintf(fp, "3 cbcModel->setNodeComparison(compare);\n"); } Cbc-2.8.12/src/CbcCutGenerator.cpp0000644000076600007660000015031212130022033015242 0ustar coincoin/* $Id: CbcCutGenerator.cpp 1883 2013-04-06 13:33:15Z stefan $ */ // Copyright (C) 2003, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" #include #include #include #include #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #else #include "OsiSolverInterface.hpp" #endif //#define CGL_DEBUG 1 #ifdef CGL_DEBUG #include "OsiRowCutDebugger.hpp" #endif #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcCutGenerator.hpp" #include "CbcBranchDynamic.hpp" #include "CglProbing.hpp" #include "CoinTime.hpp" // Default Constructor CbcCutGenerator::CbcCutGenerator () : timeInCutGenerator_(0.0), model_(NULL), generator_(NULL), generatorName_(NULL), whenCutGenerator_(-1), whenCutGeneratorInSub_(-100), switchOffIfLessThan_(0), depthCutGenerator_(-1), depthCutGeneratorInSub_(-1), inaccuracy_(0), numberTimes_(0), numberCuts_(0), numberElements_(0), numberColumnCuts_(0), numberCutsActive_(0), numberCutsAtRoot_(0), numberActiveCutsAtRoot_(0), numberShortCutsAtRoot_(0), switches_(1), maximumTries_(-1) { } // Normal constructor CbcCutGenerator::CbcCutGenerator(CbcModel * model, CglCutGenerator * generator, int howOften, const char * name, bool normal, bool atSolution, bool infeasible, int howOftenInSub, int whatDepth, int whatDepthInSub, int switchOffIfLessThan) : timeInCutGenerator_(0.0), depthCutGenerator_(whatDepth), depthCutGeneratorInSub_(whatDepthInSub), inaccuracy_(0), numberTimes_(0), numberCuts_(0), numberElements_(0), numberColumnCuts_(0), numberCutsActive_(0), numberCutsAtRoot_(0), numberActiveCutsAtRoot_(0), numberShortCutsAtRoot_(0), switches_(1), maximumTries_(-1) { if (howOften < -1900) { setGlobalCuts(true); howOften += 2000; } else if (howOften < -900) { setGlobalCutsAtRoot(true); howOften += 1000; } model_ = model; generator_ = generator->clone(); generator_->refreshSolver(model_->solver()); setNeedsOptimalBasis(generator_->needsOptimalBasis()); whenCutGenerator_ = howOften; whenCutGeneratorInSub_ = howOftenInSub; switchOffIfLessThan_ = switchOffIfLessThan; if (name) generatorName_ = CoinStrdup(name); else generatorName_ = CoinStrdup("Unknown"); setNormal(normal); setAtSolution(atSolution); setWhenInfeasible(infeasible); } // Copy constructor CbcCutGenerator::CbcCutGenerator ( const CbcCutGenerator & rhs) { model_ = rhs.model_; generator_ = rhs.generator_->clone(); //generator_->refreshSolver(model_->solver()); whenCutGenerator_ = rhs.whenCutGenerator_; whenCutGeneratorInSub_ = rhs.whenCutGeneratorInSub_; switchOffIfLessThan_ = rhs.switchOffIfLessThan_; depthCutGenerator_ = rhs.depthCutGenerator_; depthCutGeneratorInSub_ = rhs.depthCutGeneratorInSub_; generatorName_ = CoinStrdup(rhs.generatorName_); switches_ = rhs.switches_; maximumTries_ = rhs.maximumTries_; timeInCutGenerator_ = rhs.timeInCutGenerator_; savedCuts_ = rhs.savedCuts_; inaccuracy_ = rhs.inaccuracy_; numberTimes_ = rhs.numberTimes_; numberCuts_ = rhs.numberCuts_; numberElements_ = rhs.numberElements_; numberColumnCuts_ = rhs.numberColumnCuts_; numberCutsActive_ = rhs.numberCutsActive_; numberCutsAtRoot_ = rhs.numberCutsAtRoot_; numberActiveCutsAtRoot_ = rhs.numberActiveCutsAtRoot_; numberShortCutsAtRoot_ = rhs.numberShortCutsAtRoot_; } // Assignment operator CbcCutGenerator & CbcCutGenerator::operator=( const CbcCutGenerator & rhs) { if (this != &rhs) { delete generator_; free(generatorName_); model_ = rhs.model_; generator_ = rhs.generator_->clone(); generator_->refreshSolver(model_->solver()); whenCutGenerator_ = rhs.whenCutGenerator_; whenCutGeneratorInSub_ = rhs.whenCutGeneratorInSub_; switchOffIfLessThan_ = rhs.switchOffIfLessThan_; depthCutGenerator_ = rhs.depthCutGenerator_; depthCutGeneratorInSub_ = rhs.depthCutGeneratorInSub_; generatorName_ = CoinStrdup(rhs.generatorName_); switches_ = rhs.switches_; maximumTries_ = rhs.maximumTries_; timeInCutGenerator_ = rhs.timeInCutGenerator_; savedCuts_ = rhs.savedCuts_; inaccuracy_ = rhs.inaccuracy_; numberTimes_ = rhs.numberTimes_; numberCuts_ = rhs.numberCuts_; numberElements_ = rhs.numberElements_; numberColumnCuts_ = rhs.numberColumnCuts_; numberCutsActive_ = rhs.numberCutsActive_; numberCutsAtRoot_ = rhs.numberCutsAtRoot_; numberActiveCutsAtRoot_ = rhs.numberActiveCutsAtRoot_; numberShortCutsAtRoot_ = rhs.numberShortCutsAtRoot_; } return *this; } // Destructor CbcCutGenerator::~CbcCutGenerator () { free(generatorName_); delete generator_; } /* This is used to refresh any inforamtion. It also refreshes the solver in the cut generator in case generator wants to do some work */ void CbcCutGenerator::refreshModel(CbcModel * model) { model_ = model; generator_->refreshSolver(model_->solver()); } /* Generate cuts for the model data contained in si. The generated cuts are inserted into and returned in the collection of cuts cs. */ bool CbcCutGenerator::generateCuts( OsiCuts & cs , int fullScan, OsiSolverInterface * solver, CbcNode * node) { /* Make some decisions about whether we'll generate cuts. First convert whenCutGenerator_ to a set of canonical values for comparison to the node count. 0 < mod 1000000, with a result of 0 forced to 1 -99 <= <= 0 convert to 1 -100 = Off, period */ int depth; if (node) depth = node->depth(); else depth = 0; int howOften = whenCutGenerator_; if (dynamic_cast(generator_)) { if (howOften == -100 && model_->doCutsNow(3)) { howOften = 1; // do anyway } } if (howOften == -100) return false; int pass = model_->getCurrentPassNumber() - 1; if (maximumTries_>0) { // howOften means what it says if ((pass%howOften)!=0||depth) return false; else howOften=1; } if (howOften > 0) howOften = howOften % 1000000; else howOften = 1; if (!howOften) howOften = 1; bool returnCode = false; //OsiSolverInterface * solver = model_->solver(); // Reset cuts on first pass if (!pass) savedCuts_ = OsiCuts(); /* Determine if we should generate cuts based on node count. */ bool doThis = (model_->getNodeCount() % howOften) == 0; /* If the user has provided a depth specification, it will override the node count specification. */ if (depthCutGenerator_ > 0) { doThis = (depth % depthCutGenerator_) == 0; if (depth < depthCutGenerator_) doThis = true; // and also at top of tree } /* A few magic numbers ... The distinction between -100 and 100 for howOften is that we can override 100 with fullScan. -100 means no cuts, period. As does the magic number -200 for whenCutGeneratorInSub_. */ // But turn off if 100 if (howOften == 100) doThis = false; // Switch off if special setting if (whenCutGeneratorInSub_ == -200 && model_->parentModel()) { fullScan = 0; doThis = false; } if (fullScan || doThis) { CoinThreadRandom * randomNumberGenerator = NULL; #ifdef COIN_HAS_CLP { OsiClpSolverInterface * clpSolver = dynamic_cast (solver); if (clpSolver) randomNumberGenerator = clpSolver->getModelPtr()->randomNumberGenerator(); } #endif double time1 = 0.0; if (timing()) time1 = CoinCpuTime(); //#define CBC_DEBUG int numberRowCutsBefore = cs.sizeRowCuts() ; int numberColumnCutsBefore = cs.sizeColCuts() ; #ifdef JJF_ZERO int cutsBefore = cs.sizeCuts(); #endif CglTreeInfo info; info.level = depth; info.pass = pass; info.formulation_rows = model_->numberRowsAtContinuous(); info.inTree = node != NULL; info.randomNumberGenerator = randomNumberGenerator; info.options = (globalCutsAtRoot()) ? 8 : 0; if (ineffectualCuts()) info.options |= 32; if (globalCuts()) info.options |= 16; if (fullScan < 0) info.options |= 128; if (whetherInMustCallAgainMode()) info.options |= 1024; // See if we want alternate set of cuts if ((model_->moreSpecialOptions()&16384) != 0) info.options |= 256; if (model_->parentModel()) info.options |= 512; // above had &&!model_->parentModel()&&depth<2) incrementNumberTimesEntered(); CglProbing* generator = dynamic_cast(generator_); //if (!depth&&!pass) //printf("Cut generator %s when %d\n",generatorName_,whenCutGenerator_); if (!generator) { // Pass across model information in case it could be useful //void * saveData = solver->getApplicationData(); //solver->setApplicationData(model_); generator_->generateCuts(*solver, cs, info); //solver->setApplicationData(saveData); } else { // Probing - return tight column bounds CglTreeProbingInfo * info2 = model_->probingInfo(); bool doCuts = false; if (info2 && !depth) { info2->options = (globalCutsAtRoot()) ? 8 : 0; info2->level = depth; info2->pass = pass; info2->formulation_rows = model_->numberRowsAtContinuous(); info2->inTree = node != NULL; info2->randomNumberGenerator = randomNumberGenerator; generator->generateCutsAndModify(*solver, cs, info2); doCuts = true; } else if (depth) { /* The idea behind this is that probing may work in a different way deep in tree. So every now and then try various combinations to see what works. */ #define TRY_NOW_AND_THEN #ifdef TRY_NOW_AND_THEN if ((numberTimes_ == 200 || (numberTimes_ > 200 && (numberTimes_ % 2000) == 0)) && !model_->parentModel() && info.formulation_rows > 200) { /* In tree, every now and then try various combinations maxStack, maxProbe (last 5 digits) 123 is special and means CglProbing will try and be intelligent. */ int test[] = { 100123, 199999, 200123, 299999, 500123, 599999, 1000123, 1099999, 2000123, 2099999 }; int n = static_cast (sizeof(test) / sizeof(int)); int saveStack = generator->getMaxLook(); int saveNumber = generator->getMaxProbe(); int kr1 = 0; int kc1 = 0; int bestStackTree = -1; int bestNumberTree = -1; for (int i = 0; i < n; i++) { //OsiCuts cs2 = cs; int stack = test[i] / 100000; int number = test[i] - 100000 * stack; generator->setMaxLook(stack); generator->setMaxProbe(number); int numberRowCutsBefore = cs.sizeRowCuts() ; int numberColumnCutsBefore = cs.sizeColCuts() ; generator_->generateCuts(*solver, cs, info); int numberRowCuts = cs.sizeRowCuts() - numberRowCutsBefore ; int numberColumnCuts = cs.sizeColCuts() - numberColumnCutsBefore ; #ifdef CLP_INVESTIGATE if (numberRowCuts < kr1 || numberColumnCuts < kc1) printf("Odd "); #endif if (numberRowCuts > kr1 || numberColumnCuts > kc1) { #ifdef CLP_INVESTIGATE printf("*** "); #endif kr1 = numberRowCuts; kc1 = numberColumnCuts; bestStackTree = stack; bestNumberTree = number; doCuts = true; } #ifdef CLP_INVESTIGATE printf("maxStack %d number %d gives %d row cuts and %d column cuts\n", stack, number, numberRowCuts, numberColumnCuts); #endif } generator->setMaxLook(saveStack); generator->setMaxProbe(saveNumber); if (bestStackTree > 0) { generator->setMaxLook(bestStackTree); generator->setMaxProbe(bestNumberTree); #ifdef CLP_INVESTIGATE printf("RRNumber %d -> %d, stack %d -> %d\n", saveNumber, bestNumberTree, saveStack, bestStackTree); #endif } else { // no good generator->setMaxLook(0); #ifdef CLP_INVESTIGATE printf("RRSwitching off number %d -> %d, stack %d -> %d\n", saveNumber, saveNumber, saveStack, 1); #endif } } #endif if (generator->getMaxLook() > 0 && !doCuts) { generator->generateCutsAndModify(*solver, cs, &info); doCuts = true; } } else { // at root - don't always do if (pass < 15 || (pass&1) == 0) { generator->generateCutsAndModify(*solver, cs, &info); doCuts = true; } } if (doCuts && generator->tightLower()) { // probing may have tightened bounds - check const double * tightLower = generator->tightLower(); const double * lower = solver->getColLower(); const double * tightUpper = generator->tightUpper(); const double * upper = solver->getColUpper(); const double * solution = solver->getColSolution(); int j; int numberColumns = solver->getNumCols(); double primalTolerance = 1.0e-8; const char * tightenBounds = generator->tightenBounds(); #ifdef CGL_DEBUG const OsiRowCutDebugger * debugger = solver->getRowCutDebugger(); if (debugger && debugger->onOptimalPath(*solver)) { printf("On optimal path CbcCut\n"); int nCols = solver->getNumCols(); int i; const double * optimal = debugger->optimalSolution(); const double * objective = solver->getObjCoefficients(); double objval1 = 0.0, objval2 = 0.0; for (i = 0; i < nCols; i++) { #if CGL_DEBUG>1 printf("%d %g %g %g %g\n", i, lower[i], solution[i], upper[i], optimal[i]); #endif objval1 += solution[i] * objective[i]; objval2 += optimal[i] * objective[i]; assert(optimal[i] >= lower[i] - 1.0e-5 && optimal[i] <= upper[i] + 1.0e-5); assert(optimal[i] >= tightLower[i] - 1.0e-5 && optimal[i] <= tightUpper[i] + 1.0e-5); } printf("current obj %g, integer %g\n", objval1, objval2); } #endif bool feasible = true; if ((model_->getThreadMode()&2) == 0) { for (j = 0; j < numberColumns; j++) { if (solver->isInteger(j)) { if (tightUpper[j] < upper[j]) { double nearest = floor(tightUpper[j] + 0.5); //assert (fabs(tightUpper[j]-nearest)<1.0e-5); may be infeasible solver->setColUpper(j, nearest); if (nearest < solution[j] - primalTolerance) returnCode = true; } if (tightLower[j] > lower[j]) { double nearest = floor(tightLower[j] + 0.5); //assert (fabs(tightLower[j]-nearest)<1.0e-5); may be infeasible solver->setColLower(j, nearest); if (nearest > solution[j] + primalTolerance) returnCode = true; } } else { if (upper[j] > lower[j]) { if (tightUpper[j] == tightLower[j]) { // fix //if (tightLower[j]!=lower[j]) solver->setColLower(j, tightLower[j]); //if (tightUpper[j]!=upper[j]) solver->setColUpper(j, tightUpper[j]); if (tightLower[j] > solution[j] + primalTolerance || tightUpper[j] < solution[j] - primalTolerance) returnCode = true; } else if (tightenBounds && tightenBounds[j]) { solver->setColLower(j, CoinMax(tightLower[j], lower[j])); solver->setColUpper(j, CoinMin(tightUpper[j], upper[j])); if (tightLower[j] > solution[j] + primalTolerance || tightUpper[j] < solution[j] - primalTolerance) returnCode = true; } } } if (upper[j] < lower[j] - 1.0e-3) { feasible = false; break; } } } else { CoinPackedVector lbs; CoinPackedVector ubs; int numberChanged = 0; bool ifCut = false; for (j = 0; j < numberColumns; j++) { if (solver->isInteger(j)) { if (tightUpper[j] < upper[j]) { double nearest = floor(tightUpper[j] + 0.5); //assert (fabs(tightUpper[j]-nearest)<1.0e-5); may be infeasible ubs.insert(j, nearest); numberChanged++; if (nearest < solution[j] - primalTolerance) ifCut = true; } if (tightLower[j] > lower[j]) { double nearest = floor(tightLower[j] + 0.5); //assert (fabs(tightLower[j]-nearest)<1.0e-5); may be infeasible lbs.insert(j, nearest); numberChanged++; if (nearest > solution[j] + primalTolerance) ifCut = true; } } else { if (upper[j] > lower[j]) { if (tightUpper[j] == tightLower[j]) { // fix lbs.insert(j, tightLower[j]); ubs.insert(j, tightUpper[j]); if (tightLower[j] > solution[j] + primalTolerance || tightUpper[j] < solution[j] - primalTolerance) ifCut = true; } else if (tightenBounds && tightenBounds[j]) { lbs.insert(j, CoinMax(tightLower[j], lower[j])); ubs.insert(j, CoinMin(tightUpper[j], upper[j])); if (tightLower[j] > solution[j] + primalTolerance || tightUpper[j] < solution[j] - primalTolerance) ifCut = true; } } } if (upper[j] < lower[j] - 1.0e-3) { feasible = false; break; } } if (numberChanged) { OsiColCut cc; cc.setUbs(ubs); cc.setLbs(lbs); if (ifCut) { cc.setEffectiveness(100.0); } else { cc.setEffectiveness(1.0e-5); } cs.insert(cc); } } if (!feasible) { // not feasible -add infeasible cut OsiRowCut rc; rc.setLb(COIN_DBL_MAX); rc.setUb(0.0); cs.insert(rc); } } //if (!solver->basisIsAvailable()) //returnCode=true; if (!returnCode) { // bounds changed but still optimal #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver); if (clpSolver) { clpSolver->setLastAlgorithm(2); } #endif } #ifdef JJF_ZERO // Pass across info to pseudocosts char * mark = new char[numberColumns]; memset(mark, 0, numberColumns); int nLook = generator->numberThisTime(); const int * lookedAt = generator->lookedAt(); const int * fixedDown = generator->fixedDown(); const int * fixedUp = generator->fixedUp(); for (j = 0; j < nLook; j++) mark[lookedAt[j]] = 1; int numberObjects = model_->numberObjects(); for (int i = 0; i < numberObjects; i++) { CbcSimpleIntegerDynamicPseudoCost * obj1 = dynamic_cast (model_->modifiableObject(i)) ; if (obj1) { int iColumn = obj1->columnNumber(); if (mark[iColumn]) obj1->setProbingInformation(fixedDown[iColumn], fixedUp[iColumn]); } } delete [] mark; #endif } CbcCutModifier * modifier = model_->cutModifier(); if (modifier) { int numberRowCutsAfter = cs.sizeRowCuts() ; int k ; int nOdd = 0; //const OsiSolverInterface * solver = model_->solver(); for (k = numberRowCutsAfter - 1; k >= numberRowCutsBefore; k--) { OsiRowCut & thisCut = cs.rowCut(k) ; int returnCode = modifier->modify(solver, thisCut); if (returnCode) { nOdd++; if (returnCode == 3) cs.eraseRowCut(k); } } if (nOdd) COIN_DETAIL_PRINT(printf("Cut generator %s produced %d cuts of which %d were modified\n", generatorName_, numberRowCutsAfter - numberRowCutsBefore, nOdd)); } { // make all row cuts without test for duplicate int numberRowCutsAfter = cs.sizeRowCuts() ; int k ; #ifdef CGL_DEBUG const OsiRowCutDebugger * debugger = solver->getRowCutDebugger(); #endif for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { OsiRowCut * thisCut = cs.rowCutPtr(k) ; #ifdef CGL_DEBUG if (debugger && debugger->onOptimalPath(*solver)) assert(!debugger->invalidCut(*thisCut)); #endif thisCut->mutableRow().setTestForDuplicateIndex(false); } } // Add in saved cuts if violated if (false && !depth) { const double * solution = solver->getColSolution(); double primalTolerance = 1.0e-7; int numberCuts = savedCuts_.sizeRowCuts() ; for (int k = numberCuts - 1; k >= 0; k--) { const OsiRowCut * thisCut = savedCuts_.rowCutPtr(k) ; double sum = 0.0; int n = thisCut->row().getNumElements(); const int * column = thisCut->row().getIndices(); const double * element = thisCut->row().getElements(); assert (n); for (int i = 0; i < n; i++) { double value = element[i]; sum += value * solution[column[i]]; } if (sum > thisCut->ub() + primalTolerance) { sum = sum - thisCut->ub(); } else if (sum < thisCut->lb() - primalTolerance) { sum = thisCut->lb() - sum; } else { sum = 0.0; } if (sum) { // add to candidates and take out here cs.insert(*thisCut); savedCuts_.eraseRowCut(k); } } } if (!atSolution()) { int numberRowCutsAfter = cs.sizeRowCuts() ; int k ; int nEls = 0; int nCuts = numberRowCutsAfter - numberRowCutsBefore; // Remove NULL cuts! int nNull = 0; const double * solution = solver->getColSolution(); bool feasible = true; double primalTolerance = 1.0e-7; int shortCut = (depth) ? -1 : generator_->maximumLengthOfCutInTree(); for (k = numberRowCutsAfter - 1; k >= numberRowCutsBefore; k--) { const OsiRowCut * thisCut = cs.rowCutPtr(k) ; double sum = 0.0; if (thisCut->lb() <= thisCut->ub()) { int n = thisCut->row().getNumElements(); if (n <= shortCut) numberShortCutsAtRoot_++; const int * column = thisCut->row().getIndices(); const double * element = thisCut->row().getElements(); if (n <= 0) { // infeasible cut - give up feasible = false; break; } nEls += n; for (int i = 0; i < n; i++) { double value = element[i]; sum += value * solution[column[i]]; } if (sum > thisCut->ub() + primalTolerance) { sum = sum - thisCut->ub(); } else if (sum < thisCut->lb() - primalTolerance) { sum = thisCut->lb() - sum; } else { sum = 0.0; cs.eraseRowCut(k); nNull++; } } } //if (nNull) //printf("%s has %d cuts and %d elements - %d null!\n",generatorName_, // nCuts,nEls,nNull); numberRowCutsAfter = cs.sizeRowCuts() ; nCuts = numberRowCutsAfter - numberRowCutsBefore; nEls = 0; for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { const OsiRowCut * thisCut = cs.rowCutPtr(k) ; int n = thisCut->row().getNumElements(); nEls += n; } //printf("%s has %d cuts and %d elements\n",generatorName_, // nCuts,nEls); int nElsNow = solver->getMatrixByCol()->getNumElements(); int numberColumns = solver->getNumCols(); int numberRows = solver->getNumRows(); //double averagePerRow = static_cast(nElsNow)/ //static_cast(numberRows); int nAdd; int nAdd2; int nReasonable; if (!model_->parentModel() && depth < 2) { if (inaccuracy_ < 3) { nAdd = 10000; if (pass > 0 && numberColumns > -500) nAdd = CoinMin(nAdd, nElsNow + 2 * numberRows); } else { nAdd = 10000; if (pass > 0) nAdd = CoinMin(nAdd, nElsNow + 2 * numberRows); } nAdd2 = 5 * numberColumns; nReasonable = CoinMax(nAdd2, nElsNow / 8 + nAdd); if (!depth && !pass) { // allow more nAdd += nElsNow / 2; nAdd2 += nElsNow / 2; nReasonable += nElsNow / 2; } //if (!depth&&ineffectualCuts()) //nReasonable *= 2; } else { nAdd = 200; nAdd2 = 2 * numberColumns; nReasonable = CoinMax(nAdd2, nElsNow / 8 + nAdd); } //#define UNS_WEIGHT 0.1 #ifdef UNS_WEIGHT const double * colLower = solver->getColLower(); const double * colUpper = solver->getColUpper(); #endif if (/*nEls>CoinMax(nAdd2,nElsNow/8+nAdd)*/nCuts && feasible) { //printf("need to remove cuts\n"); // just add most effective #ifndef JJF_ONE int nDelete = nEls - nReasonable; nElsNow = nEls; double * sort = new double [nCuts]; int * which = new int [nCuts]; // For parallel cuts double * element2 = new double [numberColumns]; //#define USE_OBJECTIVE 2 #ifdef USE_OBJECTIVE const double *objective = solver->getObjCoefficients() ; #if USE_OBJECTIVE>1 double objNorm = 0.0; for (int i = 0; i < numberColumns; i++) objNorm += objective[i] * objective[i]; if (objNorm) objNorm = 1.0 / sqrt(objNorm); else objNorm = 1.0; objNorm *= 0.01; // downgrade #endif #endif CoinZeroN(element2, numberColumns); for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { const OsiRowCut * thisCut = cs.rowCutPtr(k) ; double sum = 0.0; if (thisCut->lb() <= thisCut->ub()) { int n = thisCut->row().getNumElements(); const int * column = thisCut->row().getIndices(); const double * element = thisCut->row().getElements(); assert (n); #ifdef UNS_WEIGHT double normU = 0.0; double norm = 1.0e-3; int nU = 0; for (int i = 0; i < n; i++) { double value = element[i]; int iColumn = column[i]; double solValue = solution[iColumn]; sum += value * solValue; value *= value; norm += value; if (solValue > colLower[iColumn] + 1.0e-6 && solValue < colUpper[iColumn] - 1.0e-6) { normU += value; nU++; } } #ifdef JJF_ZERO int nS = n - nU; if (numberColumns > 20000) { if (nS > 50) { double ratio = 50.0 / nS; normU /= ratio; } } #endif norm += UNS_WEIGHT * (normU - norm); #else double norm = 1.0e-3; #ifdef USE_OBJECTIVE double obj = 0.0; #endif for (int i = 0; i < n; i++) { int iColumn = column[i]; double value = element[i]; sum += value * solution[iColumn]; norm += value * value; #ifdef USE_OBJECTIVE obj += value * objective[iColumn]; #endif } #endif if (sum > thisCut->ub()) { sum = sum - thisCut->ub(); } else if (sum < thisCut->lb()) { sum = thisCut->lb() - sum; } else { sum = 0.0; } #ifdef USE_OBJECTIVE if (sum) { #if USE_OBJECTIVE==1 obj = CoinMax(1.0e-6, fabs(obj)); norm = sqrt(obj * norm); //sum += fabs(obj)*invObjNorm; //printf("sum %g norm %g normobj %g invNorm %g mod %g\n", // sum,norm,obj,invObjNorm,obj*invObjNorm); // normalize sum /= sqrt(norm); #else // normalize norm = 1.0 / sqrt(norm); sum = (sum + objNorm * obj) * norm; #endif } #else // normalize sum /= sqrt(norm); #endif //sum /= pow(norm,0.3); // adjust for length //sum /= pow(reinterpret_cast(n),0.2); //sum /= sqrt((double) n); // randomize //double randomNumber = //model_->randomNumberGenerator()->randomDouble(); //sum *= (0.5+randomNumber); } else { // keep sum = COIN_DBL_MAX; } sort[k-numberRowCutsBefore] = sum; which[k-numberRowCutsBefore] = k; } CoinSort_2(sort, sort + nCuts, which); // Now see which ones are too similar int nParallel = 0; double testValue = (depth > 1) ? 0.99 : 0.999999; for (k = 0; k < nCuts; k++) { int j = which[k]; const OsiRowCut * thisCut = cs.rowCutPtr(j) ; if (thisCut->lb() > thisCut->ub()) break; // cut is infeasible int n = thisCut->row().getNumElements(); const int * column = thisCut->row().getIndices(); const double * element = thisCut->row().getElements(); assert (n); double norm = 0.0; double lb = thisCut->lb(); double ub = thisCut->ub(); for (int i = 0; i < n; i++) { double value = element[i]; element2[column[i]] = value; norm += value * value; } int kkk = CoinMin(nCuts, k + 5); for (int kk = k + 1; kk < kkk; kk++) { int jj = which[kk]; const OsiRowCut * thisCut2 = cs.rowCutPtr(jj) ; if (thisCut2->lb() > thisCut2->ub()) break; // cut is infeasible int nB = thisCut2->row().getNumElements(); const int * columnB = thisCut2->row().getIndices(); const double * elementB = thisCut2->row().getElements(); assert (nB); double normB = 0.0; double product = 0.0; for (int i = 0; i < nB; i++) { double value = elementB[i]; normB += value * value; product += value * element2[columnB[i]]; } if (product > 0.0 && product*product > testValue*norm*normB) { bool parallel = true; double lbB = thisCut2->lb(); double ubB = thisCut2->ub(); if ((lb < -1.0e20 && lbB > -1.0e20) || (lbB < -1.0e20 && lb > -1.0e20)) parallel = false; double tolerance; tolerance = CoinMax(fabs(lb), fabs(lbB)) + 1.0e-6; if (fabs(lb - lbB) > tolerance) parallel = false; if ((ub > 1.0e20 && ubB < 1.0e20) || (ubB > 1.0e20 && ub < 1.0e20)) parallel = false; tolerance = CoinMax(fabs(ub), fabs(ubB)) + 1.0e-6; if (fabs(ub - ubB) > tolerance) parallel = false; if (parallel) { nParallel++; sort[k] = 0.0; break; } } } for (int i = 0; i < n; i++) { element2[column[i]] = 0.0; } } delete [] element2; CoinSort_2(sort, sort + nCuts, which); k = 0; while (nDelete > 0 || !sort[k]) { int iCut = which[k]; const OsiRowCut * thisCut = cs.rowCutPtr(iCut) ; int n = thisCut->row().getNumElements(); // may be best, just to save if short if (false && n && sort[k]) { // add to saved cuts savedCuts_.insert(*thisCut); } nDelete -= n; k++; if (k >= nCuts) break; } std::sort(which, which + k); k--; for (; k >= 0; k--) { cs.eraseRowCut(which[k]); } delete [] sort; delete [] which; numberRowCutsAfter = cs.sizeRowCuts() ; #else double * norm = new double [nCuts]; int * which = new int [2*nCuts]; double * score = new double [nCuts]; double * ortho = new double [nCuts]; int nIn = 0; int nOut = nCuts; // For parallel cuts double * element2 = new double [numberColumns]; const double *objective = solver->getObjCoefficients() ; double objNorm = 0.0; for (int i = 0; i < numberColumns; i++) objNorm += objective[i] * objective[i]; if (objNorm) objNorm = 1.0 / sqrt(objNorm); else objNorm = 1.0; objNorm *= 0.1; // weight of 0.1 CoinZeroN(element2, numberColumns); int numberRowCuts = numberRowCutsAfter - numberRowCutsBefore; int iBest = -1; double best = 0.0; int nPossible = 0; double testValue = (depth > 1) ? 0.7 : 0.5; for (k = 0; k < numberRowCuts; k++) { const OsiRowCut * thisCut = cs.rowCutPtr(k + numberRowCutsBefore) ; double sum = 0.0; if (thisCut->lb() <= thisCut->ub()) { int n = thisCut->row().getNumElements(); const int * column = thisCut->row().getIndices(); const double * element = thisCut->row().getElements(); assert (n); double normThis = 1.0e-6; double obj = 0.0; for (int i = 0; i < n; i++) { int iColumn = column[i]; double value = element[i]; sum += value * solution[iColumn]; normThis += value * value; obj += value * objective[iColumn]; } if (sum > thisCut->ub()) { sum = sum - thisCut->ub(); } else if (sum < thisCut->lb()) { sum = thisCut->lb() - sum; } else { sum = 0.0; } if (sum) { normThis = 1.0 / sqrt(normThis); norm[k] = normThis; sum *= normThis; obj *= normThis; score[k] = sum + obj * objNorm; ortho[k] = 1.0; } } else { // keep and discard others nIn = 1; which[0] = k; for (int j = 0; j < numberRowCuts; j++) { if (j != k) which[nOut++] = j; } iBest = -1; break; } if (sum) { if (score[k] > best) { best = score[k]; iBest = nPossible; } which[nPossible++] = k; } else { which[nOut++] = k; } } while (iBest >= 0) { int kBest = which[iBest]; int j = which[nIn]; which[iBest] = j; which[nIn++] = kBest; const OsiRowCut * thisCut = cs.rowCutPtr(kBest + numberRowCutsBefore) ; int n = thisCut->row().getNumElements(); nReasonable -= n; if (nReasonable <= 0) { for (k = nIn; k < nPossible; k++) which[nOut++] = which[k]; break; } // Now see which ones are too similar and choose next iBest = -1; best = 0.0; int nOld = nPossible; nPossible = nIn; const int * column = thisCut->row().getIndices(); const double * element = thisCut->row().getElements(); assert (n); double normNew = norm[kBest]; for (int i = 0; i < n; i++) { double value = element[i]; element2[column[i]] = value; } for (int j = nIn; j < nOld; j++) { k = which[j]; const OsiRowCut * thisCut2 = cs.rowCutPtr(k + numberRowCutsBefore) ; int nB = thisCut2->row().getNumElements(); const int * columnB = thisCut2->row().getIndices(); const double * elementB = thisCut2->row().getElements(); assert (nB); double normB = norm[k]; double product = 0.0; for (int i = 0; i < nB; i++) { double value = elementB[i]; product += value * element2[columnB[i]]; } double orthoScore = 1.0 - product * normNew * normB; if (orthoScore >= testValue) { ortho[k] = CoinMin(orthoScore, ortho[k]); double test = score[k] + ortho[k]; if (test > best) { best = score[k]; iBest = nPossible; } which[nPossible++] = k; } else { which[nOut++] = k; } } for (int i = 0; i < n; i++) { element2[column[i]] = 0.0; } } delete [] score; delete [] ortho; std::sort(which + nCuts, which + nOut); k = nOut - 1; for (; k >= nCuts; k--) { cs.eraseRowCut(which[k] + numberRowCutsBefore); } delete [] norm; delete [] which; numberRowCutsAfter = cs.sizeRowCuts() ; #endif } } #ifdef CBC_DEBUG { int numberRowCutsAfter = cs.sizeRowCuts() ; int k ; int nBad = 0; for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { OsiRowCut thisCut = cs.rowCut(k) ; if (thisCut.lb() > thisCut.ub() || thisCut.lb() > 1.0e8 || thisCut.ub() < -1.0e8) printf("cut from %s has bounds %g and %g!\n", generatorName_, thisCut.lb(), thisCut.ub()); if (thisCut.lb() <= thisCut.ub()) { /* check size of elements. We can allow smaller but this helps debug generators as it is unsafe to have small elements */ int n = thisCut.row().getNumElements(); const int * column = thisCut.row().getIndices(); const double * element = thisCut.row().getElements(); assert (n); for (int i = 0; i < n; i++) { double value = element[i]; if (fabs(value) <= 1.0e-12 || fabs(value) >= 1.0e20) nBad++; } } if (nBad) printf("Cut generator %s produced %d cuts of which %d had tiny or large elements\n", generatorName_, numberRowCutsAfter - numberRowCutsBefore, nBad); } } #endif int numberRowCutsAfter = cs.sizeRowCuts() ; int numberColumnCutsAfter = cs.sizeColCuts() ; if (numberRowCutsBefore < numberRowCutsAfter) { for (int k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { OsiRowCut thisCut = cs.rowCut(k) ; int n = thisCut.row().getNumElements(); numberElements_ += n; } #ifdef JJF_ZERO printf("generator %s generated %d row cuts\n", generatorName_, numberRowCutsAfter - numberRowCutsBefore); #endif numberCuts_ += numberRowCutsAfter - numberRowCutsBefore; } if (numberColumnCutsBefore < numberColumnCutsAfter) { #ifdef JJF_ZERO printf("generator %s generated %d column cuts\n", generatorName_, numberColumnCutsAfter - numberColumnCutsBefore); #endif numberColumnCuts_ += numberColumnCutsAfter - numberColumnCutsBefore; } if (timing()) timeInCutGenerator_ += CoinCpuTime() - time1; // switch off if first time and no good if (node == NULL && !pass ) { if (numberRowCutsAfter - numberRowCutsBefore < switchOffIfLessThan_ /*&& numberCuts_ < switchOffIfLessThan_*/) { // switch off maximumTries_ = 0; whenCutGenerator_=-100; //whenCutGenerator_ = -100; //whenCutGeneratorInSub_ = -200; } } if (maximumTries_>0) { maximumTries_--; if (!maximumTries_) whenCutGenerator_=-100; } } return returnCode; } void CbcCutGenerator::setHowOften(int howOften) { if (howOften >= 1000000) { // leave Probing every SCANCUTS_PROBING howOften = howOften % 1000000; CglProbing* generator = dynamic_cast(generator_); if (generator && howOften > SCANCUTS_PROBING) howOften = SCANCUTS_PROBING + 1000000; else howOften += 1000000; } whenCutGenerator_ = howOften; } void CbcCutGenerator::setWhatDepth(int value) { depthCutGenerator_ = value; } void CbcCutGenerator::setWhatDepthInSub(int value) { depthCutGeneratorInSub_ = value; } // Add in statistics from other void CbcCutGenerator::addStatistics(const CbcCutGenerator * other) { // Time in cut generator timeInCutGenerator_ += other->timeInCutGenerator_; // Number times cut generator entered numberTimes_ += other->numberTimes_; // Total number of cuts added numberCuts_ += other->numberCuts_; // Total number of elements added numberElements_ += other->numberElements_; // Total number of column cuts added numberColumnCuts_ += other->numberColumnCuts_; // Total number of cuts active after (at end of n cut passes at each node) numberCutsActive_ += other->numberCutsActive_; // Number of cuts generated at root numberCutsAtRoot_ += other->numberCutsAtRoot_; // Number of cuts active at root numberActiveCutsAtRoot_ += other->numberActiveCutsAtRoot_; // Number of short cuts at root numberShortCutsAtRoot_ += other->numberShortCutsAtRoot_; } // Scale back statistics by factor void CbcCutGenerator::scaleBackStatistics(int factor) { // leave time // Number times cut generator entered numberTimes_ = (numberTimes_+factor-1)/factor; // Total number of cuts added numberCuts_ = (numberCuts_+factor-1)/factor; // Total number of elements added numberElements_ = (numberElements_+factor-1)/factor; // Total number of column cuts added numberColumnCuts_ = (numberColumnCuts_+factor-1)/factor; // Total number of cuts active after (at end of n cut passes at each node) numberCutsActive_ = (numberCutsActive_+factor-1)/factor; // Number of cuts generated at root numberCutsAtRoot_ = (numberCutsAtRoot_+factor-1)/factor; // Number of cuts active at root numberActiveCutsAtRoot_ = (numberActiveCutsAtRoot_+factor-1)/factor; // Number of short cuts at root numberShortCutsAtRoot_ = (numberShortCutsAtRoot_+factor-1)/factor; } // Create C++ lines to get to current state void CbcCutGenerator::generateTuning( FILE * fp) { fprintf(fp, "// Cbc tuning for generator %s\n", generatorName_); fprintf(fp, " generator->setHowOften(%d);\n", whenCutGenerator_); fprintf(fp, " generator->setSwitchOffIfLessThan(%d);\n", switchOffIfLessThan_); fprintf(fp, " generator->setWhatDepth(%d);\n", depthCutGenerator_); fprintf(fp, " generator->setInaccuracy(%d);\n", inaccuracy_); if (timing()) fprintf(fp, " generator->setTiming(true);\n"); if (normal()) fprintf(fp, " generator->setNormal(true);\n"); if (atSolution()) fprintf(fp, " generator->setAtSolution(true);\n"); if (whenInfeasible()) fprintf(fp, " generator->setWhenInfeasible(true);\n"); if (needsOptimalBasis()) fprintf(fp, " generator->setNeedsOptimalBasis(true);\n"); if (mustCallAgain()) fprintf(fp, " generator->setMustCallAgain(true);\n"); if (whetherToUse()) fprintf(fp, " generator->setWhetherToUse(true);\n"); } Cbc-2.8.12/src/CbcSolver.hpp0000644000076600007660000003006412265247303014142 0ustar coincoin/* $Id: CbcSolver.hpp 2004 2014-01-14 14:50:43Z forrest $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /*! \file CbcSolver.hpp \brief Defines CbcSolver, the proposed top-level class for the new-style cbc solver. This class is currently an orphan. With the removal of all code flagged with the NEW_STYLE_SOLVER, this class is never instantiated (and cannot be instantiated). It is available to be coopted as a top-level object wrapping the current CbcMain0 and CbcMain1, should that appear to be a desireable path forward. -- lh, 091211 -- */ #ifndef CbcSolver_H #define CbcSolver_H #include #include #include "CoinMessageHandler.hpp" #include "OsiClpSolverInterface.hpp" #if CBC_OTHER_SOLVER==1 #include "OsiCpxSolverInterface.hpp" #endif #include "CbcModel.hpp" #include "CbcOrClpParam.hpp" class CbcUser; class CbcStopNow; class CglCutGenerator; //############################################################################# /*! \brief This allows the use of the standalone solver in a flexible manner. It has an original OsiClpSolverInterface and CbcModel which it can use repeatedly, e.g., to get a heuristic solution and then start again. So I [jjf] will need a primitive scripting language which can then call solve and manipulate solution value and solution arrays. Also provides for user callback functions. Currently two ideas in gestation, CbcUser and CbcStopNow. The latter seems limited to deciding whether or not to stop. The former seems completely general, with a notion of importing and exporting, and a `solve', which should be interpreted as `do whatever this user function does'. Parameter initialisation is at last centralised in fillParameters(). */ class CbcSolver { public: ///@name Solve method //@{ /** This takes a list of commands, does "stuff" and returns returnMode - 0 model and solver untouched - babModel updated 1 model updated - just with solution basis etc 2 model updated i.e. as babModel (babModel NULL) (only use without preprocessing) */ int solve(int argc, const char * argv[], int returnMode); /** This takes a list of commands, does "stuff" and returns returnMode - 0 model and solver untouched - babModel updated 1 model updated - just with solution basis etc 2 model updated i.e. as babModel (babModel NULL) (only use without preprocessing) */ int solve(const char * input, int returnMode); //@} ///@name Constructors and destructors etc //@{ /// Default Constructor CbcSolver(); /// Constructor from solver CbcSolver(const OsiClpSolverInterface &); /// Constructor from model CbcSolver(const CbcModel &); /** Copy constructor . */ CbcSolver(const CbcSolver & rhs); /// Assignment operator CbcSolver & operator=(const CbcSolver& rhs); /// Destructor ~CbcSolver (); /// Fill with standard parameters void fillParameters(); /*! \brief Set default values in solvers from parameters Misleading. The current code actually reads default values from the underlying solvers and installs them as default values for a subset of parameters in #parameters_. */ void fillValuesInSolver(); /// Add user function void addUserFunction(CbcUser * function); /// Set user call back void setUserCallBack(CbcStopNow * function); /// Add cut generator void addCutGenerator(CglCutGenerator * generator); //@} ///@name miscellaneous methods to line up with old //@{ // analyze model int * analyze(OsiClpSolverInterface * solverMod, int & numberChanged, double & increment, bool changeInt, CoinMessageHandler * generalMessageHandler); /** 1 - add heuristics to model 2 - do heuristics (and set cutoff and best solution) 3 - for miplib test so skip some (out model later) */ //int doHeuristics(CbcModel * model, int type); /** Updates model_ from babModel_ according to returnMode returnMode - 0 model and solver untouched - babModel updated 1 model updated - just with solution basis etc 2 model updated i.e. as babModel (babModel NULL) (only use without preprocessing) */ void updateModel(ClpSimplex * model2, int returnMode); //@} ///@name useful stuff //@{ /// Get int value int intValue(CbcOrClpParameterType type) const; /// Set int value void setIntValue(CbcOrClpParameterType type, int value); /// Get double value double doubleValue(CbcOrClpParameterType type) const; /// Set double value void setDoubleValue(CbcOrClpParameterType type, double value); /// User function (NULL if no match) CbcUser * userFunction(const char * name) const; /// Return original Cbc model inline CbcModel * model() { return &model_; } /// Return updated Cbc model inline CbcModel * babModel() { return babModel_; } /// Number of userFunctions inline int numberUserFunctions() const { return numberUserFunctions_; } /// User function array inline CbcUser ** userFunctionArray() const { return userFunction_; } /// Copy of model on initial load (will contain output solutions) inline OsiClpSolverInterface * originalSolver() const { return originalSolver_; } /// Copy of model on initial load inline CoinModel * originalCoinModel() const { return originalCoinModel_; } /// Copy of model on initial load (will contain output solutions) void setOriginalSolver(OsiClpSolverInterface * originalSolver); /// Copy of model on initial load void setOriginalCoinModel(CoinModel * originalCoinModel); /// Number of cutgenerators inline int numberCutGenerators() const { return numberCutGenerators_; } /// Cut generator array inline CglCutGenerator ** cutGeneratorArray() const { return cutGenerator_; } /// Start time inline double startTime() const { return startTime_; } /// Whether to print to std::cout inline void setPrinting(bool onOff) { noPrinting_ = !onOff; } /// Where to start reading commands inline void setReadMode(int value) { readMode_ = value; } //@} private: ///@name Private member data //@{ /// Reference model CbcModel model_; /// Updated model CbcModel * babModel_; /// User functions CbcUser ** userFunction_; /** Status of user functions 0 - not used 1 - needs cbc_load 2 - available - data in coinModel 3 - data loaded - can do cbc_save */ int * statusUserFunction_; /// Copy of model on initial load (will contain output solutions) OsiClpSolverInterface * originalSolver_; /// Copy of model on initial load CoinModel * originalCoinModel_; /// Cut generators CglCutGenerator ** cutGenerator_; /// Number of user functions int numberUserFunctions_; /// Number of cut generators int numberCutGenerators_; /// Stop now stuff CbcStopNow * callBack_; /// Cpu time at instantiation double startTime_; /// Parameters and values CbcOrClpParam * parameters_; /// Number of parameters int numberParameters_ ; /// Whether to do miplib test bool doMiplib_; /// Whether to print to std::cout bool noPrinting_; /// Where to start reading commands int readMode_; //@} }; //############################################################################# /** The CbcSolver class was taken out at a 9/12/09 meeting This is a feeble replacement. At present everything is public */ class CbcSolverUsefulData { public: ///@name Constructors and destructors etc //@{ /// Default Constructor CbcSolverUsefulData(); /** Copy constructor . */ CbcSolverUsefulData(const CbcSolverUsefulData & rhs); /// Assignment operator CbcSolverUsefulData & operator=(const CbcSolverUsefulData& rhs); /// Destructor ~CbcSolverUsefulData (); //@} ///@name Member data //@{ // For time double totalTime_; // Parameters CbcOrClpParam parameters_[CBCMAXPARAMETERS]; // Printing bool noPrinting_; // Whether to use signal handler bool useSignalHandler_; // Number of Parameters int numberParameters_; // Default pump tuning int initialPumpTune_; //@} }; /// And this uses it // When we want to load up CbcModel with options first void CbcMain0 (CbcModel & babSolver,CbcSolverUsefulData & solverData); int CbcMain1 (int argc, const char *argv[], CbcModel & babSolver, int (CbcModel * currentSolver, int whereFrom),CbcSolverUsefulData & solverData); //############################################################################# /*! \brief A class to allow the use of unknown user functionality For example, access to a modelling language (CbcAmpl). */ class CbcUser { public: ///@name import/export methods //@{ /*! \brief Import - gets full command arguments \return - -1 - no action - 0 - data read in without error - 1 - errors */ virtual int importData(CbcSolver * /*model*/, int & /*argc*/, char ** /*argv[]*/) { return -1; } /*! \brief Export Values for mode: - 1 OsiClpSolver - 2 CbcModel - add 10 if infeasible from odd situation */ virtual void exportSolution(CbcSolver * /*model*/, int /*mode*/, const char * /*message*/ = NULL) {} /// Export Data (i.e. at very end) virtual void exportData(CbcSolver * /*model*/) {} /// Get useful stuff virtual void fillInformation(CbcSolver * /*model*/, CbcSolverUsefulData & /*info*/) {} //@} ///@name usage methods //@{ /// CoinModel if valid inline CoinModel *coinModel() const { return coinModel_; } /// Other info - needs expanding virtual void * stuff() { return NULL; } /// Name inline std::string name() const { return userName_; } /// Solve (whatever that means) virtual void solve(CbcSolver * model, const char * options) = 0; /// Returns true if function knows about option virtual bool canDo(const char * options) = 0; //@} ///@name Constructors and destructors etc //@{ /// Default Constructor CbcUser(); /// Copy constructor CbcUser(const CbcUser & rhs); /// Assignment operator CbcUser & operator=(const CbcUser& rhs); /// Clone virtual CbcUser * clone() const = 0; /// Destructor virtual ~CbcUser (); //@} protected: ///@name Private member data //@{ /// CoinModel CoinModel * coinModel_; /// Name of user function std::string userName_; //@} }; //############################################################################# /*! \brief Support the use of a call back class to decide whether to stop Definitely under construction. */ class CbcStopNow { public: ///@name Decision methods //@{ /*! \brief Import Values for whereFrom: - 1 after initial solve by dualsimplex etc - 2 after preprocessing - 3 just before branchAndBound (so user can override) - 4 just after branchAndBound (before postprocessing) - 5 after postprocessing - 6 after a user called heuristic phase \return 0 if good nonzero return code to stop */ virtual int callBack(CbcModel * /*currentSolver*/, int /*whereFrom*/) { return 0; } //@} ///@name Constructors and destructors etc //@{ /// Default Constructor CbcStopNow(); /** Copy constructor . */ CbcStopNow(const CbcStopNow & rhs); /// Assignment operator CbcStopNow & operator=(const CbcStopNow& rhs); /// Clone virtual CbcStopNow * clone() const; /// Destructor virtual ~CbcStopNow (); //@} private: ///@name Private member data //@{ //@} }; #endif Cbc-2.8.12/src/CbcHeuristicDiveVectorLength.cpp0000644000076600007660000000770612131315050017751 0ustar coincoin/* $Id: CbcHeuristicDiveVectorLength.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcHeuristicDiveVectorLength.hpp" #include "CbcStrategy.hpp" // Default Constructor CbcHeuristicDiveVectorLength::CbcHeuristicDiveVectorLength() : CbcHeuristicDive() { } // Constructor from model CbcHeuristicDiveVectorLength::CbcHeuristicDiveVectorLength(CbcModel & model) : CbcHeuristicDive(model) { } // Destructor CbcHeuristicDiveVectorLength::~CbcHeuristicDiveVectorLength () { } // Clone CbcHeuristicDiveVectorLength * CbcHeuristicDiveVectorLength::clone() const { return new CbcHeuristicDiveVectorLength(*this); } // Create C++ lines to get to current state void CbcHeuristicDiveVectorLength::generateCpp( FILE * fp) { CbcHeuristicDiveVectorLength other; fprintf(fp, "0#include \"CbcHeuristicDiveVectorLength.hpp\"\n"); fprintf(fp, "3 CbcHeuristicDiveVectorLength heuristicDiveVectorLength(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicDiveVectorLength"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicDiveVectorLength);\n"); } // Copy constructor CbcHeuristicDiveVectorLength::CbcHeuristicDiveVectorLength(const CbcHeuristicDiveVectorLength & rhs) : CbcHeuristicDive(rhs) { } // Assignment operator CbcHeuristicDiveVectorLength & CbcHeuristicDiveVectorLength::operator=( const CbcHeuristicDiveVectorLength & rhs) { if (this != &rhs) { CbcHeuristicDive::operator=(rhs); } return *this; } bool CbcHeuristicDiveVectorLength::selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound) { const double * objective = solver->getObjCoefficients(); double direction = solver->getObjSense(); // 1 for min, -1 for max const int * columnLength = matrix_.getVectorLengths(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); bestColumn = -1; bestRound = -1; // -1 rounds down, +1 rounds up double bestScore = COIN_DBL_MAX; bool allTriviallyRoundableSoFar = true; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; double fraction = value - floor(value); int round = 0; if (fabs(floor(value + 0.5) - value) > integerTolerance) { if (allTriviallyRoundableSoFar || (downLocks_[i] > 0 && upLocks_[i] > 0)) { if (allTriviallyRoundableSoFar && downLocks_[i] > 0 && upLocks_[i] > 0) { allTriviallyRoundableSoFar = false; bestScore = COIN_DBL_MAX; } // the variable cannot be rounded double obj = direction * objective[iColumn]; if (obj >= 0.0) round = 1; // round up else round = -1; // round down double objDelta; if (round == 1) objDelta = (1.0 - fraction) * obj; else objDelta = - fraction * obj; // we want the smaller score double score = objDelta / (static_cast (columnLength[iColumn]) + 1.0); // if variable is not binary, penalize it if (!solver->isBinary(iColumn)) score *= 1000.0; if (score < bestScore) { bestColumn = iColumn; bestScore = score; bestRound = round; } } } } return allTriviallyRoundableSoFar; } Cbc-2.8.12/src/CbcGenBaB.cpp0000644000076600007660000007460612131315050013736 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenBaB.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #include #include "CoinTime.hpp" #include "OsiSolverInterface.hpp" #include "OsiChooseVariable.hpp" #include "CglPreProcess.hpp" #include "CbcModel.hpp" #include "CbcCutGenerator.hpp" #include "CbcBranchActual.hpp" #include "CbcStrategy.hpp" #include "CbcGenCtlBlk.hpp" #include "CbcGenParam.hpp" #include "CbcGenCbcParam.hpp" #define CBC_TRACK_SOLVERS 1 // #define COIN_CBC_VERBOSITY 5 /* The support functions for the main branch-and-cut action routine. */ namespace { char svnid[] = "$Id: CbcGenBaB.cpp 1902 2013-04-10 16:58:16Z stefan $" ; /* A hack to fix variables based on reduced cost prior to branch-and-cut. Note that we're *not* looking at the integrality gap here. Given the reduced costs of the root relaxation, we're simply placing a bet that variables with really unfavourable reduced costs that are at their most favourable bound in the root relaxation will never move from that bound. For the standard OsiSolverInterface, this requires a bit of effort as the solution and bounds arrays are const and the functions to change them have incompatible interfaces. */ void reducedCostHack (OsiSolverInterface *osi, double threshold) { int numCols = osi->getNumCols() ; int i ; const double *lower = osi->getColLower() ; const double *upper = osi->getColUpper() ; const double *solution = osi->getColSolution() ; const double *dj = osi->getReducedCost() ; /* First task: scan the columns looking for variables that are at their favourable bound and have reduced cost that exceeds the threshold. Remember the column index and the value. */ double *chgBnds = new double [numCols] ; int *chgCols = new int [numCols] ; int numFixed = 0 ; for (i = 0 ; i < numCols ; i++) { if (osi->isInteger(i)) { double value = solution[i] ; if (value < lower[i] + 1.0e-5 && dj[i] > threshold) { chgCols[numFixed] = i ; chgBnds[numFixed] = lower[i] ; numFixed++ ; } else if (value > upper[i] - 1.0e-5 && dj[i] < -threshold) { chgCols[numFixed] = i ; chgBnds[numFixed] = upper[i] ; numFixed++ ; } } } /* Second task: For variables that we want to fix, we need to: * Prepare an array with the new lower and upper bounds for variables that will be fixed. setColSetBounds requires an array with column indices and an array with new values for both bounds. * Set the correct value in a copy of the current solution. setColSolution requires a complete solution. */ if (numFixed > 0) { double *newSoln = CoinCopyOfArray(solution, numCols) ; double *newBnds = new double [2*numFixed] ; double *bndPtr = &newBnds[0] ; for (i = 0 ; i < numFixed ; i++) { int j = chgCols[i] ; double val = chgBnds[i] ; *bndPtr++ = val ; *bndPtr++ = val ; newSoln[j] = val ; } osi->setColSetBounds(&chgCols[0], &chgCols[numFixed], &newBnds[0]) ; osi->setColSolution(&newSoln[0]) ; std::cout << "Reduced cost fixing prior to B&C: " << numFixed << " columns fixed." << std::endl ; delete[] newSoln ; delete[] newBnds ; } delete[] chgBnds ; delete[] chgCols ; return ; } /* Helper routine to solve a continuous relaxation and print something intelligent when the result is other than optimal. Returns true if the result is optimal, false otherwise. */ bool solveRelaxation (CbcModel *model) { OsiSolverInterface *osi = model->solver() ; model->initialSolve() ; if (!(osi->isProvenOptimal())) { bool reason = false ; if (osi->isProvenPrimalInfeasible()) { std::cout << "Continuous relaxation is primal infeasible." << std::endl ; reason = true ; } if (osi->isProvenDualInfeasible()) { std::cout << "Continuous relaxation is dual infeasible." << std::endl ; reason = true ; } if (osi->isIterationLimitReached()) { std::cout << "Continuous solver reached iteration limit." << std::endl ; reason = true ; } if (osi->isAbandoned()) { std::cout << "Continuous solver abandoned the problem." << std::endl ; reason = true ; } if (reason == false) { std::cout << "Continuous solver failed for unknown reason." << std::endl ; } return (false) ; } return (true) ; } /* Helper routine to establish a priority vector. */ void setupPriorities (CbcModel *model, CbcGenCtlBlk::BPControl how) { int numCols = model->getNumCols() ; int *sort = new int[numCols] ; double *dsort = new double[numCols] ; int *priority = new int[numCols] ; const double *objective = model->getObjCoefficients() ; int iColumn ; int n = 0 ; bool priorityOK = true ; for (iColumn = 0 ; iColumn < numCols ; iColumn++) { if (model->isInteger(iColumn)) { sort[n] = n ; if (how == CbcGenCtlBlk::BPCost) { dsort[n++] = -objective[iColumn] ; } else if (how == CbcGenCtlBlk::BPOrder) { dsort[n++] = iColumn ; } else { std::cerr << "setupPriorities: Unrecognised priority specification." << std::endl ; priorityOK = false ; } } } if (priorityOK) { CoinSort_2(dsort, dsort + n, sort) ; int level = 0 ; double last = -1.0e100 ; for (int i = 0 ; i < n ; i++) { int iPut = sort[i] ; if (dsort[i] != last) { level++ ; last = dsort[i] ; } priority[iPut] = level ; } model->passInPriorities(priority, false) ; } delete [] priority ; delete [] sort ; delete [] dsort ; return ; } /* Helper routine to install a batch of heuristics. Each call to getXXXHeuristic will return a pointer to the heuristic object in gen iff the heuristic is enabled. */ void installHeuristics (CbcGenCtlBlk *ctlBlk, CbcModel *model) { CbcGenCtlBlk::CGControl action ; CbcHeuristic *gen ; CbcTreeLocal *localTree ; /* FPump goes first because it only works before there's a solution. */ action = ctlBlk->getFPump(gen, model) ; if (action != CbcGenCtlBlk::CGOff) { model->addHeuristic(gen, "FPump") ; } action = ctlBlk->getRounding(gen, model) ; if (action != CbcGenCtlBlk::CGOff) { model->addHeuristic(gen, "Rounding") ; } action = ctlBlk->getCombine(gen, model) ; if (action != CbcGenCtlBlk::CGOff) { model->addHeuristic(gen, "Combine") ; } action = ctlBlk->getGreedyCover(gen, model) ; if (action != CbcGenCtlBlk::CGOff) { model->addHeuristic(gen, "GCov") ; } action = ctlBlk->getGreedyEquality(gen, model) ; if (action != CbcGenCtlBlk::CGOff) { model->addHeuristic(gen, "GEq") ; } /* This one's a bit different. We acquire the local tree and install it in the model. */ action = ctlBlk->getTreeLocal(localTree, model) ; if (action != CbcGenCtlBlk::CGOff) { model->passInTreeHandler(*localTree) ; } return ; } /* Helper routine to install cut generators. I need to install the new lift-and-project generator (LandP). Also need to figure out stored cuts. */ void installCutGenerators (CbcGenCtlBlk *ctlBlk, CbcModel *model) { int switches[20] ; int genCnt = 0 ; CbcGenCtlBlk::CGControl action ; CglCutGenerator *gen ; /* The magic numbers for the howOften parameter that determines how often the generator is invoked. -100 is disabled, -99 is root only, -98 will stay active only so long as it generates cuts that improve the objective. A value 1 <= k <= 90 means the generator will be called every k nodes. If k is negative, then it can be switched off if unproductive. If k is positive, it'll carry on regardless. */ int howOften[CbcGenCtlBlk::CGMarker] ; howOften[CbcGenCtlBlk::CGOff] = -100 ; howOften[CbcGenCtlBlk::CGOn] = -1 ; howOften[CbcGenCtlBlk::CGRoot] = -99 ; howOften[CbcGenCtlBlk::CGIfMove] = -98 ; howOften[CbcGenCtlBlk::CGForceOn] = 1 ; howOften[CbcGenCtlBlk::CGForceBut] = 1 ; /* A negative value for rowCuts means that the specified actions happen only at the root. */ action = ctlBlk->getProbing(gen) ; if (action != CbcGenCtlBlk::CGOff) { if (action == CbcGenCtlBlk::CGForceBut) { CglProbing *probingGen = dynamic_cast(gen) ; probingGen->setRowCuts(-3) ; } model->addCutGenerator(gen, howOften[action], "Probing") ; switches[genCnt++] = 0 ; } action = ctlBlk->getGomory(gen) ; if (action != CbcGenCtlBlk::CGOff) { model->addCutGenerator(gen, howOften[action], "Gomory") ; switches[genCnt++] = -1 ; } action = ctlBlk->getKnapsack(gen) ; if (action != CbcGenCtlBlk::CGOff) { model->addCutGenerator(gen, howOften[action], "Knapsack") ; switches[genCnt++] = 0 ; } action = ctlBlk->getRedSplit(gen) ; if (action != CbcGenCtlBlk::CGOff) { model->addCutGenerator(gen, howOften[action], "RedSplit") ; switches[genCnt++] = 1 ; } action = ctlBlk->getClique(gen) ; if (action != CbcGenCtlBlk::CGOff) { model->addCutGenerator(gen, howOften[action], "Clique") ; switches[genCnt++] = 0 ; } action = ctlBlk->getMir(gen) ; if (action != CbcGenCtlBlk::CGOff) { model->addCutGenerator(gen, howOften[action], "MIR2") ; switches[genCnt++] = -1 ; } action = ctlBlk->getFlow(gen) ; if (action != CbcGenCtlBlk::CGOff) { model->addCutGenerator(gen, howOften[action], "Flow") ; switches[genCnt++] = 1 ; } action = ctlBlk->getTwomir(gen) ; if (action != CbcGenCtlBlk::CGOff) { model->addCutGenerator(gen, howOften[action], "2-MIR") ; switches[genCnt++] = 1 ; } /* Set control parameters on cut generators. cutDepth says `use this generator when (depth in tree) mod cutDepth == 0'. setSwitchOffIfLessThan says `switch this generator off if the number of cuts at the root is less than the given value'. Sort of. I need to document the magic numbers for howOften , etc. */ genCnt = model->numberCutGenerators() ; int iGen ; for (iGen = 0 ; iGen < genCnt ; iGen++) { CbcCutGenerator *generator = model->cutGenerator(iGen) ; int howOften = generator->howOften() ; if (howOften == -98 || howOften == -99) { generator->setSwitchOffIfLessThan(switches[iGen]) ; } generator->setTiming(true) ; int cutDepth = ctlBlk->getCutDepth() ; if (cutDepth >= 0) { generator->setWhatDepth(cutDepth) ; } } /* Now some additional control parameters that affect cut generation activity. Minimum drop is the minimum objective degradation required to continue with cut passes. We want at least .05 unless the objective is tiny, in which case we'll drop down to a floor of .0001. */ { double objFrac = fabs(model->getMinimizationObjValue()) * .001 + .0001 ; double minDrop = CoinMin(.05, objFrac) ; model->setMinimumDrop(minDrop) ; } /* Set the maximum number of rounds of cut generation at the root and at nodes in the tree. If the value is positive, cut generation will terminate early if the objective degradation doesn't meet the minimum drop requirement. If the value is negatie, minimum drop is not considered. At the root, for small problems, push for 100 passes (really we're betting that we'll stop because no cuts were generated). For medium size problems, the same but say we can quit if we're not achieving the minimum drop. For big problems, cut the number of rounds to 20. The user may have expressed an opinion; if so, it's already set. Once we're in the tree, aim for one pass per activation. */ if (ctlBlk->setByUser_[CbcCbcParam::CUTPASS] == false) { int numCols = model->getNumCols() ; if (numCols < 500) model->setMaximumCutPassesAtRoot(-100) ; else if (numCols < 5000) model->setMaximumCutPassesAtRoot(100) ; else model->setMaximumCutPassesAtRoot(20) ; } model->setMaximumCutPasses(1) ; return ; } /* Install `objects' (integers, SOS sets, etc.) in the OSI. Cribbed from CoinSolve 061216 and subjected to moderate rewriting. A substantial amount of code that's only relevant for AMPL has been deleted. We're only supporting OsiObjects in cbc-generic. */ void setupObjects (OsiSolverInterface *osi, bool didIPP, CglPreProcess *ippObj) { int numInts = osi->getNumIntegers() ; int numObjs = osi->numberObjects() ; /* Does this OSI have defined objects already? If not, we'd best define the basic integer objects. */ if (numInts == 0 || numObjs == 0) { osi->findIntegers(false) ; numInts = osi->getNumIntegers() ; numObjs = osi->numberObjects() ; } /* If we did preprocessing and discovered SOS sets, create SOS objects and install them in the OSI. The priority of SOS objects is set so that larger sets have higher (lower numeric value) priority. The priority of the original objects is reset to be lower than the priority of any SOS object. Since the SOS objects are copied into the OSI, we need to delete our originals once they've been installed. It's not clear to me that this is the right thing to do, particularly if the OSI comes equipped with complex objects. -- lh, 061216 -- */ if (didIPP && ippObj->numberSOS()) { OsiObject **oldObjs = osi->objects() ; int numCols = osi->getNumCols() ; for (int iObj = 0 ; iObj < numObjs ; iObj++) { oldObjs[iObj]->setPriority(numCols + 1) ; } int numSOS = ippObj->numberSOS() ; OsiObject **sosObjs = new OsiObject *[numSOS] ; const int *starts = ippObj->startSOS() ; const int *which = ippObj->whichSOS() ; const int *type = ippObj->typeSOS() ; const double *weight = ippObj->weightSOS() ; int iSOS ; for (iSOS = 0 ; iSOS < numSOS ; iSOS++) { int iStart = starts[iSOS] ; int sosLen = starts[iSOS+1] - iStart ; sosObjs[iSOS] = new OsiSOS(osi, sosLen, which + iStart, weight + iStart, type[iSOS]) ; sosObjs[iSOS]->setPriority(numCols - sosLen) ; } osi->addObjects(numSOS, sosObjs) ; for (iSOS = 0 ; iSOS < numSOS ; iSOS++) delete sosObjs[iSOS] ; delete [] sosObjs ; } return ; } } // end local namespace namespace CbcGenParamUtils { /* Run branch-and-cut. */ int doBaCParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; CbcModel *model = ctlBlk->model_ ; assert (model != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } ctlBlk->setBaBStatus(CbcGenCtlBlk::BACAbandon, CbcGenCtlBlk::BACmInvalid, CbcGenCtlBlk::BACwNotStarted, false, 0) ; /* We ain't gonna do squat without a good model. */ if (!ctlBlk->goodModel_) { std::cout << "** Current model not valid!" << std::endl ; return (retval) ; } /* Start the clock ticking. */ double time1 = CoinCpuTime() ; double time2 ; /* Create a clone of the model which we can modify with impunity. Extract the underlying solver for convenient access. */ CbcModel babModel(*model) ; OsiSolverInterface *babSolver = babModel.solver() ; assert (babSolver != 0) ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: initial babSolver is " << std::hex << babSolver << std::dec << ", log level " << babSolver->messageHandler()->logLevel() << "." << std::endl ; # endif /* Solve the root relaxation. Bail unless it solves to optimality. */ if (!solveRelaxation(&babModel)) { ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBareRoot) ; return (0) ; } # if COIN_CBC_VERBOSITY > 0 std::cout << "doBaCParam: initial relaxation z = " << babSolver->getObjValue() << "." << std::endl ; # endif /* Are we up for fixing variables based on reduced cost alone? */ if (ctlBlk->djFix_.action_ == true) { reducedCostHack(babSolver, ctlBlk->djFix_.threshold_) ; } /* Time to consider preprocessing. We'll do a bit of setup before getting to the meat of the issue. preIppSolver will hold a clone of the unpreprocessed constraint system. We'll need it when we postprocess. ippSolver holds the preprocessed constraint system. Again, we clone it and give the clone to babModel for B&C. Presumably we need an unmodified copy of the preprocessed system to do postprocessing, but the copy itself is hidden inside the preprocess object. */ OsiSolverInterface *preIppSolver = 0 ; CglPreProcess ippObj ; bool didIPP = false ; int numberChanged = 0 ; int numberOriginalColumns = babSolver->getNumCols() ; CbcGenCtlBlk::IPPControl ippAction = ctlBlk->getIPPAction() ; if (!(ippAction == CbcGenCtlBlk::IPPOff || ippAction == CbcGenCtlBlk::IPPStrategy)) { double timeLeft = babModel.getMaximumSeconds() ; preIppSolver = babSolver->clone() ; OsiSolverInterface *ippSolver ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: clone made prior to IPP is " << std::hex << preIppSolver << std::dec << ", log level " << preIppSolver->messageHandler()->logLevel() << "." << std::endl ; # endif preIppSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ; ippObj.messageHandler()->setLogLevel(babModel.logLevel()) ; CglProbing probingGen ; probingGen.setUsingObjective(true) ; probingGen.setMaxPass(3) ; probingGen.setMaxProbeRoot(preIppSolver->getNumCols()) ; probingGen.setMaxElements(100) ; probingGen.setMaxLookRoot(50) ; probingGen.setRowCuts(3) ; ippObj.addCutGenerator(&probingGen) ; /* For preProcessNonDefault, the 2nd parameter controls the conversion of clique and SOS constraints. 0 does nothing, -1 converts <= to ==, and 2 and 3 form SOS sets under strict and not-so-strict conditions, respectively. */ int convert = 0 ; if (ippAction == CbcGenCtlBlk::IPPEqual) { convert = -1 ; } else if (ippAction == CbcGenCtlBlk::IPPEqualAll) { convert = -2 ; } else if (ippAction == CbcGenCtlBlk::IPPSOS) { convert = 2 ; } else if (ippAction == CbcGenCtlBlk::IPPTrySOS) { convert = 3 ; } ippSolver = ippObj.preProcessNonDefault(*preIppSolver, convert, 10) ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver returned from IPP is " << std::hex << ippSolver << std::dec ; if (ippSolver) { std::cout << ", log level " << ippSolver->messageHandler()->logLevel() ; } std::cout << "." << std::endl ; # endif /* ippSolver == 0 is success of a sort --- integer preprocess has found the problem to be infeasible or unbounded. Need to think about how to indicate status. */ if (!ippSolver) { std::cout << "Integer preprocess says infeasible or unbounded" << std::endl ; delete preIppSolver ; ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPP) ; return (0) ; } # if COIN_CBC_VERBOSITY > 0 else { std::cout << "After integer preprocessing, model has " << ippSolver->getNumRows() << " rows, " << ippSolver->getNumCols() << " columns, and " << ippSolver->getNumElements() << " elements." << std::endl ; } # endif preIppSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; ippSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (ippAction == CbcGenCtlBlk::IPPSave) { ippSolver->writeMps("presolved", "mps", 1.0) ; std::cout << "Integer preprocessed model written to `presolved.mps' " << "as minimisation problem." << std::endl ; } OsiSolverInterface *osiTmp = ippSolver->clone() ; babModel.assignSolver(osiTmp) ; babSolver = babModel.solver() ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: clone of IPP solver passed to babModel is " << std::hex << babSolver << std::dec << ", log level " << babSolver->messageHandler()->logLevel() << "." << std::endl ; # endif if (!solveRelaxation(&babModel)) { delete preIppSolver ; ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPPRelax) ; return (0) ; } # if COIN_CBC_VERBOSITY > 0 std::cout << "doBaCParam: presolved relaxation z = " << babSolver->getObjValue() << "." << std::endl ; # endif babModel.setMaximumSeconds(timeLeft - (CoinCpuTime() - time1)) ; didIPP = true ; } /* At this point, babModel and babSolver hold the constraint system we'll use for B&C (either the original system or the preprocessed system) and we have a solution to the lp relaxation. If we're using the COSTSTRATEGY option, set up priorities here and pass them to the babModel. */ if (ctlBlk->priorityAction_ != CbcGenCtlBlk::BPOff) { setupPriorities(&babModel, ctlBlk->priorityAction_) ; } /* Install heuristics and cutting planes. */ installHeuristics(ctlBlk, &babModel) ; installCutGenerators(ctlBlk, &babModel) ; /* Set up status print frequency for babModel. */ if (babModel.getNumCols() > 2000 || babModel.getNumRows() > 1500 || babModel.messageHandler()->logLevel() > 1) babModel.setPrintFrequency(100) ; /* If we've read in a known good solution for debugging, activate the row cut debugger. */ if (ctlBlk->debugSol_.values_) { if (ctlBlk->debugSol_.numCols_ == babModel.getNumCols()) { babSolver->activateRowCutDebugger(ctlBlk->debugSol_.values_) ; } else { std::cout << "doBaCParam: debug file has incorrect number of columns." << std::endl ; } } /* Set ratio-based integrality gap, if specified by user. */ if (ctlBlk->setByUser_[CbcCbcParam::GAPRATIO] == true) { double obj = babSolver->getObjValue() ; double gapRatio = babModel.getDblParam(CbcModel::CbcAllowableFractionGap) ; double gap = gapRatio * (1.0e-5 + fabs(obj)) ; babModel.setAllowableGap(gap) ; std::cout << "doBaCParam: Continuous objective = " << obj << ", so allowable gap set to " << gap << std::endl ; } /* A bit of mystery code. As best I can figure, setSpecialOptions(2) suppresses the removal of warm start information when checkSolution runs an lp to check a solution. John's comment, ``probably faster to use a basis to get integer solutions'' makes some sense in this context. Didn't try to track down moreMipOptions just yet. */ babModel.setSpecialOptions(babModel.specialOptions() | 2) ; /* { int ndx = whichParam(MOREMIPOPTIONS,numberParameters,parameters) ; int moreMipOptions = parameters[ndx].intValue() ; if (moreMipOptions >= 0) { printf("more mip options %d\n",moreMipOptions); babModel.setSearchStrategy(moreMipOptions); } } */ /* Begin the final run-up to branch-and-cut. Make sure that objects are set up in the solver. It's possible that whoever loaded the model into the solver also set up objects. But it's also entirely likely that none exist to this point (and interesting to note that IPP doesn't need to know anything about objects). */ setupObjects(babSolver, didIPP, &ippObj) ; /* Set the branching method. We can't do this until we establish objects, because the constructor will set up arrays based on the number of objects, and there's no provision to set this information after creation. Arguably not good --- it'd be nice to set this in the prototype model that's cloned for this routine. In CoinSolve, shadowPriceMode is handled with the TESTOSI option. */ OsiChooseStrong strong(babSolver) ; strong.setNumberBeforeTrusted(babModel.numberBeforeTrust()) ; strong.setNumberStrong(babModel.numberStrong()) ; strong.setShadowPriceMode(ctlBlk->chooseStrong_.shadowPriceMode_) ; CbcBranchDefaultDecision decision ; decision.setChooseMethod(strong) ; babModel.setBranchingMethod(decision) ; /* Here I've deleted a huge block of code that deals with external priorities, branch direction, pseudocosts, and solution. (PRIORITYIN) Also a block of code that generates C++ code. */ /* Set up strategy for branch-and-cut. Note that the integer code supplied to setupPreProcessing is *not* compatible with the IPPAction enum. But at least it's documented. See desiredPreProcess_ in CbcStrategyDefault. `1' is accidentally equivalent to IPPOn. */ if (ippAction == CbcGenCtlBlk::IPPStrategy) { CbcStrategyDefault strategy(true, 5, 5) ; strategy.setupPreProcessing(1) ; babModel.setStrategy(strategy) ; } /* Yes! At long last, we're ready for the big call. Do branch and cut. In general, the solver used to return the solution will not be the solver we passed in, so reset babSolver here. */ int statistics = (ctlBlk->printOpt_ > 0) ? ctlBlk->printOpt_ : 0 ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver at call to branchAndBound is " << std::hex << babModel.solver() << std::dec << ", log level " << babModel.solver()->messageHandler()->logLevel() << "." << std::endl ; # endif babModel.branchAndBound(statistics) ; babSolver = babModel.solver() ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver at return from branchAndBound is " << std::hex << babModel.solver() << std::dec << ", log level " << babModel.solver()->messageHandler()->logLevel() << "." << std::endl ; # endif /* Write out solution to preprocessed model. */ if (ctlBlk->debugCreate_ == "createAfterPre" && babModel.bestSolution()) { CbcGenParamUtils::saveSolution(babSolver, "debug.file") ; } /* Print some information about branch-and-cut. */ # if COIN_CBC_VERBOSITY > 0 std::cout << "Cuts at root node changed objective from " << babModel.getContinuousObjective() << " to " << babModel.rootObjectiveAfterCuts() << std::endl ; for (int iGen = 0 ; iGen < babModel.numberCutGenerators() ; iGen++) { CbcCutGenerator *generator = babModel.cutGenerator(iGen) ; std::cout << generator->cutGeneratorName() << " was tried " << generator->numberTimesEntered() << " times and created " << generator->numberCutsInTotal() << " cuts of which " << generator->numberCutsActive() << " were active after adding rounds of cuts" ; if (generator->timing()) { std::cout << " ( " << generator->timeInCutGenerator() << " seconds)" ; } std::cout << std::endl ; } # endif time2 = CoinCpuTime(); ctlBlk->totalTime_ += time2 - time1; /* If we performed integer preprocessing, time to back it out. */ if (ippAction != CbcGenCtlBlk::IPPOff) { # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver passed to IPP postprocess is " << std::hex << babSolver << std::dec << "." << std::endl ; # endif ippObj.postProcess(*babSolver); babModel.assignSolver(preIppSolver) ; babSolver = babModel.solver() ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver in babModel after IPP postprocess is " << std::hex << babSolver << std::dec << "." << std::endl ; # endif } /* Write out postprocessed solution to debug file, if requested. */ if (ctlBlk->debugCreate_ == "create" && babModel.bestSolution()) { CbcGenParamUtils::saveSolution(babSolver, "debug.file") ; } /* If we have a good solution, detach the solver with the answer. Fill in the rest of the status information for the benefit of the wider world. */ bool keepAnswerSolver = false ; OsiSolverInterface *answerSolver = 0 ; if (babModel.bestSolution()) { babModel.setModelOwnsSolver(false) ; keepAnswerSolver = true ; answerSolver = babSolver ; } ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBAC, keepAnswerSolver, answerSolver) ; /* And one last bit of information & statistics. */ ctlBlk->printBaBStatus() ; std::cout << " " ; if (keepAnswerSolver) { std::cout << "objective " << babModel.getObjValue() << "; " ; } std::cout << babModel.getNodeCount() << " nodes and " << babModel.getIterationCount() << " iterations - took " << time2 - time1 << " seconds" << std::endl ; return (0) ; } } // end namespace CbcGenParamutils Cbc-2.8.12/src/CbcSolver.cpp0000644000076600007660000207072312374600030014134 0ustar coincoin/* $Id: CbcSolver.cpp 2057 2014-08-19 07:43:20Z forrest $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /*! \file CbcSolver.cpp \brief Second level routines for the cbc stand-alone solver. */ #include "CbcConfig.h" #include "CoinPragma.hpp" #include #include #include #include #include #include #include #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "CoinMpsIO.hpp" #include "CoinModel.hpp" #include "ClpFactorization.hpp" #include "ClpQuadraticObjective.hpp" #include "CoinTime.hpp" #include "ClpSimplex.hpp" #include "ClpSimplexOther.hpp" #include "ClpSolve.hpp" #include "ClpMessage.hpp" #include "ClpPackedMatrix.hpp" #include "ClpPlusMinusOneMatrix.hpp" #include "ClpNetworkMatrix.hpp" #include "ClpDualRowSteepest.hpp" #include "ClpDualRowDantzig.hpp" #include "ClpLinearObjective.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "ClpPrimalColumnDantzig.hpp" #include "ClpPresolve.hpp" #ifndef COIN_HAS_CBC #define COIN_HAS_CBC #endif #include "CbcOrClpParam.hpp" #include "OsiRowCutDebugger.hpp" #include "OsiChooseVariable.hpp" #include "OsiAuxInfo.hpp" #include "CbcMipStartIO.hpp" #include "CbcSolverHeuristics.hpp" #ifdef COIN_HAS_GLPK #include "glpk.h" extern glp_tran* cbc_glp_tran; extern glp_prob* cbc_glp_prob; #else #define GLP_UNDEF 1 #define GLP_FEAS 2 #define GLP_INFEAS 3 #define GLP_NOFEAS 4 #define GLP_OPT 5 #endif #ifndef CBC_QUIET #define CBC_QUIET 0 #endif //#define USER_HAS_FAKE_CLP //#define USER_HAS_FAKE_CBC //#define CLP_MALLOC_STATISTICS #ifdef CLP_MALLOC_STATISTICS #include #include #include #include "stolen_from_ekk_malloc.cpp" static double malloc_times = 0.0; static double malloc_total = 0.0; static int malloc_amount[] = {0, 32, 128, 256, 1024, 4096, 16384, 65536, 262144, INT_MAX}; static int malloc_n = 10; double malloc_counts[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; bool malloc_counts_on = true; void * operator new (size_t size) throw (std::bad_alloc) { malloc_times ++; malloc_total += size; int i; for (i = 0; i < malloc_n; i++) { if ((int) size <= malloc_amount[i]) { malloc_counts[i]++; break; } } # ifdef DEBUG_MALLOC void *p; if (malloc_counts_on) p = stolen_from_ekk_mallocBase(size); else p = malloc(size); # else void * p = malloc(size); # endif //char * xx = (char *) p; //memset(xx,0,size); // Initialize random seed //CoinSeedRandom(987654321); return p; } void operator delete (void *p) throw() { # ifdef DEBUG_MALLOC if (malloc_counts_on) stolen_from_ekk_freeBase(p); else free(p); # else free(p); # endif } static void malloc_stats2() { double average = malloc_total / malloc_times; printf("count %g bytes %g - average %g\n", malloc_times, malloc_total, average); for (int i = 0; i < malloc_n; i++) printf("%g ", malloc_counts[i]); printf("\n"); malloc_times = 0.0; malloc_total = 0.0; memset(malloc_counts, 0, sizeof(malloc_counts)); // print results } #else //CLP_MALLOC_STATISTICS //void stolen_from_ekk_memory(void * dummy,int type) //{ //} //bool malloc_counts_on=false; #endif //CLP_MALLOC_STATISTICS //#define DMALLOC #ifdef DMALLOC #include "dmalloc.h" #endif #ifdef WSSMP_BARRIER #define FOREIGN_BARRIER #endif #ifdef UFL_BARRIER #define FOREIGN_BARRIER #endif #ifdef TAUCS_BARRIER #define FOREIGN_BARRIER #endif static int initialPumpTune = -1; #include "CoinWarmStartBasis.hpp" #include "OsiSolverInterface.hpp" #include "OsiCuts.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" #ifndef COIN_HAS_LINK #define COIN_HAS_LINK #endif #ifdef COIN_HAS_LINK #include "CbcLinked.hpp" #endif #include "CglPreProcess.hpp" #include "CglCutGenerator.hpp" #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglRedSplit.hpp" #include "CglRedSplit2.hpp" #include "CglGMI.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding2.hpp" #include "CglTwomir.hpp" #include "CglDuplicateRow.hpp" #include "CglStored.hpp" #include "CglLandP.hpp" #include "CglResidualCapacity.hpp" #include "CglZeroHalf.hpp" //#define CGL_WRITEMPS #ifdef CGL_WRITEMPS extern double * debugSolution; extern int debugNumberColumns; #endif #include "CbcModel.hpp" #include "CbcHeuristic.hpp" #include "CbcHeuristicLocal.hpp" #include "CbcHeuristicPivotAndFix.hpp" //#include "CbcHeuristicPivotAndComplement.hpp" #include "CbcHeuristicRandRound.hpp" #include "CbcHeuristicGreedy.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcHeuristicRINS.hpp" #include "CbcHeuristicDiveCoefficient.hpp" #include "CbcHeuristicDiveFractional.hpp" #include "CbcHeuristicDiveGuided.hpp" #include "CbcHeuristicDiveVectorLength.hpp" #include "CbcHeuristicDivePseudoCost.hpp" #include "CbcHeuristicDiveLineSearch.hpp" #include "CbcTreeLocal.hpp" #include "CbcCompareActual.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchLotsize.hpp" #include "CbcOrClpParam.hpp" #include "CbcCutGenerator.hpp" #include "CbcStrategy.hpp" #include "CbcBranchCut.hpp" #include "OsiClpSolverInterface.hpp" #include "CbcSolverAnalyze.hpp" #include "CbcSolverExpandKnapsack.hpp" #include "CbcSolver.hpp" //#define IN_BRANCH_AND_BOUND (0x01000000|262144) #define IN_BRANCH_AND_BOUND (0x01000000|262144|128|1024|2048) //#define IN_BRANCH_AND_BOUND (0x01000000|262144|128) /* CbcStopNow class definitions. */ CbcStopNow::CbcStopNow() { } CbcStopNow::~CbcStopNow() { } // Copy constructor CbcStopNow::CbcStopNow ( const CbcStopNow & ) { } // Assignment operator CbcStopNow & CbcStopNow::operator=(const CbcStopNow & rhs) { if (this != &rhs) { } return *this; } // Clone CbcStopNow * CbcStopNow::clone() const { return new CbcStopNow(*this); } /* CbcUser class definitions. */ // User stuff (base class) CbcUser::CbcUser() : coinModel_(NULL), userName_("null") { } CbcUser::~CbcUser() { delete coinModel_; } // Copy constructor CbcUser::CbcUser ( const CbcUser & rhs) { if (rhs.coinModel_) coinModel_ = new CoinModel(*rhs.coinModel_); else coinModel_ = NULL; userName_ = rhs.userName_; } // Assignment operator CbcUser & CbcUser::operator=(const CbcUser & rhs) { if (this != &rhs) { if (rhs.coinModel_) coinModel_ = new CoinModel(*rhs.coinModel_); else coinModel_ = NULL; userName_ = rhs.userName_; } return *this; } static void putBackOtherSolutions(CbcModel * presolvedModel, CbcModel * model, CglPreProcess * preProcess) { int numberSolutions=presolvedModel->numberSavedSolutions(); int numberColumns=presolvedModel->getNumCols(); if (numberSolutions>1) { model->deleteSolutions(); double * bestSolution = CoinCopyOfArray(presolvedModel->bestSolution(),numberColumns); //double cutoff = presolvedModel->getCutoff(); double objectiveValue=presolvedModel->getObjValue(); //model->createSpaceForSavedSolutions(numberSolutions-1); for (int iSolution=numberSolutions-1;iSolution>=0;iSolution--) { presolvedModel->setCutoff(COIN_DBL_MAX); presolvedModel->solver()->setColSolution(presolvedModel->savedSolution(iSolution)); //presolvedModel->savedSolutionObjective(iSolution)); preProcess->postProcess(*presolvedModel->solver(),false); model->setBestSolution(preProcess->originalModel()->getColSolution(),model->solver()->getNumCols(), presolvedModel->savedSolutionObjective(iSolution)); } presolvedModel->setBestObjectiveValue(objectiveValue); presolvedModel->solver()->setColSolution(bestSolution); //presolvedModel->setBestSolution(bestSolution,numberColumns,objectiveValue); } } /* CbcSolver class definitions */ CbcSolver::CbcSolver() : babModel_(NULL), userFunction_(NULL), statusUserFunction_(NULL), originalSolver_(NULL), originalCoinModel_(NULL), cutGenerator_(NULL), numberUserFunctions_(0), numberCutGenerators_(0), startTime_(CoinCpuTime()), parameters_(NULL), numberParameters_(0), doMiplib_(false), noPrinting_(false), readMode_(1) { callBack_ = new CbcStopNow(); fillParameters(); } CbcSolver::CbcSolver(const OsiClpSolverInterface & solver) : babModel_(NULL), userFunction_(NULL), statusUserFunction_(NULL), originalSolver_(NULL), originalCoinModel_(NULL), cutGenerator_(NULL), numberUserFunctions_(0), numberCutGenerators_(0), startTime_(CoinCpuTime()), parameters_(NULL), numberParameters_(0), doMiplib_(false), noPrinting_(false), readMode_(1) { callBack_ = new CbcStopNow(); model_ = CbcModel(solver); fillParameters(); } CbcSolver::CbcSolver(const CbcModel & solver) : babModel_(NULL), userFunction_(NULL), statusUserFunction_(NULL), originalSolver_(NULL), originalCoinModel_(NULL), cutGenerator_(NULL), numberUserFunctions_(0), numberCutGenerators_(0), startTime_(CoinCpuTime()), parameters_(NULL), numberParameters_(0), doMiplib_(false), noPrinting_(false), readMode_(1) { callBack_ = new CbcStopNow(); model_ = solver; fillParameters(); } CbcSolver::~CbcSolver() { int i; for (i = 0; i < numberUserFunctions_; i++) delete userFunction_[i]; delete [] userFunction_; for (i = 0; i < numberCutGenerators_; i++) delete cutGenerator_[i]; delete [] cutGenerator_; delete [] statusUserFunction_; delete originalSolver_; delete originalCoinModel_; delete babModel_; delete [] parameters_; delete callBack_; } // Copy constructor CbcSolver::CbcSolver ( const CbcSolver & rhs) : model_(rhs.model_), babModel_(NULL), userFunction_(NULL), statusUserFunction_(NULL), numberUserFunctions_(rhs.numberUserFunctions_), startTime_(CoinCpuTime()), parameters_(NULL), numberParameters_(rhs.numberParameters_), doMiplib_(rhs.doMiplib_), noPrinting_(rhs.noPrinting_), readMode_(rhs.readMode_) { fillParameters(); if (rhs.babModel_) babModel_ = new CbcModel(*rhs.babModel_); userFunction_ = new CbcUser * [numberUserFunctions_]; int i; for (i = 0; i < numberUserFunctions_; i++) userFunction_[i] = rhs.userFunction_[i]->clone(); for (i = 0; i < numberParameters_; i++) parameters_[i] = rhs.parameters_[i]; for (i = 0; i < numberCutGenerators_; i++) cutGenerator_[i] = rhs.cutGenerator_[i]->clone(); callBack_ = rhs.callBack_->clone(); originalSolver_ = NULL; if (rhs.originalSolver_) { OsiSolverInterface * temp = rhs.originalSolver_->clone(); originalSolver_ = dynamic_cast (temp); assert (originalSolver_); } originalCoinModel_ = NULL; if (rhs.originalCoinModel_) originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_); } // Assignment operator CbcSolver & CbcSolver::operator=(const CbcSolver & rhs) { if (this != &rhs) { int i; for (i = 0; i < numberUserFunctions_; i++) delete userFunction_[i]; delete [] userFunction_; for (i = 0; i < numberCutGenerators_; i++) delete cutGenerator_[i]; delete [] cutGenerator_; delete [] statusUserFunction_; delete originalSolver_; delete originalCoinModel_; statusUserFunction_ = NULL; delete babModel_; delete [] parameters_; delete callBack_; numberUserFunctions_ = rhs.numberUserFunctions_; startTime_ = rhs.startTime_; numberParameters_ = rhs.numberParameters_; for (i = 0; i < numberParameters_; i++) parameters_[i] = rhs.parameters_[i]; for (i = 0; i < numberCutGenerators_; i++) cutGenerator_[i] = rhs.cutGenerator_[i]->clone(); noPrinting_ = rhs.noPrinting_; readMode_ = rhs.readMode_; doMiplib_ = rhs.doMiplib_; model_ = rhs.model_; if (rhs.babModel_) babModel_ = new CbcModel(*rhs.babModel_); else babModel_ = NULL; userFunction_ = new CbcUser * [numberUserFunctions_]; for (i = 0; i < numberUserFunctions_; i++) userFunction_[i] = rhs.userFunction_[i]->clone(); callBack_ = rhs.callBack_->clone(); originalSolver_ = NULL; if (rhs.originalSolver_) { OsiSolverInterface * temp = rhs.originalSolver_->clone(); originalSolver_ = dynamic_cast (temp); assert (originalSolver_); } originalCoinModel_ = NULL; if (rhs.originalCoinModel_) originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_); } return *this; } // Get int value int CbcSolver::intValue(CbcOrClpParameterType type) const { return parameters_[whichParam(type, numberParameters_, parameters_)].intValue(); } // Set int value void CbcSolver::setIntValue(CbcOrClpParameterType type, int value) { parameters_[whichParam(type, numberParameters_, parameters_)].setIntValue(value); } // Get double value double CbcSolver::doubleValue(CbcOrClpParameterType type) const { return parameters_[whichParam(type, numberParameters_, parameters_)].doubleValue(); } // Set double value void CbcSolver::setDoubleValue(CbcOrClpParameterType type, double value) { parameters_[whichParam(type, numberParameters_, parameters_)].setDoubleValue(value); } // User function (NULL if no match) CbcUser * CbcSolver::userFunction(const char * name) const { int i; for (i = 0; i < numberUserFunctions_; i++) { if (!strcmp(name, userFunction_[i]->name().c_str())) break; } if (i < numberUserFunctions_) return userFunction_[i]; else return NULL; } void CbcSolver::fillParameters() { int maxParam = 200; CbcOrClpParam * parameters = new CbcOrClpParam [maxParam]; numberParameters_ = 0 ; establishParams(numberParameters_, parameters) ; assert (numberParameters_ <= maxParam); parameters_ = new CbcOrClpParam [numberParameters_]; int i; for (i = 0; i < numberParameters_; i++) parameters_[i] = parameters[i]; delete [] parameters; const char dirsep = CoinFindDirSeparator(); std::string directory; std::string dirSample; std::string dirNetlib; std::string dirMiplib; if (dirsep == '/') { directory = "./"; dirSample = "../../Data/Sample/"; dirNetlib = "../../Data/Netlib/"; dirMiplib = "../../Data/miplib3/"; } else { directory = ".\\"; dirSample = "..\\..\\..\\..\\Data\\Sample\\"; dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; } std::string defaultDirectory = directory; std::string importFile = ""; std::string exportFile = "default.mps"; std::string importBasisFile = ""; std::string importPriorityFile = ""; std::string mipStartFile = ""; std::string debugFile = ""; std::string printMask = ""; std::string exportBasisFile = "default.bas"; std::string saveFile = "default.prob"; std::string restoreFile = "default.prob"; std::string solutionFile = "stdout"; std::string solutionSaveFile = "solution.file"; int doIdiot = -1; int outputFormat = 2; int substitution = 3; int dualize = 3; int preSolve = 5; int doSprint = -1; int testOsiParameters = -1; int createSolver = 0; ClpSimplex * lpSolver; OsiClpSolverInterface * clpSolver; if (model_.solver()) { clpSolver = dynamic_cast (model_.solver()); assert (clpSolver); lpSolver = clpSolver->getModelPtr(); assert (lpSolver); } else { lpSolver = new ClpSimplex(); clpSolver = new OsiClpSolverInterface(lpSolver, true); createSolver = 1 ; } parameters_[whichParam(CLP_PARAM_ACTION_BASISIN, numberParameters_, parameters_)].setStringValue(importBasisFile); parameters_[whichParam(CBC_PARAM_ACTION_PRIORITYIN, numberParameters_, parameters_)].setStringValue(importPriorityFile); parameters_[whichParam(CBC_PARAM_ACTION_MIPSTART, numberParameters_, parameters_)].setStringValue(mipStartFile); parameters_[whichParam(CLP_PARAM_ACTION_BASISOUT, numberParameters_, parameters_)].setStringValue(exportBasisFile); parameters_[whichParam(CLP_PARAM_ACTION_DEBUG, numberParameters_, parameters_)].setStringValue(debugFile); parameters_[whichParam(CLP_PARAM_ACTION_PRINTMASK, numberParameters_, parameters_)].setStringValue(printMask); parameters_[whichParam(CLP_PARAM_ACTION_DIRECTORY, numberParameters_, parameters_)].setStringValue(directory); parameters_[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, numberParameters_, parameters_)].setStringValue(dirSample); parameters_[whichParam(CLP_PARAM_ACTION_DIRNETLIB, numberParameters_, parameters_)].setStringValue(dirNetlib); parameters_[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, numberParameters_, parameters_)].setStringValue(dirMiplib); parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualBound()); parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualTolerance()); parameters_[whichParam(CLP_PARAM_ACTION_EXPORT, numberParameters_, parameters_)].setStringValue(exportFile); parameters_[whichParam(CLP_PARAM_INT_IDIOT, numberParameters_, parameters_)].setIntValue(doIdiot); parameters_[whichParam(CLP_PARAM_ACTION_IMPORT, numberParameters_, parameters_)].setStringValue(importFile); parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].setDoubleValue(1.0e-8); int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_); int value = 1; clpSolver->messageHandler()->setLogLevel(1) ; lpSolver->setLogLevel(1); parameters_[iParam].setIntValue(value); iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_); model_.messageHandler()->setLogLevel(value); parameters_[iParam].setIntValue(value); parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters_, parameters_)].setIntValue(lpSolver->factorizationFrequency()); parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters_, parameters_)].setIntValue(lpSolver->maximumIterations()); parameters_[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, numberParameters_, parameters_)].setIntValue(outputFormat); parameters_[whichParam(CLP_PARAM_INT_PRESOLVEPASS, numberParameters_, parameters_)].setIntValue(preSolve); parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, numberParameters_, parameters_)].setIntValue(lpSolver->perturbation()); parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->primalTolerance()); parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters_, parameters_)].setDoubleValue(lpSolver->infeasibilityCost()); parameters_[whichParam(CLP_PARAM_ACTION_RESTORE, numberParameters_, parameters_)].setStringValue(restoreFile); parameters_[whichParam(CLP_PARAM_ACTION_SAVE, numberParameters_, parameters_)].setStringValue(saveFile); //parameters_[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters_,parameters_)].setDoubleValue(1.0e8); parameters_[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, numberParameters_, parameters_)].setDoubleValue(1.0e8); parameters_[whichParam(CLP_PARAM_ACTION_SOLUTION, numberParameters_, parameters_)].setStringValue(solutionFile); parameters_[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, numberParameters_, parameters_)].setStringValue(solutionFile); parameters_[whichParam(CLP_PARAM_ACTION_SAVESOL, numberParameters_, parameters_)].setStringValue(solutionSaveFile); parameters_[whichParam(CLP_PARAM_INT_SPRINT, numberParameters_, parameters_)].setIntValue(doSprint); parameters_[whichParam(CLP_PARAM_INT_SUBSTITUTION, numberParameters_, parameters_)].setIntValue(substitution); parameters_[whichParam(CLP_PARAM_INT_DUALIZE, numberParameters_, parameters_)].setIntValue(dualize); parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, numberParameters_, parameters_)].setIntValue(model_.numberBeforeTrust()); parameters_[whichParam(CBC_PARAM_INT_MAXNODES, numberParameters_, parameters_)].setIntValue(model_.getMaximumNodes()); parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, numberParameters_, parameters_)].setIntValue(model_.numberStrong()); parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight)); parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance)); parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement)); parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].setIntValue(testOsiParameters); parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_)].setIntValue(1003); initialPumpTune = 1003; #ifdef CBC_THREAD parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].setIntValue(0); #endif // Set up likely cut generators and defaults parameters_[whichParam(CBC_PARAM_STR_PREPROCESS, numberParameters_, parameters_)].setCurrentOption("sos"); parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].setIntValue(1057); parameters_[whichParam(CBC_PARAM_INT_CUTPASSINTREE, numberParameters_, parameters_)].setIntValue(1); parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, numberParameters_, parameters_)].setIntValue(-1); parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].setIntValue(100); parameters_[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, numberParameters_, parameters_)].setCurrentOption("on"); parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, numberParameters_, parameters_)].setCurrentOption("on"); parameters_[whichParam(CBC_PARAM_STR_NODESTRATEGY, numberParameters_, parameters_)].setCurrentOption("fewest"); parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove"); parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove"); parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove"); parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_GMICUTS, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, numberParameters_, parameters_)].setCurrentOption("ifmove"); parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove"); parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove"); parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove"); parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_ROUNDING, numberParameters_, parameters_)].setCurrentOption("on"); parameters_[whichParam(CBC_PARAM_STR_FPUMP, numberParameters_, parameters_)].setCurrentOption("on"); parameters_[whichParam(CBC_PARAM_STR_GREEDY, numberParameters_, parameters_)].setCurrentOption("on"); parameters_[whichParam(CBC_PARAM_STR_COMBINE, numberParameters_, parameters_)].setCurrentOption("on"); parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_RANDROUND, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_NAIVE, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_DINS, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_RENS, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, numberParameters_, parameters_)].setCurrentOption("off"); parameters_[whichParam(CBC_PARAM_STR_COSTSTRATEGY, numberParameters_, parameters_)].setCurrentOption("off"); if (createSolver) delete clpSolver; } /* Initialise a subset of the parameters prior to processing any input from the user. Why this choice of subset? */ /*! \todo Guard/replace clp-specific code */ void CbcSolver::fillValuesInSolver() { OsiSolverInterface * solver = model_.solver(); OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); assert (clpSolver); ClpSimplex * lpSolver = clpSolver->getModelPtr(); /* Why are we reaching into the underlying solver(s) for these settings? Shouldn't CbcSolver have its own defaults, which are then imposed on the underlying solver? Coming at if from the other side, if CbcSolver had the capability to use multiple solvers then it definitely makes sense to acquire the defaults from the solver (on the assumption that we haven't processed command line parameters yet, which can then override the defaults). But then it's more of a challenge to avoid solver-specific coding here. */ noPrinting_ = (lpSolver->logLevel() == 0); CoinMessageHandler * generalMessageHandler = clpSolver->messageHandler(); generalMessageHandler->setPrefix(true); lpSolver->setPerturbation(50); lpSolver->messageHandler()->setPrefix(false); parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualBound()); parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualTolerance()); /* Why are we doing this? We read the log level from parameters_, set it into the message handlers for cbc and the underlying solver. Then we read the log level back from the handlers and use it to set the values in parameters_! */ int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_); int value = parameters_[iParam].intValue(); clpSolver->messageHandler()->setLogLevel(value) ; lpSolver->setLogLevel(value); iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_); value = parameters_[iParam].intValue(); model_.messageHandler()->setLogLevel(value); parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_)].setIntValue(model_.logLevel()); parameters_[whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_)].setIntValue(lpSolver->logLevel()); parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters_, parameters_)].setIntValue(lpSolver->factorizationFrequency()); parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters_, parameters_)].setIntValue(lpSolver->maximumIterations()); parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, numberParameters_, parameters_)].setIntValue(lpSolver->perturbation()); parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->primalTolerance()); parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters_, parameters_)].setDoubleValue(lpSolver->infeasibilityCost()); parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, numberParameters_, parameters_)].setIntValue(model_.numberBeforeTrust()); parameters_[whichParam(CBC_PARAM_INT_MAXNODES, numberParameters_, parameters_)].setIntValue(model_.getMaximumNodes()); parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, numberParameters_, parameters_)].setIntValue(model_.numberStrong()); parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight)); parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance)); parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement)); } // Add user function void CbcSolver::addUserFunction(CbcUser * function) { CbcUser ** temp = new CbcUser * [numberUserFunctions_+1]; int i; for (i = 0; i < numberUserFunctions_; i++) temp[i] = userFunction_[i]; delete [] userFunction_; userFunction_ = temp; userFunction_[numberUserFunctions_++] = function->clone(); delete [] statusUserFunction_; statusUserFunction_ = NULL; } // Set user call back void CbcSolver::setUserCallBack(CbcStopNow * function) { delete callBack_; callBack_ = function->clone(); } // Copy of model on initial load (will contain output solutions) void CbcSolver::setOriginalSolver(OsiClpSolverInterface * originalSolver) { delete originalSolver_; OsiSolverInterface * temp = originalSolver->clone(); originalSolver_ = dynamic_cast (temp); assert (originalSolver_); } // Copy of model on initial load void CbcSolver::setOriginalCoinModel(CoinModel * originalCoinModel) { delete originalCoinModel_; originalCoinModel_ = new CoinModel(*originalCoinModel); } // Add cut generator void CbcSolver::addCutGenerator(CglCutGenerator * generator) { CglCutGenerator ** temp = new CglCutGenerator * [numberCutGenerators_+1]; int i; for (i = 0; i < numberCutGenerators_; i++) temp[i] = cutGenerator_[i]; delete [] cutGenerator_; cutGenerator_ = temp; cutGenerator_[numberCutGenerators_++] = generator->clone(); } /* The only other solver that's ever been used is cplex, and the use is limited -- do the root with clp and all the cbc smarts, then give the problem over to cplex to finish. Although the defines can be read in some places to allow other options, nothing's been tested and success is unlikely. CBC_OTHER_SOLVER == 1 is cplex. */ #if CBC_OTHER_SOLVER==1 # ifndef COIN_HAS_CPX # error "Configuration did not detect cplex installation." # else # include "OsiCpxSolverInterface.hpp" # endif #endif #ifdef COIN_HAS_ASL #include "Cbc_ampl.h" #endif static void statistics(ClpSimplex * originalModel, ClpSimplex * model); static bool maskMatches(const int * starts, char ** masks, std::string & check); static void generateCode(CbcModel * model, const char * fileName, int type, int preProcess); // dummy fake main programs for UserClp and UserCbc void fakeMain (ClpSimplex & model, OsiSolverInterface & osiSolver, CbcModel & babSolver); void fakeMain2 (ClpSimplex & model, OsiClpSolverInterface & osiSolver, int options); // Allow for interrupts // But is this threadsafe? (so switched off by option) #include "CoinSignal.hpp" static CbcModel * currentBranchModel = NULL; extern "C" { static void signal_handler(int whichSignal) { if (currentBranchModel != NULL) { currentBranchModel->sayEventHappened(); // say why stopped if (currentBranchModel->heuristicModel()) currentBranchModel->heuristicModel()->sayEventHappened(); } return; } } //#define CBC_SIG_TRAP #ifdef CBC_SIG_TRAP #include static sigjmp_buf cbc_seg_buffer; extern "C" { static void signal_handler_error(int whichSignal) { siglongjmp(cbc_seg_buffer, 1); } } #endif /* Debug checks on special ordered sets. This is active only for debugging. The entire body of the routine becomes a noop when COIN_DEVELOP is not defined. To avoid compiler warnings, the formal parameters also need to go away. */ #ifdef COIN_DEVELOP void checkSOS(CbcModel * babModel, const OsiSolverInterface * solver) #else void checkSOS(CbcModel * /*babModel*/, const OsiSolverInterface * /*solver*/) #endif { #ifdef COIN_DEVELOP if (!babModel->ownObjects()) return; #if COIN_DEVELOP>2 //const double *objective = solver->getObjCoefficients() ; const double *columnLower = solver->getColLower() ; const double * columnUpper = solver->getColUpper() ; const double * solution = solver->getColSolution(); //int numberRows = solver->getNumRows(); //double direction = solver->getObjSense(); //int iRow,iColumn; #endif // Row copy CoinPackedMatrix matrixByRow(*solver->getMatrixByRow()); //const double * elementByRow = matrixByRow.getElements(); //const int * column = matrixByRow.getIndices(); //const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); // Column copy CoinPackedMatrix matrixByCol(*solver->getMatrixByCol()); const double * element = matrixByCol.getElements(); const int * row = matrixByCol.getIndices(); const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); const int * columnLength = matrixByCol.getVectorLengths(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); OsiObject ** objects = babModel->objects(); int numberObjects = babModel->numberObjects(); int numberColumns = solver->getNumCols() ; for (int iObj = 0; iObj < numberObjects; iObj++) { CbcSOS * objSOS = dynamic_cast (objects[iObj]) ; if (objSOS) { int n = objSOS->numberMembers(); const int * which = objSOS->members(); #if COIN_DEVELOP>2 const double * weight = objSOS->weights(); #endif int type = objSOS->sosType(); // convexity row? int iColumn; iColumn = which[0]; int j; int convex = -1; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j]; if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0 && value == 1.0) { // possible if (rowLength[iRow] == n) { if (convex == -1) convex = iRow; else convex = -2; } } } printf ("set %d of type %d has %d members - possible convexity row %d\n", iObj, type, n, convex); for (int i = 0; i < n; i++) { iColumn = which[i]; // Column may have been added if (iColumn < numberColumns) { int convex2 = -1; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (iRow == convex) { double value = element[j]; if (value == 1.0) { convex2 = iRow; } } } if (convex2<0 && convex >= 0) { printf("odd convexity row\n"); convex = -2; } #if COIN_DEVELOP>2 printf("col %d has weight %g and value %g, bounds %g %g\n", iColumn, weight[i], solution[iColumn], columnLower[iColumn], columnUpper[iColumn]); #endif } } } } #endif // COIN_DEVELOP } static int dummyCallBack(CbcModel * /*model*/, int /*whereFrom*/) { return 0; } /* Global parameters for command processing. These will need to be moved into an object of some sort in order to make this set of calls thread-safe. */ int CbcOrClpRead_mode = 1; FILE * CbcOrClpReadCommand = stdin; extern int CbcOrClpEnvironmentIndex; int callCbc1(const char * input2, CbcModel & model, int callBack(CbcModel * currentSolver, int whereFrom), CbcSolverUsefulData & parameterData); /* Wrappers for CbcMain0, CbcMain1. The various forms of callCbc will eventually resolve to a call to CbcMain0 followed by a call to callCbc1. */ /* Simplest calling form: supply just a string with the command options. The wrapper creates an OsiClpSolverInterface and calls the next wrapper. */ int callCbc(const std::string input2) { char * input3 = CoinStrdup(input2.c_str()); OsiClpSolverInterface solver1; int returnCode = callCbc(input3, solver1); free(input3); return returnCode; } int callCbc(const char * input2) { { OsiClpSolverInterface solver1; return callCbc(input2, solver1); } } /* Second calling form: supply the command line and an OsiClpSolverInterface. the wrapper will create a CbcModel and call the next wrapper. */ int callCbc(const std::string input2, OsiClpSolverInterface& solver1) { char * input3 = CoinStrdup(input2.c_str()); int returnCode = callCbc(input3, solver1); free(input3); return returnCode; } int callCbc(const char * input2, OsiClpSolverInterface& solver1) { CbcModel model(solver1); return callCbc(input2, model); } /* Third calling form: supply the command line and a CbcModel. This wrapper will actually call CbcMain0 and then call the next set of wrappers (callCbc1) to handle the call to CbcMain1. */ int callCbc(const char * input2, CbcModel & babSolver) { CbcSolverUsefulData data; #ifndef CBC_NO_INTERRUPT data.useSignalHandler_=true; #endif #ifndef CBC_NO_PRINTING data.noPrinting_ = false; #endif CbcMain0(babSolver, data); return callCbc1(input2, babSolver, dummyCallBack, data); } int callCbc(const std::string input2, CbcModel & babSolver) { char * input3 = CoinStrdup(input2.c_str()); CbcMain0(babSolver); int returnCode = callCbc1(input3, babSolver); free(input3); return returnCode; } /* Various overloads of callCbc1. The first pair accepts just a CbcModel and supplements it with a dummy callback routine. The second pair allows the user to supply a callback. See CbcMain1 for further explanation of the callback. The various overloads of callCbc1 resolve to the final version, which breaks the string into individual parameter strings (i.e., creates something that looks like a standard argv vector). */ int callCbc1(const std::string input2, CbcModel & babSolver) { char * input3 = CoinStrdup(input2.c_str()); int returnCode = callCbc1(input3, babSolver); free(input3); return returnCode; } int callCbc1(const char * input2, CbcModel & model) { return callCbc1(input2, model, dummyCallBack); } int callCbc1(const std::string input2, CbcModel & babSolver, int callBack(CbcModel * currentSolver, int whereFrom)) { char * input3 = CoinStrdup(input2.c_str()); int returnCode = callCbc1(input3, babSolver, callBack); free(input3); return returnCode; } int callCbc1(const char * input2, CbcModel & model, int callBack(CbcModel * currentSolver, int whereFrom), CbcSolverUsefulData & parameterData) { char * input = CoinStrdup(input2); size_t length = strlen(input); bool blank = input[0] == '0'; int n = blank ? 0 : 1; for (size_t i = 0; i < length; i++) { if (blank) { // look for next non blank if (input[i] == ' ') { continue; } else { n++; blank = false; } } else { // look for next blank if (input[i] != ' ') { continue; } else { blank = true; } } } char ** argv = new char * [n+2]; argv[0] = CoinStrdup("cbc"); size_t i = 0; while (input[i] == ' ') i++; for (int j = 0; j < n; j++) { size_t saveI = i; for (; i < length; i++) { // look for next blank if (input[i] != ' ') { continue; } else { break; } } input[i++] = '\0'; argv[j+1] = CoinStrdup(input + saveI); while (input[i] == ' ') i++; } argv[n+1] = CoinStrdup("-quit"); free(input); currentBranchModel = NULL; CbcOrClpRead_mode = 1; CbcOrClpReadCommand = stdin; int returnCode = CbcMain1(n + 2, const_cast(argv), model, callBack,parameterData); for (int k = 0; k < n + 2; k++) free(argv[k]); delete [] argv; return returnCode; } static CbcSolverUsefulData staticParameterData; int callCbc1(const char * input2, CbcModel & model, int callBack(CbcModel * currentSolver, int whereFrom)) { // allow interrupts and printing #ifndef CBC_NO_INTERRUPT staticParameterData.useSignalHandler_=true; #endif #ifndef CBC_NO_PRINTING staticParameterData.noPrinting_ = false; #endif return callCbc1(input2,model,callBack,staticParameterData); } CglPreProcess * cbcPreProcessPointer=NULL; int CbcClpUnitTest (const CbcModel & saveModel, const std::string& dirMiplib, int testSwitch, const double * stuff); int CbcMain1 (int argc, const char *argv[], CbcModel & model) { return CbcMain1(argc, argv, model, dummyCallBack); } #ifdef CBC_THREAD_SAFE // Copies of some input decoding static std::string CoinReadGetCommand(int &whichArgument, int argc, const char *argv[]) { std::string field; if (whichArgument < argc) field = argv[whichArgument++]; else field = "quit"; if (field[0] == '-') field = field.substr(1); return field; } static std::string CoinReadGetString(int &whichArgument, int argc, const char *argv[]) { std::string field; if (whichArgument < argc) field = argv[whichArgument++]; else field = ""; return field; } // valid 0 - okay, 1 bad, 2 not there static int CoinReadGetIntField(int &whichArgument, int argc, const char *argv[], int * valid) { std::string field; if (whichArgument < argc) field = argv[whichArgument++]; else field = "0"; long int value = 0; const char * start = field.c_str(); char * endPointer = NULL; // check valid value = strtol(start, &endPointer, 10); if (*endPointer == '\0') { *valid = 0; } else { *valid = 1; std::cout << "String of " << field; } return static_cast(value); } static double CoinReadGetDoubleField(int &whichArgument, int argc, const char *argv[], int * valid) { std::string field; if (whichArgument < argc) field = argv[whichArgument++]; else field = "0.0"; double value = 0.0; const char * start = field.c_str(); char * endPointer = NULL; // check valid value = strtod(start, &endPointer); if (*endPointer == '\0') { *valid = 0; } else { *valid = 1; std::cout << "String of " << field; } return value; } // Redefine all #define CoinReadGetCommand(x,y) CoinReadGetCommand(whichArgument,x,y) #define CoinReadGetString(x,y) CoinReadGetString(whichArgument,x,y) #define CoinReadGetIntField(x,y,z) CoinReadGetIntField(whichArgument,x,y,z) #define CoinReadGetDoubleField(x,y,z) CoinReadGetDoubleField(whichArgument,x,y,z) #endif // Default Constructor CbcSolverUsefulData::CbcSolverUsefulData() { totalTime_ = 0.0; noPrinting_ = true; useSignalHandler_ = false; establishParams(numberParameters_,parameters_); } /* Copy constructor . */ CbcSolverUsefulData::CbcSolverUsefulData(const CbcSolverUsefulData & rhs) { totalTime_ = rhs.totalTime_; noPrinting_ = rhs.noPrinting_; useSignalHandler_ = rhs.useSignalHandler_; numberParameters_ = rhs.numberParameters_; memcpy(parameters_,rhs.parameters_,sizeof(parameters_)); } // Assignment operator CbcSolverUsefulData & CbcSolverUsefulData::operator=(const CbcSolverUsefulData& rhs) { if (this != &rhs) { totalTime_ = rhs.totalTime_; noPrinting_ = rhs.noPrinting_; useSignalHandler_ = rhs.useSignalHandler_; numberParameters_ = rhs.numberParameters_; memcpy(parameters_,rhs.parameters_,sizeof(parameters_)); } return *this; } // Destructor CbcSolverUsefulData::~CbcSolverUsefulData () { } /* Meaning of whereFrom: 1 after initial solve by dualsimplex etc 2 after preprocessing 3 just before branchAndBound (so user can override) 4 just after branchAndBound (before postprocessing) 5 after postprocessing 6 after a user called heuristic phase */ int CbcMain1 (int argc, const char *argv[], CbcModel & model, int callBack(CbcModel * currentSolver, int whereFrom)) { // allow interrupts and printing staticParameterData.noPrinting_ = false; staticParameterData.useSignalHandler_=true; return CbcMain1(argc,argv,model,callBack,staticParameterData); } /* Meaning of whereFrom: 1 after initial solve by dualsimplex etc 2 after preprocessing 3 just before branchAndBound (so user can override) 4 just after branchAndBound (before postprocessing) 5 after postprocessing 6 after a user called heuristic phase */ int CbcMain1 (int argc, const char *argv[], CbcModel & model, int callBack(CbcModel * currentSolver, int whereFrom), CbcSolverUsefulData & parameterData) { CbcOrClpParam * parameters_ = parameterData.parameters_; int numberParameters_ = parameterData.numberParameters_; double totalTime = parameterData.totalTime_; bool noPrinting = parameterData.noPrinting_; bool useSignalHandler = parameterData.useSignalHandler_; CbcModel & model_ = model; #ifdef CBC_THREAD_SAFE // Initialize argument int whichArgument=1; #endif #ifdef CBC_USE_INITIAL_TIME if (model_.useElapsedTime()) model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay()); else model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); #endif CbcModel * babModel_ = NULL; int returnMode = 1; CbcOrClpRead_mode = 1; int statusUserFunction_[1]; int numberUserFunctions_ = 1; // to allow for ampl // Statistics double statistics_seconds = 0.0, statistics_obj = 0.0; double statistics_sys_seconds = 0.0, statistics_elapsed_seconds = 0.0; CoinWallclockTime(); double statistics_continuous = 0.0, statistics_tighter = 0.0; double statistics_cut_time = 0.0; int statistics_nodes = 0, statistics_iterations = 0; int statistics_nrows = 0, statistics_ncols = 0; int statistics_nprocessedrows = 0, statistics_nprocessedcols = 0; std::string statistics_result; int * statistics_number_cuts = NULL; const char ** statistics_name_generators = NULL; int statistics_number_generators = 0; memset(statusUserFunction_, 0, numberUserFunctions_*sizeof(int)); /* Note This is meant as a stand-alone executable to do as much of coin as possible. It should only have one solver known to it. */ CoinMessageHandler * generalMessageHandler = model_.messageHandler(); generalMessageHandler->setPrefix(false); #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * originalSolver = dynamic_cast (model_.solver()); assert (originalSolver); // Move handler across if not default if (!originalSolver->defaultHandler() && originalSolver->getModelPtr()->defaultHandler()) originalSolver->getModelPtr()->passInMessageHandler(originalSolver->messageHandler()); CoinMessages generalMessages = originalSolver->getModelPtr()->messages(); char generalPrint[10000]; if (originalSolver->getModelPtr()->logLevel() == 0) noPrinting = true; #elif CBC_OTHER_SOLVER==1 OsiCpxSolverInterface * originalSolver = dynamic_cast (model_.solver()); assert (originalSolver); OsiClpSolverInterface dummySolver; OsiCpxSolverInterface * clpSolver = originalSolver; CoinMessages generalMessages = dummySolver.getModelPtr()->messages(); char generalPrint[10000]; noPrinting = true; #endif bool noPrinting_ = noPrinting; // Say not in integer int integerStatus = -1; // Say no resolve after cuts model_.setResolveAfterTakeOffCuts(false); // see if log in list for (int i = 1; i < argc; i++) { if (!strncmp(argv[i], "log", 3)) { const char * equals = strchr(argv[i], '='); if (equals && atoi(equals + 1) != 0) noPrinting_ = false; else noPrinting_ = true; break; } else if (!strncmp(argv[i], "-log", 4) && i < argc - 1) { if (atoi(argv[i+1]) != 0) noPrinting_ = false; else noPrinting_ = true; break; } } double time0; double time0Elapsed = CoinGetTimeOfDay(); { double time1 = CoinCpuTime(), time2; time0 = time1; double time1Elapsed = time0Elapsed; bool goodModel = (originalSolver->getNumCols()) ? true : false; // register signal handler //CoinSighandler_t saveSignal=signal(SIGINT,signal_handler); #if CBC_QUIET < 2 if (useSignalHandler) signal(SIGINT, signal_handler); #endif // Set up all non-standard stuff int cutPass = -1234567; int cutPassInTree = -1234567; int tunePreProcess = 0; int testOsiParameters = -1; // 0 normal, 1 from ampl or MIQP etc (2 allows cuts) int complicatedInteger = 0; OsiSolverInterface * solver = model_.solver(); if (noPrinting_) setCbcOrClpPrinting(false); #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); ClpSimplex * lpSolver = clpSolver->getModelPtr(); if (noPrinting_) { lpSolver->setLogLevel(0); } #else ClpSimplex * lpSolver = NULL; #endif // For priorities etc int * priorities = NULL; int * branchDirection = NULL; double * pseudoDown = NULL; double * pseudoUp = NULL; double * solutionIn = NULL; int * prioritiesIn = NULL; std::vector< std::pair< std::string, double > > mipStart; std::vector< std::pair< std::string, double > > mipStartBefore; int numberSOS = 0; int * sosStart = NULL; int * sosIndices = NULL; char * sosType = NULL; double * sosReference = NULL; int * cut = NULL; int * sosPriority = NULL; CglStored storedAmpl; CoinModel * coinModel = NULL; CoinModel saveCoinModel; CoinModel saveTightenedModel; int * whichColumn = NULL; int * knapsackStart = NULL; int * knapsackRow = NULL; int numberKnapsack = 0; #ifdef COIN_HAS_ASL ampl_info info; { memset(&info, 0, sizeof(info)); if (argc > 2 && !strcmp(argv[2], "-AMPL")) { statusUserFunction_[0] = 1; // see if log in list noPrinting_ = true; for (int i = 1; i < argc; i++) { if (!strncmp(argv[i], "log", 3)) { const char * equals = strchr(argv[i], '='); if (equals && atoi(equals + 1) > 0) { noPrinting_ = false; info.logLevel = atoi(equals + 1); int log = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_); parameters_[log].setIntValue(info.logLevel); // mark so won't be overWritten info.numberRows = -1234567; break; } } } union { void * voidModel; CoinModel * model; } coinModelStart; coinModelStart.model = NULL; int returnCode = readAmpl(&info, argc, const_cast(argv), & coinModelStart.voidModel); coinModel = coinModelStart.model; if (returnCode) return returnCode; CbcOrClpRead_mode = 2; // so will start with parameters // see if log in list (including environment) for (int i = 1; i < info.numberArguments; i++) { if (!strcmp(info.arguments[i], "log")) { if (i < info.numberArguments - 1 && atoi(info.arguments[i+1]) > 0) noPrinting_ = false; break; } } if (noPrinting_) { model_.messageHandler()->setLogLevel(0); setCbcOrClpPrinting(false); } if (!noPrinting_) printf("%d rows, %d columns and %d elements\n", info.numberRows, info.numberColumns, info.numberElements); #ifdef COIN_HAS_LINK if (!coinModel) { #endif solver->loadProblem(info.numberColumns, info.numberRows, info.starts, info.rows, info.elements, info.columnLower, info.columnUpper, info.objective, info.rowLower, info.rowUpper); // take off cuts if ampl wants that if (info.cut && 0) { printf("AMPL CUTS OFF until global cuts fixed\n"); info.cut = NULL; } if (info.cut) { int numberRows = info.numberRows; int * whichRow = new int [numberRows]; // Row copy const CoinPackedMatrix * matrixByRow = solver->getMatrixByRow(); const double * elementByRow = matrixByRow->getElements(); const int * column = matrixByRow->getIndices(); const CoinBigIndex * rowStart = matrixByRow->getVectorStarts(); const int * rowLength = matrixByRow->getVectorLengths(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int nDelete = 0; for (int iRow = 0; iRow < numberRows; iRow++) { if (info.cut[iRow]) { whichRow[nDelete++] = iRow; int start = rowStart[iRow]; storedAmpl.addCut(rowLower[iRow], rowUpper[iRow], rowLength[iRow], column + start, elementByRow + start); } } solver->deleteRows(nDelete, whichRow); delete [] whichRow; } #ifdef COIN_HAS_LINK } else { #ifndef CBC_OTHER_SOLVER // save saveCoinModel = *coinModel; // load from coin model OsiSolverLink solver1; OsiSolverInterface * solver2 = solver1.clone(); model_.assignSolver(solver2, false); OsiSolverLink * si = dynamic_cast(model_.solver()) ; assert (si != NULL); si->setDefaultMeshSize(0.001); // need some relative granularity si->setDefaultBound(100.0); double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue(); if (dextra3) si->setDefaultMeshSize(dextra3); si->setDefaultBound(100000.0); si->setIntegerPriority(1000); si->setBiLinearPriority(10000); CoinModel * model2 = reinterpret_cast (coinModel); int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_)].intValue(); si->load(*model2, true, logLevel); // redo solver = model_.solver(); clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); lpSolver = clpSolver->getModelPtr(); clpSolver->messageHandler()->setLogLevel(0) ; testOsiParameters = 0; parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].setIntValue(0); complicatedInteger = 1; if (info.cut) { printf("Sorry - can't do cuts with LOS as ruins delicate row order\n"); abort(); int numberRows = info.numberRows; int * whichRow = new int [numberRows]; // Row copy const CoinPackedMatrix * matrixByRow = solver->getMatrixByRow(); const double * elementByRow = matrixByRow->getElements(); const int * column = matrixByRow->getIndices(); const CoinBigIndex * rowStart = matrixByRow->getVectorStarts(); const int * rowLength = matrixByRow->getVectorLengths(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int nDelete = 0; for (int iRow = 0; iRow < numberRows; iRow++) { if (info.cut[iRow]) { whichRow[nDelete++] = iRow; int start = rowStart[iRow]; storedAmpl.addCut(rowLower[iRow], rowUpper[iRow], rowLength[iRow], column + start, elementByRow + start); } } solver->deleteRows(nDelete, whichRow); // and special matrix si->cleanMatrix()->deleteRows(nDelete, whichRow); delete [] whichRow; } #endif } #endif // If we had a solution use it if (info.primalSolution) { solver->setColSolution(info.primalSolution); } // status if (info.rowStatus) { unsigned char * statusArray = lpSolver->statusArray(); int i; for (i = 0; i < info.numberColumns; i++) statusArray[i] = static_cast(info.columnStatus[i]); statusArray += info.numberColumns; for (i = 0; i < info.numberRows; i++) statusArray[i] = static_cast(info.rowStatus[i]); CoinWarmStartBasis * basis = lpSolver->getBasis(); solver->setWarmStart(basis); delete basis; } freeArrays1(&info); // modify objective if necessary solver->setObjSense(info.direction); solver->setDblParam(OsiObjOffset, -info.offset); if (info.offset) { sprintf(generalPrint, "Ampl objective offset is %g", info.offset); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } // Set integer variables (unless nonlinear when set) if (!info.nonLinear) { for (int i = info.numberColumns - info.numberIntegers; i < info.numberColumns; i++) solver->setInteger(i); } goodModel = true; // change argc etc argc = info.numberArguments; argv = const_cast(info.arguments); } } #endif // default action on import int allowImportErrors = 0; int keepImportNames = 1; int doIdiot = -1; int outputFormat = 2; int slpValue = -1; int cppValue = -1; int printOptions = 0; int printMode = 0; int presolveOptions = 0; int substitution = 3; int dualize = 3; int doCrash = 0; int doVector = 0; int doSprint = -1; int doScaling = 4; // set reasonable defaults int preSolve = 5; int preProcess = 4; bool useStrategy = false; bool preSolveFile = false; bool strongChanged = false; bool pumpChanged = false; double djFix = 1.0e100; double tightenFactor = 0.0; const char dirsep = CoinFindDirSeparator(); std::string directory; std::string dirSample; std::string dirNetlib; std::string dirMiplib; if (dirsep == '/') { directory = "./"; dirSample = "../../Data/Sample/"; dirNetlib = "../../Data/Netlib/"; dirMiplib = "../../Data/miplib3/"; } else { directory = ".\\"; dirSample = "..\\..\\..\\..\\Data\\Sample\\"; dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; } std::string defaultDirectory = directory; std::string importFile = ""; std::string exportFile = "default.mps"; std::string importBasisFile = ""; std::string importPriorityFile = ""; std::string debugFile = ""; std::string printMask = ""; double * debugValues = NULL; int numberDebugValues = -1; int basisHasValues = 0; std::string exportBasisFile = "default.bas"; std::string saveFile = "default.prob"; std::string restoreFile = "default.prob"; std::string solutionFile = "stdout"; std::string solutionSaveFile = "solution.file"; int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_); int log = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_); #ifndef CBC_OTHER_SOLVER double normalIncrement = model_.getCutoffIncrement();; #endif if (testOsiParameters >= 0) { // trying nonlinear - switch off some stuff preProcess = 0; } // Set up likely cut generators and defaults int nodeStrategy = 0; bool dominatedCuts = false; int doSOS = 1; int verbose = 0; CglGomory gomoryGen; // try larger limit gomoryGen.setLimitAtRoot(1000); gomoryGen.setLimit(50); // set default action (0=off,1=on,2=root) int gomoryAction = 3; CglProbing probingGen; probingGen.setUsingObjective(1); probingGen.setMaxPass(1); probingGen.setMaxPassRoot(1); // Number of unsatisfied variables to look at probingGen.setMaxProbe(10); probingGen.setMaxProbeRoot(50); // How far to follow the consequences probingGen.setMaxLook(10); probingGen.setMaxLookRoot(50); probingGen.setMaxLookRoot(10); // Only look at rows with fewer than this number of elements probingGen.setMaxElements(200); probingGen.setMaxElementsRoot(300); probingGen.setRowCuts(3); // set default action (0=off,1=on,2=root) int probingAction = 1; CglKnapsackCover knapsackGen; //knapsackGen.switchOnExpensive(); //knapsackGen.setMaxInKnapsack(100); // set default action (0=off,1=on,2=root) int knapsackAction = 3; CglRedSplit redsplitGen; //redsplitGen.setLimit(100); // set default action (0=off,1=on,2=root) // Off as seems to give some bad cuts int redsplitAction = 0; CglRedSplit2 redsplit2Gen; //redsplit2Gen.setLimit(100); // set default action (0=off,1=on,2=root) // Off int redsplit2Action = 0; CglGMI GMIGen; //GMIGen.setLimit(100); // set default action (0=off,1=on,2=root) // Off int GMIAction = 0; CglFakeClique cliqueGen(NULL, false); //CglClique cliqueGen(false,true); cliqueGen.setStarCliqueReport(false); cliqueGen.setRowCliqueReport(false); cliqueGen.setMinViolation(0.1); // set default action (0=off,1=on,2=root) int cliqueAction = 3; // maxaggr,multiply,criterion(1-3) CglMixedIntegerRounding2 mixedGen(1, true, 1); // set default action (0=off,1=on,2=root) int mixedAction = 3; mixedGen.setDoPreproc(1); // safer (and better) CglFlowCover flowGen; // set default action (0=off,1=on,2=root) int flowAction = 3; CglTwomir twomirGen; twomirGen.setMaxElements(250); // set default action (0=off,1=on,2=root) int twomirAction = 3; #ifndef DEBUG_MALLOC CglLandP landpGen; landpGen.validator().setMinViolation(1.0e-4); #endif // set default action (0=off,1=on,2=root) int landpAction = 0; CglResidualCapacity residualCapacityGen; residualCapacityGen.setDoPreproc(1); // always preprocess // set default action (0=off,1=on,2=root) int residualCapacityAction = 0; CglZeroHalf zerohalfGen; //zerohalfGen.switchOnExpensive(); // set default action (0=off,1=on,2=root) int zerohalfAction = 0; // Stored cuts //bool storedCuts = false; int useCosts = 0; // don't use input solution int useSolution = -1; // total number of commands read int numberGoodCommands = 0; // Set false if user does anything advanced bool defaultSettings = true; // Hidden stuff for barrier int choleskyType = 0; int gamma = 0; int scaleBarrier = 0; int doKKT = 0; int crossover = 2; // do crossover unless quadratic bool biLinearProblem=false; // For names int lengthName = 0; std::vector rowNames; std::vector columnNames; // Default strategy stuff { // try changing tolerance at root #define MORE_CUTS #ifdef MORE_CUTS gomoryGen.setAwayAtRoot(0.005); twomirGen.setAwayAtRoot(0.005); twomirGen.setAway(0.01); //twomirGen.setMirScale(1,1); //twomirGen.setTwomirScale(1,1); //twomirGen.setAMax(2); #else gomoryGen.setAwayAtRoot(0.01); twomirGen.setAwayAtRoot(0.01); twomirGen.setAway(0.01); #endif int iParam; iParam = whichParam(CBC_PARAM_INT_DIVEOPT, numberParameters_, parameters_); parameters_[iParam].setIntValue(3); iParam = whichParam(CBC_PARAM_INT_FPUMPITS, numberParameters_, parameters_); parameters_[iParam].setIntValue(30); iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_); parameters_[iParam].setIntValue(1005043); initialPumpTune = 1005043; iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, numberParameters_, parameters_); parameters_[iParam].setIntValue(6); tunePreProcess = 6; iParam = whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_); parameters_[iParam].setCurrentOption("on"); iParam = whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_); parameters_[iParam].setCurrentOption("on"); iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_); parameters_[iParam].setCurrentOption("on"); probingAction = 3; //parameters_[iParam].setCurrentOption("forceOnStrong"); //probingAction = 8; } std::string field; #if CBC_QUIET == 0 if (!noPrinting_) { sprintf(generalPrint, "Welcome to the CBC MILP Solver \n"); if (strcmp(CBC_VERSION, "trunk")){ sprintf(generalPrint + strlen(generalPrint), "Version: %s \n", CBC_VERSION); }else{ sprintf(generalPrint + strlen(generalPrint), "Version: Trunk (unstable) \n"); } sprintf(generalPrint + strlen(generalPrint), "Build Date: %s \n", __DATE__); #ifdef CBC_SVN_REV sprintf(generalPrint + strlen(generalPrint), "Revision Number: %d \n", CBC_SVN_REV); #endif generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; // Print command line if (argc > 1) { bool foundStrategy = false; sprintf(generalPrint, "command line - "); for (int i = 0; i < argc; i++) { if (!argv[i]) break; if (strstr(argv[i], "strat")) foundStrategy = true; sprintf(generalPrint + strlen(generalPrint), "%s ", argv[i]); } if (!foundStrategy) sprintf(generalPrint + strlen(generalPrint), "(default strategy 1)"); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } #endif while (1) { // next command field = CoinReadGetCommand(argc, argv); // Reset time time1 = CoinCpuTime(); time1Elapsed = CoinGetTimeOfDay(); // adjust field if has odd trailing characters char temp [200]; strcpy(temp, field.c_str()); int length = static_cast(strlen(temp)); for (int k = length - 1; k >= 0; k--) { if (temp[k] < ' ') length--; else break; } temp[length] = '\0'; field = temp; // exit if null or similar if (!field.length()) { if (numberGoodCommands == 1 && goodModel) { // we just had file name - do branch and bound field = "branch"; } else if (!numberGoodCommands) { // let's give the sucker a hint std::cout << "CoinSolver takes input from arguments ( - switches to stdin)" << std::endl << "Enter ? for list of commands or help" << std::endl; field = "-"; } else { break; } } // see if ? at end size_t numberQuery = 0; if (field != "?" && field != "???") { size_t length = field.length(); size_t i; for (i = length - 1; i > 0; i--) { if (field[i] == '?') numberQuery++; else break; } field = field.substr(0, length - numberQuery); } // find out if valid command int iParam; int numberMatches = 0; int firstMatch = -1; for ( iParam = 0; iParam < numberParameters_; iParam++ ) { int match = parameters_[iParam].matches(field); if (match == 1) { numberMatches = 1; firstMatch = iParam; break; } else { if (match && firstMatch < 0) firstMatch = iParam; numberMatches += match >> 1; } } if (iParam < numberParameters_ && !numberQuery) { // found CbcOrClpParam found = parameters_[iParam]; CbcOrClpParameterType type = found.type(); int valid; numberGoodCommands++; if (type == CBC_PARAM_ACTION_BAB && goodModel) { #ifndef CBC_USE_INITIAL_TIME if (model_.useElapsedTime()) model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay()); else model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime()); #endif biLinearProblem=false; // check if any integers #ifndef CBC_OTHER_SOLVER #ifdef COIN_HAS_ASL if (info.numberSos && doSOS && statusUserFunction_[0]) { // SOS numberSOS = info.numberSos; } #endif lpSolver = clpSolver->getModelPtr(); if (!lpSolver->integerInformation() && !numberSOS && !clpSolver->numberSOS() && !model_.numberObjects() && !clpSolver->numberObjects()) type = CLP_PARAM_ACTION_DUALSIMPLEX; #endif } if (type == CBC_PARAM_GENERALQUERY) { bool evenHidden = false; int printLevel = parameters_[whichParam(CLP_PARAM_STR_ALLCOMMANDS, numberParameters_, parameters_)].currentOptionAsInteger(); int convertP[] = {2, 1, 0}; printLevel = convertP[printLevel]; if ((verbose&8) != 0) { // even hidden evenHidden = true; verbose &= ~8; } #ifdef COIN_HAS_ASL if (verbose < 4 && statusUserFunction_[0]) verbose += 4; #endif if (verbose < 4) { std::cout << "In argument list keywords have leading - " ", -stdin or just - switches to stdin" << std::endl; std::cout << "One command per line (and no -)" << std::endl; std::cout << "abcd? gives list of possibilities, if only one + explanation" << std::endl; std::cout << "abcd?? adds explanation, if only one fuller help" << std::endl; std::cout << "abcd without value (where expected) gives current value" << std::endl; std::cout << "abcd value sets value" << std::endl; std::cout << "Commands are:" << std::endl; } else { std::cout << "Cbc options are set within AMPL with commands like:" << std::endl << std::endl; std::cout << " option cbc_options \"cuts=root log=2 feas=on slog=1\"" << std::endl << std::endl; std::cout << "only maximize, dual, primal, help and quit are recognized without =" << std::endl; } int maxAcross = 10; if ((verbose % 4) != 0) maxAcross = 1; int limits[] = {1, 51, 101, 151, 201, 251, 301, 351, 401}; std::vector types; types.push_back("Double parameters:"); types.push_back("Branch and Cut double parameters:"); types.push_back("Integer parameters:"); types.push_back("Branch and Cut integer parameters:"); types.push_back("Keyword parameters:"); types.push_back("Branch and Cut keyword parameters:"); types.push_back("Actions or string parameters:"); types.push_back("Branch and Cut actions:"); int iType; for (iType = 0; iType < 8; iType++) { int across = 0; int lengthLine = 0; if ((verbose % 4) != 0) std::cout << std::endl; std::cout << types[iType] << std::endl; if ((verbose&2) != 0) std::cout << std::endl; for ( iParam = 0; iParam < numberParameters_; iParam++ ) { int type = parameters_[iParam].type(); //printf("%d type %d limits %d %d display %d\n",iParam, // type,limits[iType],limits[iType+1],parameters_[iParam].displayThis()); if ((parameters_[iParam].displayThis() >= printLevel || evenHidden) && type >= limits[iType] && type < limits[iType+1]) { // but skip if not useful for ampl (and in ampl mode) if (verbose >= 4 && (parameters_[iParam].whereUsed()&4) == 0) continue; if (!across) { if ((verbose&2) != 0) std::cout << "Command "; } int length = parameters_[iParam].lengthMatchName() + 1; if (lengthLine + length > 80) { std::cout << std::endl; across = 0; lengthLine = 0; } std::cout << " " << parameters_[iParam].matchName(); lengthLine += length; across++; if (across == maxAcross) { across = 0; if ((verbose % 4) != 0) { // put out description as well if ((verbose&1) != 0) std::cout << " " << parameters_[iParam].shortHelp(); std::cout << std::endl; if ((verbose&2) != 0) { std::cout << "---- description" << std::endl; parameters_[iParam].printLongHelp(); std::cout << "----" << std::endl << std::endl; } } else { std::cout << std::endl; } } } } if (across) std::cout << std::endl; } } else if (type == CBC_PARAM_FULLGENERALQUERY) { std::cout << "Full list of commands is:" << std::endl; int maxAcross = 5; int limits[] = {1, 51, 101, 151, 201, 251, 301, 351, 401}; std::vector types; types.push_back("Double parameters:"); types.push_back("Branch and Cut double parameters:"); types.push_back("Integer parameters:"); types.push_back("Branch and Cut integer parameters:"); types.push_back("Keyword parameters:"); types.push_back("Branch and Cut keyword parameters:"); types.push_back("Actions or string parameters:"); types.push_back("Branch and Cut actions:"); int iType; for (iType = 0; iType < 8; iType++) { int across = 0; std::cout << types[iType] << " "; for ( iParam = 0; iParam < numberParameters_; iParam++ ) { int type = parameters_[iParam].type(); if (type >= limits[iType] && type < limits[iType+1]) { if (!across) std::cout << " "; std::cout << parameters_[iParam].matchName() << " "; across++; if (across == maxAcross) { std::cout << std::endl; across = 0; } } } if (across) std::cout << std::endl; } } else if (type < 101) { // get next field as double double value = CoinReadGetDoubleField(argc, argv, &valid); if (!valid) { if (type < 51) { int returnCode; const char * message = parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode); if (!noPrinting_ && strlen(message)) { generalMessageHandler->message(CLP_GENERAL, generalMessages) << message << CoinMessageEol; } } else if (type < 81) { int returnCode; const char * message = parameters_[iParam].setDoubleParameterWithMessage(model_, value, returnCode); if (!noPrinting_ && strlen(message)) { generalMessageHandler->message(CLP_GENERAL, generalMessages) << message << CoinMessageEol; } } else { int returnCode; const char * message = parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode); if (!noPrinting_ && strlen(message)) { generalMessageHandler->message(CLP_GENERAL, generalMessages) << message << CoinMessageEol; } switch (type) { case CBC_PARAM_DBL_DJFIX: djFix = value; #ifndef CBC_OTHER_SOLVER if (goodModel && djFix < 1.0e20) { // do some fixing clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver()); clpSolver->initialSolve(); lpSolver = clpSolver->getModelPtr(); int numberColumns = lpSolver->numberColumns(); int i; const char * type = lpSolver->integerInformation(); double * lower = lpSolver->columnLower(); double * upper = lpSolver->columnUpper(); double * solution = lpSolver->primalColumnSolution(); double * dj = lpSolver->dualColumnSolution(); int numberFixed = 0; double dextra4 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, numberParameters_, parameters_)].doubleValue(); if (dextra4) printf("Multiple for continuous dj fixing is %g\n", dextra4); for (i = 0; i < numberColumns; i++) { double djValue = dj[i]; if (!type[i]) djValue *= dextra4; if (type[i] || dextra4) { double value = solution[i]; if (value < lower[i] + 1.0e-5 && djValue > djFix) { solution[i] = lower[i]; upper[i] = lower[i]; numberFixed++; } else if (value > upper[i] - 1.0e-5 && djValue < -djFix) { solution[i] = upper[i]; lower[i] = upper[i]; numberFixed++; } } } sprintf(generalPrint, "%d columns fixed\n", numberFixed); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } #endif break; case CBC_PARAM_DBL_TIGHTENFACTOR: tightenFactor = value; if (!complicatedInteger) defaultSettings = false; // user knows what she is doing break; default: break; } } } else if (valid == 1) { std::cout << " is illegal for double parameter " << parameters_[iParam].name() << " value remains " << parameters_[iParam].doubleValue() << std::endl; } else { std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].doubleValue() << std::endl; } } else if (type < 201) { // get next field as int int value = CoinReadGetIntField(argc, argv, &valid); if (!valid) { if (type < 151) { if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEPASS) preSolve = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_IDIOT) doIdiot = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_SPRINT) doSprint = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_OUTPUTFORMAT) outputFormat = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_SLPVALUE) slpValue = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_CPP) cppValue = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEOPTIONS) presolveOptions = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_PRINTOPTIONS) printOptions = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_SUBSTITUTION) substitution = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_DUALIZE) dualize = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_PROCESSTUNE) tunePreProcess = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_USESOLUTION) useSolution = value; else if (parameters_[iParam].type() == CLP_PARAM_INT_VERBOSE) verbose = value; int returnCode; const char * message = parameters_[iParam].setIntParameterWithMessage(lpSolver, value, returnCode); if (!noPrinting_ && strlen(message)) { generalMessageHandler->message(CLP_GENERAL, generalMessages) << message << CoinMessageEol; } } else { if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASS) cutPass = value; else if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASSINTREE) cutPassInTree = value; else if (parameters_[iParam].type() == CBC_PARAM_INT_STRONGBRANCHING || parameters_[iParam].type() == CBC_PARAM_INT_NUMBERBEFORE) strongChanged = true; else if (parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE || parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE2 || parameters_[iParam].type() == CBC_PARAM_INT_FPUMPITS) pumpChanged = true; else if (parameters_[iParam].type() == CBC_PARAM_INT_EXPERIMENT) { int addFlags=0; if (value>=10) { addFlags = 1048576*(value/10); value = value % 10; parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, numberParameters_, parameters_)].setIntValue(value); } if (value >= 1) { int values[]={24003,280003,792003,24003,24003}; if (value>=2&&value<=3) { // swap default diving int iParam = whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_); parameters_[iParam].setCurrentOption("off"); iParam = whichParam(CBC_PARAM_STR_DIVINGP, numberParameters_, parameters_); parameters_[iParam].setCurrentOption("on"); } int extra4 = values[value-1]+addFlags; parameters_[whichParam(CBC_PARAM_INT_EXTRA4, numberParameters_, parameters_)].setIntValue(extra4); if (!noPrinting_) { generalMessageHandler->message(CLP_GENERAL, generalMessages) << "switching on global root cuts for gomory and knapsack" << CoinMessageEol; generalMessageHandler->message(CLP_GENERAL, generalMessages) << "using OSL factorization" << CoinMessageEol; generalMessageHandler->message(CLP_GENERAL, generalMessages) << "extra options - -rens on -extra4 " <factorization()->forceOtherFactorization(3); parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].setIntValue(100); parameters_[whichParam(CBC_PARAM_INT_CUTPASS, numberParameters_, parameters_)].setIntValue(1000); cutPass = 1000; parameters_[whichParam(CBC_PARAM_STR_RENS, numberParameters_, parameters_)].setCurrentOption("on"); } } else if (parameters_[iParam].type() == CBC_PARAM_INT_STRATEGY) { if (value == 0) { gomoryGen.setAwayAtRoot(0.05); int iParam; iParam = whichParam(CBC_PARAM_INT_DIVEOPT, numberParameters_, parameters_); parameters_[iParam].setIntValue(-1); iParam = whichParam(CBC_PARAM_INT_FPUMPITS, numberParameters_, parameters_); parameters_[iParam].setIntValue(20); iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_); parameters_[iParam].setIntValue(1003); initialPumpTune = 1003; iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, numberParameters_, parameters_); parameters_[iParam].setIntValue(0); tunePreProcess = 0; iParam = whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_); parameters_[iParam].setCurrentOption("off"); iParam = whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_); parameters_[iParam].setCurrentOption("off"); iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_); // but not if cuts off int jParam = whichParam(CBC_PARAM_STR_CUTSSTRATEGY, numberParameters_, parameters_); jParam = parameters_[jParam].currentOptionAsInteger(); if (jParam) { parameters_[iParam].setCurrentOption("on"); probingAction = 1; } else { parameters_[iParam].setCurrentOption("off"); probingAction = 0; } } } int returnCode; const char * message = parameters_[iParam].setIntParameterWithMessage(model_, value, returnCode); if (!noPrinting_ && strlen(message)) { generalMessageHandler->message(CLP_GENERAL, generalMessages) << message << CoinMessageEol; } } } else if (valid == 1) { std::cout << " is illegal for integer parameter " << parameters_[iParam].name() << " value remains " << parameters_[iParam].intValue() << std::endl; } else { std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].intValue() << std::endl; } } else if (type < 301) { // one of several strings std::string value = CoinReadGetString(argc, argv); int action = parameters_[iParam].parameterOption(value); if (action < 0) { if (value != "EOL") { // no match parameters_[iParam].printOptions(); } else { // print current value std::cout << parameters_[iParam].name() << " has value " << parameters_[iParam].currentOption() << std::endl; } } else { const char * message = parameters_[iParam].setCurrentOptionWithMessage(action); if (!noPrinting_ && strlen(message)) { generalMessageHandler->message(CLP_GENERAL, generalMessages) << message << CoinMessageEol; } // for now hard wired switch (type) { case CLP_PARAM_STR_DIRECTION: if (action == 0) lpSolver->setOptimizationDirection(1); else if (action == 1) lpSolver->setOptimizationDirection(-1); else lpSolver->setOptimizationDirection(0); break; case CLP_PARAM_STR_DUALPIVOT: if (action == 0) { ClpDualRowSteepest steep(3); lpSolver->setDualRowPivotAlgorithm(steep); } else if (action == 1) { ClpDualRowDantzig dantzig; //ClpDualRowSteepest dantzig(5); lpSolver->setDualRowPivotAlgorithm(dantzig); } else if (action == 2) { // partial steep ClpDualRowSteepest steep(2); lpSolver->setDualRowPivotAlgorithm(steep); } else { ClpDualRowSteepest steep; lpSolver->setDualRowPivotAlgorithm(steep); } break; case CLP_PARAM_STR_PRIMALPIVOT: if (action == 0) { ClpPrimalColumnSteepest steep(3); lpSolver->setPrimalColumnPivotAlgorithm(steep); } else if (action == 1) { ClpPrimalColumnSteepest steep(0); lpSolver->setPrimalColumnPivotAlgorithm(steep); } else if (action == 2) { ClpPrimalColumnDantzig dantzig; lpSolver->setPrimalColumnPivotAlgorithm(dantzig); } else if (action == 3) { ClpPrimalColumnSteepest steep(4); lpSolver->setPrimalColumnPivotAlgorithm(steep); } else if (action == 4) { ClpPrimalColumnSteepest steep(1); lpSolver->setPrimalColumnPivotAlgorithm(steep); } else if (action == 5) { ClpPrimalColumnSteepest steep(2); lpSolver->setPrimalColumnPivotAlgorithm(steep); } else if (action == 6) { ClpPrimalColumnSteepest steep(10); lpSolver->setPrimalColumnPivotAlgorithm(steep); } break; case CLP_PARAM_STR_SCALING: lpSolver->scaling(action); solver->setHintParam(OsiDoScale, action != 0, OsiHintTry); doScaling = action; break; case CLP_PARAM_STR_AUTOSCALE: lpSolver->setAutomaticScaling(action != 0); break; case CLP_PARAM_STR_SPARSEFACTOR: lpSolver->setSparseFactorization((1 - action) != 0); break; case CLP_PARAM_STR_BIASLU: lpSolver->factorization()->setBiasLU(action); break; case CLP_PARAM_STR_PERTURBATION: if (action == 0) lpSolver->setPerturbation(50); else lpSolver->setPerturbation(100); break; case CLP_PARAM_STR_ERRORSALLOWED: allowImportErrors = action; break; case CLP_PARAM_STR_INTPRINT: printMode = action; break; //case CLP_PARAM_NOTUSED_ALGORITHM: //algorithm = action; //defaultSettings=false; // user knows what she is doing //abort(); //break; case CLP_PARAM_STR_KEEPNAMES: keepImportNames = 1 - action; break; case CLP_PARAM_STR_PRESOLVE: if (action == 0) preSolve = 5; else if (action == 1) preSolve = 0; else if (action == 2) preSolve = 10; else preSolveFile = true; break; case CLP_PARAM_STR_PFI: lpSolver->factorization()->setForrestTomlin(action == 0); break; case CLP_PARAM_STR_FACTORIZATION: lpSolver->factorization()->forceOtherFactorization(action); break; case CLP_PARAM_STR_CRASH: doCrash = action; break; case CLP_PARAM_STR_VECTOR: doVector = action; break; case CLP_PARAM_STR_MESSAGES: lpSolver->messageHandler()->setPrefix(action != 0); break; case CLP_PARAM_STR_CHOLESKY: choleskyType = action; break; case CLP_PARAM_STR_GAMMA: gamma = action; break; case CLP_PARAM_STR_BARRIERSCALE: scaleBarrier = action; break; case CLP_PARAM_STR_KKT: doKKT = action; break; case CLP_PARAM_STR_CROSSOVER: crossover = action; break; case CLP_PARAM_STR_TIME_MODE: model_.setUseElapsedTime(action!=0); break; case CBC_PARAM_STR_SOS: doSOS = action; break; case CBC_PARAM_STR_GOMORYCUTS: defaultSettings = false; // user knows what she is doing gomoryAction = action; break; case CBC_PARAM_STR_PROBINGCUTS: defaultSettings = false; // user knows what she is doing probingAction = action; break; case CBC_PARAM_STR_KNAPSACKCUTS: defaultSettings = false; // user knows what she is doing knapsackAction = action; break; case CBC_PARAM_STR_REDSPLITCUTS: defaultSettings = false; // user knows what she is doing redsplitAction = action; break; case CBC_PARAM_STR_REDSPLIT2CUTS: defaultSettings = false; // user knows what she is doing redsplit2Action = action; break; case CBC_PARAM_STR_GMICUTS: defaultSettings = false; // user knows what she is doing GMIAction = action; break; case CBC_PARAM_STR_CLIQUECUTS: defaultSettings = false; // user knows what she is doing cliqueAction = action; break; case CBC_PARAM_STR_FLOWCUTS: defaultSettings = false; // user knows what she is doing flowAction = action; break; case CBC_PARAM_STR_MIXEDCUTS: defaultSettings = false; // user knows what she is doing mixedAction = action; break; case CBC_PARAM_STR_TWOMIRCUTS: defaultSettings = false; // user knows what she is doing twomirAction = action; break; case CBC_PARAM_STR_LANDPCUTS: defaultSettings = false; // user knows what she is doing landpAction = action; break; case CBC_PARAM_STR_RESIDCUTS: defaultSettings = false; // user knows what she is doing residualCapacityAction = action; break; case CBC_PARAM_STR_ZEROHALFCUTS: defaultSettings = false; // user knows what she is doing zerohalfAction = action; break; case CBC_PARAM_STR_ROUNDING: defaultSettings = false; // user knows what she is doing break; case CBC_PARAM_STR_FPUMP: defaultSettings = false; // user knows what she is doing break; case CBC_PARAM_STR_RINS: break; case CBC_PARAM_STR_DINS: break; case CBC_PARAM_STR_RENS: break; case CBC_PARAM_STR_CUTSSTRATEGY: gomoryAction = action; probingAction = action; knapsackAction = action; zerohalfAction = action; cliqueAction = action; flowAction = action; mixedAction = action; twomirAction = action; //landpAction = action; parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, numberParameters_, parameters_)].setCurrentOption(action); if (!action) { redsplitAction = action; parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, numberParameters_, parameters_)].setCurrentOption(action); redsplit2Action = action; parameters_[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, numberParameters_, parameters_)].setCurrentOption(action); GMIAction = action; parameters_[whichParam(CBC_PARAM_STR_GMICUTS, numberParameters_, parameters_)].setCurrentOption(action); landpAction = action; parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, numberParameters_, parameters_)].setCurrentOption(action); residualCapacityAction = action; parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, numberParameters_, parameters_)].setCurrentOption(action); } break; case CBC_PARAM_STR_HEURISTICSTRATEGY: parameters_[whichParam(CBC_PARAM_STR_ROUNDING, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_GREEDY, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_COMBINE, numberParameters_, parameters_)].setCurrentOption(action); //parameters_[whichParam(CBC_PARAM_STR_LOCALTREE,numberParameters_,parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_FPUMP, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_)].setCurrentOption(action); parameters_[whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_)].setCurrentOption(action); break; case CBC_PARAM_STR_GREEDY: case CBC_PARAM_STR_DIVINGS: case CBC_PARAM_STR_DIVINGC: case CBC_PARAM_STR_DIVINGF: case CBC_PARAM_STR_DIVINGG: case CBC_PARAM_STR_DIVINGL: case CBC_PARAM_STR_DIVINGP: case CBC_PARAM_STR_DIVINGV: case CBC_PARAM_STR_COMBINE: case CBC_PARAM_STR_PIVOTANDCOMPLEMENT: case CBC_PARAM_STR_PIVOTANDFIX: case CBC_PARAM_STR_RANDROUND: case CBC_PARAM_STR_LOCALTREE: case CBC_PARAM_STR_NAIVE: case CBC_PARAM_STR_CPX: defaultSettings = false; // user knows what she is doing break; case CBC_PARAM_STR_COSTSTRATEGY: useCosts = action; break; case CBC_PARAM_STR_NODESTRATEGY: nodeStrategy = action; break; case CBC_PARAM_STR_PREPROCESS: preProcess = action; break; default: //abort(); break; } } } else { // action if (type == CLP_PARAM_ACTION_EXIT) { #ifdef COIN_HAS_ASL if (statusUserFunction_[0]) { if (info.numberIntegers || info.numberBinary) { // integer } else { // linear } writeAmpl(&info); freeArrays2(&info); freeArgs(&info); } #endif break; // stop all } switch (type) { case CLP_PARAM_ACTION_DUALSIMPLEX: case CLP_PARAM_ACTION_PRIMALSIMPLEX: case CLP_PARAM_ACTION_SOLVECONTINUOUS: case CLP_PARAM_ACTION_BARRIER: if (goodModel) { // Say not in integer integerStatus = -1; double objScale = parameters_[whichParam(CLP_PARAM_DBL_OBJSCALE2, numberParameters_, parameters_)].doubleValue(); if (objScale != 1.0) { int iColumn; int numberColumns = lpSolver->numberColumns(); double * dualColumnSolution = lpSolver->dualColumnSolution(); ClpObjective * obj = lpSolver->objectiveAsObject(); assert(dynamic_cast (obj)); double offset; double * objective = obj->gradient(NULL, NULL, offset, true); for (iColumn = 0; iColumn < numberColumns; iColumn++) { dualColumnSolution[iColumn] *= objScale; objective[iColumn] *= objScale;; } int iRow; int numberRows = lpSolver->numberRows(); double * dualRowSolution = lpSolver->dualRowSolution(); for (iRow = 0; iRow < numberRows; iRow++) dualRowSolution[iRow] *= objScale; lpSolver->setObjectiveOffset(objScale*lpSolver->objectiveOffset()); } ClpSolve::SolveType method; ClpSolve::PresolveType presolveType; ClpSimplex * model2 = lpSolver; if (dualize) { bool tryIt = true; double fractionColumn = 1.0; double fractionRow = 1.0; if (dualize == 3) { dualize = 1; int numberColumns = lpSolver->numberColumns(); int numberRows = lpSolver->numberRows(); if (numberRows < 50000 || 5*numberColumns > numberRows) { tryIt = false; } else { fractionColumn = 0.1; fractionRow = 0.1; } } if (tryIt) { model2 = static_cast (model2)->dualOfModel(fractionRow, fractionColumn); if (model2) { sprintf(generalPrint, "Dual of model has %d rows and %d columns", model2->numberRows(), model2->numberColumns()); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; model2->setOptimizationDirection(1.0); } else { model2 = lpSolver; dualize = 0; } } else { dualize = 0; } } if (noPrinting_) lpSolver->setLogLevel(0); ClpSolve solveOptions; solveOptions.setPresolveActions(presolveOptions); solveOptions.setSubstitution(substitution); if (preSolve != 5 && preSolve) { presolveType = ClpSolve::presolveNumber; if (preSolve < 0) { preSolve = - preSolve; if (preSolve <= 100) { presolveType = ClpSolve::presolveNumber; sprintf(generalPrint, "Doing %d presolve passes - picking up non-costed slacks", preSolve); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; solveOptions.setDoSingletonColumn(true); } else { preSolve -= 100; presolveType = ClpSolve::presolveNumberCost; sprintf(generalPrint, "Doing %d presolve passes - picking up costed slacks", preSolve); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } } else if (preSolve) { presolveType = ClpSolve::presolveOn; } else { presolveType = ClpSolve::presolveOff; } solveOptions.setPresolveType(presolveType, preSolve); if (type == CLP_PARAM_ACTION_DUALSIMPLEX || type == CLP_PARAM_ACTION_SOLVECONTINUOUS) { method = ClpSolve::useDual; } else if (type == CLP_PARAM_ACTION_PRIMALSIMPLEX) { method = ClpSolve::usePrimalorSprint; } else { method = ClpSolve::useBarrier; if (crossover == 1) { method = ClpSolve::useBarrierNoCross; } else if (crossover == 2) { ClpObjective * obj = lpSolver->objectiveAsObject(); if (obj->type() > 1) { method = ClpSolve::useBarrierNoCross; presolveType = ClpSolve::presolveOff; solveOptions.setPresolveType(presolveType, preSolve); } } } solveOptions.setSolveType(method); if (preSolveFile) presolveOptions |= 0x40000000; solveOptions.setSpecialOption(4, presolveOptions); solveOptions.setSpecialOption(5, printOptions); if (doVector) { ClpMatrixBase * matrix = lpSolver->clpMatrix(); if (dynamic_cast< ClpPackedMatrix*>(matrix)) { ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); clpMatrix->makeSpecialColumnCopy(); } } if (method == ClpSolve::useDual) { // dual if (doCrash) solveOptions.setSpecialOption(0, 1, doCrash); // crash else if (doIdiot) solveOptions.setSpecialOption(0, 2, doIdiot); // possible idiot } else if (method == ClpSolve::usePrimalorSprint) { // primal // if slp turn everything off if (slpValue > 0) { doCrash = false; doSprint = 0; doIdiot = -1; solveOptions.setSpecialOption(1, 10, slpValue); // slp method = ClpSolve::usePrimal; } if (doCrash) { solveOptions.setSpecialOption(1, 1, doCrash); // crash } else if (doSprint > 0) { // sprint overrides idiot solveOptions.setSpecialOption(1, 3, doSprint); // sprint } else if (doIdiot > 0) { solveOptions.setSpecialOption(1, 2, doIdiot); // idiot } else if (slpValue <= 0) { if (doIdiot == 0) { if (doSprint == 0) solveOptions.setSpecialOption(1, 4); // all slack else solveOptions.setSpecialOption(1, 9); // all slack or sprint } else { if (doSprint == 0) solveOptions.setSpecialOption(1, 8); // all slack or idiot else solveOptions.setSpecialOption(1, 7); // initiative } } if (basisHasValues == -1) solveOptions.setSpecialOption(1, 11); // switch off values } else if (method == ClpSolve::useBarrier || method == ClpSolve::useBarrierNoCross) { int barrierOptions = choleskyType; if (scaleBarrier) barrierOptions |= 8; if (doKKT) barrierOptions |= 16; if (gamma) barrierOptions |= 32 * gamma; if (crossover == 3) barrierOptions |= 256; // try presolve in crossover solveOptions.setSpecialOption(4, barrierOptions); } model2->setMaximumSeconds(model_.getMaximumSeconds()); #ifdef COIN_HAS_LINK OsiSolverInterface * coinSolver = model_.solver(); OsiSolverLink * linkSolver = dynamic_cast< OsiSolverLink*> (coinSolver); if (!linkSolver) { model2->initialSolve(solveOptions); } else { // special solver int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].intValue(); double * solution = NULL; if (testOsiOptions < 10) { solution = linkSolver->nonlinearSLP(slpValue > 0 ? slpValue : 20 , 1.0e-5); } else if (testOsiOptions >= 10) { CoinModel coinModel = *linkSolver->coinModel(); ClpSimplex * tempModel = approximateSolution(coinModel, slpValue > 0 ? slpValue : 50 , 1.0e-5, 0); assert (tempModel); solution = CoinCopyOfArray(tempModel->primalColumnSolution(), coinModel.numberColumns()); model2->setObjectiveValue(tempModel->objectiveValue()); model2->setProblemStatus(tempModel->problemStatus()); model2->setSecondaryStatus(tempModel->secondaryStatus()); delete tempModel; } if (solution) { memcpy(model2->primalColumnSolution(), solution, CoinMin(model2->numberColumns(), linkSolver->coinModel()->numberColumns())*sizeof(double)); delete [] solution; } else { printf("No nonlinear solution\n"); } } #else model2->initialSolve(solveOptions); #endif { // map states /* clp status -1 - unknown e.g. before solve or if postSolve says not optimal 0 - optimal 1 - primal infeasible 2 - dual infeasible 3 - stopped on iterations or time 4 - stopped due to errors 5 - stopped by event handler (virtual int ClpEventHandler::event()) */ /* cbc status -1 before branchAndBound 0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found (or check value of best solution) 1 stopped - on maxnodes, maxsols, maxtime 2 difficulties so run was abandoned (5 event user programmed event occurred) */ /* clp secondary status of problem - may get extended 0 - none 1 - primal infeasible because dual limit reached OR probably primal infeasible but can't prove it (main status 4) 2 - scaled problem optimal - unscaled problem has primal infeasibilities 3 - scaled problem optimal - unscaled problem has dual infeasibilities 4 - scaled problem optimal - unscaled problem has primal and dual infeasibilities 5 - giving up in primal with flagged variables 6 - failed due to empty problem check 7 - postSolve says not optimal 8 - failed due to bad element check 9 - status was 3 and stopped on time 100 up - translation of enum from ClpEventHandler */ /* cbc secondary status of problem -1 unset (status_ will also be -1) 0 search completed with solution 1 linear relaxation not feasible (or worse than cutoff) 2 stopped on gap 3 stopped on nodes 4 stopped on time 5 stopped on user event 6 stopped on solutions 7 linear relaxation unbounded 8 stopped on iterations limit */ int iStatus = model2->status(); int iStatus2 = model2->secondaryStatus(); if (iStatus == 0) { iStatus2 = 0; if (found.type() == CBC_PARAM_ACTION_BAB) { // set best solution in model as no integers model_.setBestSolution(model2->primalColumnSolution(), model2->numberColumns(), model2->getObjValue()* model2->getObjSense()); } } else if (iStatus == 1) { iStatus = 0; iStatus2 = 1; // say infeasible } else if (iStatus == 2) { iStatus = 0; iStatus2 = 7; // say unbounded } else if (iStatus == 3) { iStatus = 1; if (iStatus2 == 9) // what does 9 mean ????????????? iStatus2 = 4; else iStatus2 = 3; // Use nodes - as closer than solutions } else if (iStatus == 4) { iStatus = 2; // difficulties iStatus2 = 0; } model_.setProblemStatus(iStatus); model_.setSecondaryStatus(iStatus2); if ((iStatus == 2 || iStatus2 > 0) && !noPrinting_) { std::string statusName[] = {"", "Stopped on ", "Run abandoned", "", "", "User ctrl-c"}; std::string minor[] = {"Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "iterations limit", "Problem proven infeasible"}; sprintf(generalPrint, "\nResult - %s%s\n\n", statusName[iStatus].c_str(), minor[iStatus2].c_str()); sprintf(generalPrint + strlen(generalPrint), "Enumerated nodes: 0\n"); sprintf(generalPrint + strlen(generalPrint), "Total iterations: 0\n"); #if CBC_QUIET == 0 sprintf(generalPrint + strlen(generalPrint), "Time (CPU seconds): %.2f\n", CoinCpuTime() - time0); sprintf(generalPrint + strlen(generalPrint), "Time (Wallclock Seconds): %.2f\n", CoinGetTimeOfDay()-time0Elapsed); #endif generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } //assert (lpSolver==clpSolver->getModelPtr()); assert (clpSolver == model_.solver()); clpSolver->setWarmStart(NULL); // and in babModel if exists if (babModel_) { babModel_->setProblemStatus(iStatus); babModel_->setSecondaryStatus(iStatus2); } int returnCode = callBack(&model, 1); if (returnCode) { // exit if user wants delete babModel_; babModel_ = NULL; return returnCode; } } basisHasValues = 1; if (dualize) { int returnCode = static_cast (lpSolver)->restoreFromDual(model2); if (model2->status() == 3) returnCode = 0; delete model2; if (returnCode && dualize != 2) lpSolver->primal(1); model2 = lpSolver; } #ifdef COIN_HAS_ASL if (statusUserFunction_[0]) { double value = model2->getObjValue() * model2->getObjSense(); char buf[300]; int pos = 0; int iStat = model2->status(); if (iStat == 0) { pos += sprintf(buf + pos, "optimal," ); } else if (iStat == 1) { // infeasible pos += sprintf(buf + pos, "infeasible,"); } else if (iStat == 2) { // unbounded pos += sprintf(buf + pos, "unbounded,"); } else if (iStat == 3) { pos += sprintf(buf + pos, "stopped on iterations or time,"); } else if (iStat == 4) { iStat = 7; pos += sprintf(buf + pos, "stopped on difficulties,"); } else if (iStat == 5) { iStat = 3; pos += sprintf(buf + pos, "stopped on ctrl-c,"); } else if (iStat == 6) { // bab infeasible pos += sprintf(buf + pos, "integer infeasible,"); iStat = 1; } else { pos += sprintf(buf + pos, "status unknown,"); iStat = 6; } info.problemStatus = iStat; info.objValue = value; pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), value); sprintf(buf + pos, "\n%d iterations", model2->getIterationCount()); free(info.primalSolution); int numberColumns = model2->numberColumns(); info.primalSolution = reinterpret_cast (malloc(numberColumns * sizeof(double))); CoinCopyN(model2->primalColumnSolution(), numberColumns, info.primalSolution); int numberRows = model2->numberRows(); free(info.dualSolution); info.dualSolution = reinterpret_cast (malloc(numberRows * sizeof(double))); CoinCopyN(model2->dualRowSolution(), numberRows, info.dualSolution); CoinWarmStartBasis * basis = model2->getBasis(); free(info.rowStatus); info.rowStatus = reinterpret_cast (malloc(numberRows * sizeof(int))); free(info.columnStatus); info.columnStatus = reinterpret_cast (malloc(numberColumns * sizeof(int))); // Put basis in int i; // free,basic,ub,lb are 0,1,2,3 for (i = 0; i < numberRows; i++) { CoinWarmStartBasis::Status status = basis->getArtifStatus(i); info.rowStatus[i] = status; } for (i = 0; i < numberColumns; i++) { CoinWarmStartBasis::Status status = basis->getStructStatus(i); info.columnStatus[i] = status; } // put buffer into info strcpy(info.buffer, buf); delete basis; } #endif } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_STATISTICS: if (goodModel) { // If presolve on look at presolved bool deleteModel2 = false; ClpSimplex * model2 = lpSolver; if (preSolve) { ClpPresolve pinfo; int presolveOptions2 = presolveOptions&~0x40000000; if ((presolveOptions2&0xffff) != 0) pinfo.setPresolveActions(presolveOptions2); pinfo.setSubstitution(substitution); if ((printOptions&1) != 0) pinfo.statistics(); double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].doubleValue(); model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, true, preSolve); if (model2) { printf("Statistics for presolved model\n"); deleteModel2 = true; } else { printf("Presolved model looks infeasible - will use unpresolved\n"); model2 = lpSolver; } } else { printf("Statistics for unpresolved model\n"); model2 = lpSolver; } statistics(lpSolver, model2); if (deleteModel2) delete model2; } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_TIGHTEN: if (goodModel) { int numberInfeasibilities = lpSolver->tightenPrimalBounds(); if (numberInfeasibilities) std::cout << "** Analysis indicates model infeasible" << std::endl; } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_PLUSMINUS: if (goodModel) { ClpMatrixBase * saveMatrix = lpSolver->clpMatrix(); ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(saveMatrix); if (clpMatrix) { ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix())); if (newMatrix->getIndices()) { lpSolver->replaceMatrix(newMatrix); delete saveMatrix; std::cout << "Matrix converted to +- one matrix" << std::endl; } else { std::cout << "Matrix can not be converted to +- 1 matrix" << std::endl; } } else { std::cout << "Matrix not a ClpPackedMatrix" << std::endl; } } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_OUTDUPROWS: dominatedCuts = true; #ifdef JJF_ZERO if (goodModel) { int numberRows = clpSolver->getNumRows(); //int nOut = outDupRow(clpSolver); CglDuplicateRow dupcuts(clpSolver); storedCuts = dupcuts.outDuplicates(clpSolver) != 0; int nOut = numberRows - clpSolver->getNumRows(); if (nOut && !noPrinting_) sprintf(generalPrint, "%d rows eliminated", nOut); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } #endif break; case CLP_PARAM_ACTION_NETWORK: if (goodModel) { ClpMatrixBase * saveMatrix = lpSolver->clpMatrix(); ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(saveMatrix); if (clpMatrix) { ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix())); if (newMatrix->getIndices()) { lpSolver->replaceMatrix(newMatrix); delete saveMatrix; std::cout << "Matrix converted to network matrix" << std::endl; } else { std::cout << "Matrix can not be converted to network matrix" << std::endl; } } else { std::cout << "Matrix not a ClpPackedMatrix" << std::endl; } } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CBC_PARAM_ACTION_DOHEURISTIC: if (goodModel) { int vubAction = parameters_[whichParam(CBC_PARAM_INT_VUBTRY, numberParameters_, parameters_)].intValue(); if (vubAction != -1) { // look at vubs // extra1 is number of ints to leave free // Just ones which affect >= extra3 int extra3 = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, numberParameters_, parameters_)].intValue(); /* 2 is cost above which to fix if feasible 3 is fraction of integer variables fixed if relaxing (0.97) 4 is fraction of all variables fixed if relaxing (0.0) */ double dextra[6]; int extra[5]; extra[1] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue(); int exp1 = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, numberParameters_, parameters_)].intValue(); if (exp1 == 4 && extra[1] == -1) extra[1] = 999998; dextra[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, numberParameters_, parameters_)].doubleValue(); dextra[2] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, numberParameters_, parameters_)].doubleValue(); dextra[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue(); dextra[4] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, numberParameters_, parameters_)].doubleValue(); dextra[5] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA5, numberParameters_, parameters_)].doubleValue(); if (!dextra[3]) dextra[3] = 0.97; //OsiClpSolverInterface * newSolver = fixVubs(model_, extra3, vubAction, generalMessageHandler, debugValues, dextra, extra); //assert (!newSolver); } // Actually do heuristics doHeuristics(&model_, 2, parameters_, numberParameters_, noPrinting_, initialPumpTune); if (model_.bestSolution()) { model_.setProblemStatus(1); model_.setSecondaryStatus(6); #ifdef COIN_HAS_ASL if (statusUserFunction_[0]) { double value = model_.getObjValue(); char buf[300]; int pos = 0; pos += sprintf(buf + pos, "feasible,"); info.problemStatus = 0; info.objValue = value; pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), value); sprintf(buf + pos, "\n0 iterations"); free(info.primalSolution); int numberColumns = lpSolver->numberColumns(); info.primalSolution = reinterpret_cast (malloc(numberColumns * sizeof(double))); CoinCopyN(model_.bestSolution(), numberColumns, info.primalSolution); int numberRows = lpSolver->numberRows(); free(info.dualSolution); info.dualSolution = reinterpret_cast (malloc(numberRows * sizeof(double))); CoinZeroN(info.dualSolution, numberRows); CoinWarmStartBasis * basis = lpSolver->getBasis(); free(info.rowStatus); info.rowStatus = reinterpret_cast (malloc(numberRows * sizeof(int))); free(info.columnStatus); info.columnStatus = reinterpret_cast (malloc(numberColumns * sizeof(int))); // Put basis in int i; // free,basic,ub,lb are 0,1,2,3 for (i = 0; i < numberRows; i++) { CoinWarmStartBasis::Status status = basis->getArtifStatus(i); info.rowStatus[i] = status; } for (i = 0; i < numberColumns; i++) { CoinWarmStartBasis::Status status = basis->getStructStatus(i); info.columnStatus[i] = status; } // put buffer into info strcpy(info.buffer, buf); delete basis; } #endif } int returnCode = callBack(&model, 6); if (returnCode) { // exit if user wants delete babModel_; babModel_ = NULL; return returnCode; } } break; case CBC_PARAM_ACTION_MIPLIB: // User can set options - main difference is lack of model and CglPreProcess goodModel = true; /* Run branch-and-cut. First set a few options -- node comparison, scaling. Print elapsed time at the end. */ case CBC_PARAM_ACTION_BAB: // branchAndBound // obsolete case STRENGTHEN: if (goodModel) { bool miplib = type == CBC_PARAM_ACTION_MIPLIB; int logLevel = parameters_[slog].intValue(); int truncateColumns=COIN_INT_MAX; int * newPriorities=NULL; // Reduce printout if (logLevel <= 1) { model_.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); } else { model_.solver()->setHintParam(OsiDoReducePrint, false, OsiHintTry); } { OsiSolverInterface * solver = model_.solver(); #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * si = dynamic_cast(solver) ; assert (si != NULL); si->getModelPtr()->scaling(doScaling); ClpSimplex * lpSolver = si->getModelPtr(); if (doVector) { ClpMatrixBase * matrix = lpSolver->clpMatrix(); if (dynamic_cast< ClpPackedMatrix*>(matrix)) { ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); clpMatrix->makeSpecialColumnCopy(); } } #elif CBC_OTHER_SOLVER==1 OsiCpxSolverInterface * si = dynamic_cast(solver) ; assert (si != NULL); #endif statistics_nrows = si->getNumRows(); statistics_ncols = si->getNumCols(); statistics_nprocessedrows = si->getNumRows(); statistics_nprocessedcols = si->getNumCols(); // See if quadratic #ifndef CBC_OTHER_SOLVER #ifdef COIN_HAS_LINK if (!complicatedInteger) { ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(lpSolver->objectiveAsObject())); if (obj) { preProcess = 0; int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].intValue(); parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].setIntValue(CoinMax(0, testOsiOptions)); // create coin model coinModel = lpSolver->createCoinModel(); assert (coinModel); // load from coin model OsiSolverLink solver1; OsiSolverInterface * solver2 = solver1.clone(); model_.assignSolver(solver2, false); OsiSolverLink * si = dynamic_cast(model_.solver()) ; assert (si != NULL); si->setDefaultMeshSize(0.001); // need some relative granularity si->setDefaultBound(100.0); double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue(); if (dextra3) si->setDefaultMeshSize(dextra3); si->setDefaultBound(1000.0); si->setIntegerPriority(1000); si->setBiLinearPriority(10000); biLinearProblem=true; si->setSpecialOptions2(2 + 4 + 8); CoinModel * model2 = coinModel; si->load(*model2, true, parameters_[log].intValue()); // redo solver = model_.solver(); clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); lpSolver = clpSolver->getModelPtr(); clpSolver->messageHandler()->setLogLevel(0) ; testOsiParameters = 0; complicatedInteger = 2; // allow cuts OsiSolverInterface * coinSolver = model_.solver(); OsiSolverLink * linkSolver = dynamic_cast< OsiSolverLink*> (coinSolver); if (linkSolver->quadraticModel()) { ClpSimplex * qp = linkSolver->quadraticModel(); //linkSolver->nonlinearSLP(CoinMax(slpValue,10),1.0e-5); qp->nonlinearSLP(CoinMax(slpValue, 40), 1.0e-5); qp->primal(1); OsiSolverLinearizedQuadratic solver2(qp); const double * solution = NULL; // Reduce printout solver2.setHintParam(OsiDoReducePrint, true, OsiHintTry); CbcModel model2(solver2); // Now do requested saves and modifications CbcModel * cbcModel = & model2; OsiSolverInterface * osiModel = model2.solver(); OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (osiModel); ClpSimplex * clpModel = osiclpModel->getModelPtr(); // Set changed values CglProbing probing; probing.setMaxProbe(10); probing.setMaxLook(10); probing.setMaxElements(200); probing.setMaxProbeRoot(50); probing.setMaxLookRoot(10); probing.setRowCuts(3); probing.setUsingObjective(true); cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1); cbcModel->cutGenerator(0)->setTiming(true); CglGomory gomory; gomory.setLimitAtRoot(512); cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1); cbcModel->cutGenerator(1)->setTiming(true); CglKnapsackCover knapsackCover; cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1); cbcModel->cutGenerator(2)->setTiming(true); CglRedSplit redSplit; cbcModel->addCutGenerator(&redSplit, -99, "RedSplit", true, false, false, -100, -1, -1); cbcModel->cutGenerator(3)->setTiming(true); CglClique clique; clique.setStarCliqueReport(false); clique.setRowCliqueReport(false); clique.setMinViolation(0.1); cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1); cbcModel->cutGenerator(4)->setTiming(true); CglMixedIntegerRounding2 mixedIntegerRounding2; cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1); cbcModel->cutGenerator(5)->setTiming(true); CglFlowCover flowCover; cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1); cbcModel->cutGenerator(6)->setTiming(true); CglTwomir twomir; twomir.setMaxElements(250); cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1); cbcModel->cutGenerator(7)->setTiming(true); CbcHeuristicFPump heuristicFPump(*cbcModel); heuristicFPump.setWhen(13); heuristicFPump.setMaximumPasses(20); heuristicFPump.setMaximumRetries(7); heuristicFPump.setHeuristicName("feasibility pump"); heuristicFPump.setInitialWeight(1); heuristicFPump.setFractionSmall(0.6); cbcModel->addHeuristic(&heuristicFPump); CbcRounding rounding(*cbcModel); rounding.setHeuristicName("rounding"); cbcModel->addHeuristic(&rounding); CbcHeuristicLocal heuristicLocal(*cbcModel); heuristicLocal.setHeuristicName("combine solutions"); heuristicLocal.setSearchType(1); heuristicLocal.setFractionSmall(0.6); cbcModel->addHeuristic(&heuristicLocal); CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel); heuristicGreedyCover.setHeuristicName("greedy cover"); cbcModel->addHeuristic(&heuristicGreedyCover); CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel); heuristicGreedyEquality.setHeuristicName("greedy equality"); cbcModel->addHeuristic(&heuristicGreedyEquality); CbcCompareDefault compare; cbcModel->setNodeComparison(compare); cbcModel->setNumberBeforeTrust(5); cbcModel->setSpecialOptions(2); cbcModel->messageHandler()->setLogLevel(1); cbcModel->setMaximumCutPassesAtRoot(-100); cbcModel->setMaximumCutPasses(1); cbcModel->setMinimumDrop(0.05); // For branchAndBound this may help clpModel->defaultFactorizationFrequency(); clpModel->setDualBound(1.0001e+08); clpModel->setPerturbation(50); osiclpModel->setSpecialOptions(193); osiclpModel->messageHandler()->setLogLevel(0); osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100); osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry); // You can save some time by switching off message building // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL); // Solve cbcModel->initialSolve(); if (clpModel->tightenPrimalBounds() != 0) { #ifndef DISALLOW_PRINTING std::cout << "Problem is infeasible - tightenPrimalBounds!" << std::endl; #endif break; } clpModel->dual(); // clean up cbcModel->initialSolve(); #ifdef CBC_THREAD int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].intValue(); cbcModel->setNumberThreads(numberThreads % 100); cbcModel->setThreadMode(CoinMin(numberThreads / 100, 7)); #endif //setCutAndHeuristicOptions(*cbcModel); cbcModel->branchAndBound(); OsiSolverLinearizedQuadratic * solver3 = dynamic_cast (model2.solver()); assert (solver3); solution = solver3->bestSolution(); double bestObjectiveValue = solver3->bestObjectiveValue(); linkSolver->setBestObjectiveValue(bestObjectiveValue); if (solution) { linkSolver->setBestSolution(solution, solver3->getNumCols()); } CbcHeuristicDynamic3 dynamic(model_); dynamic.setHeuristicName("dynamic pass thru"); model_.addHeuristic(&dynamic); // if convex if ((linkSolver->specialOptions2()&4) != 0 && solution) { int numberColumns = coinModel->numberColumns(); assert (linkSolver->objectiveVariable() == numberColumns); // add OA cut double offset; double * gradient = new double [numberColumns+1]; memcpy(gradient, qp->objectiveAsObject()->gradient(qp, solution, offset, true, 2), numberColumns*sizeof(double)); double rhs = 0.0; int * column = new int[numberColumns+1]; int n = 0; for (int i = 0; i < numberColumns; i++) { double value = gradient[i]; if (fabs(value) > 1.0e-12) { gradient[n] = value; rhs += value * solution[i]; column[n++] = i; } } gradient[n] = -1.0; column[n++] = numberColumns; storedAmpl.addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient); delete [] gradient; delete [] column; } // could do three way branching round a) continuous b) best solution printf("obj %g\n", bestObjectiveValue); linkSolver->initialSolve(); } } } #endif #endif if (logLevel <= 1) si->setHintParam(OsiDoReducePrint, true, OsiHintTry); #ifndef CBC_OTHER_SOLVER si->setSpecialOptions(0x40000000); #endif } if (!miplib) { if (!preSolve) { model_.solver()->setHintParam(OsiDoPresolveInInitial, false, OsiHintTry); model_.solver()->setHintParam(OsiDoPresolveInResolve, false, OsiHintTry); } double time1a = CoinCpuTime(); OsiSolverInterface * solver = model_.solver(); #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * si = dynamic_cast(solver) ; if (si) si->setSpecialOptions(si->specialOptions() | 1024); #endif model_.initialSolve(); #ifndef CBC_OTHER_SOLVER ClpSimplex * clpSolver = si->getModelPtr(); int iStatus = clpSolver->status(); int iStatus2 = clpSolver->secondaryStatus(); if (iStatus == 0) { iStatus2 = 0; } else if (iStatus == 1) { iStatus = 0; iStatus2 = 1; // say infeasible } else if (iStatus == 2) { iStatus = 0; iStatus2 = 7; // say unbounded } else if (iStatus == 3) { iStatus = 1; if (iStatus2 == 9) iStatus2 = 4; else iStatus2 = 3; // Use nodes - as closer than solutions } else if (iStatus == 4) { iStatus = 2; // difficulties iStatus2 = 0; } model_.setProblemStatus(iStatus); model_.setSecondaryStatus(iStatus2); si->setWarmStart(NULL); int returnCode = callBack(&model_, 1); if (returnCode) { // exit if user wants delete babModel_; babModel_ = NULL; return returnCode; } if (clpSolver->status() > 0) { // and in babModel if exists if (babModel_) { babModel_->setProblemStatus(iStatus); babModel_->setSecondaryStatus(iStatus2); } if (!noPrinting_) { iStatus = clpSolver->status(); const char * msg[] = {"infeasible", "unbounded", "stopped", "difficulties", "other" }; sprintf(generalPrint, "Problem is %s - %.2f seconds", msg[iStatus-1], CoinCpuTime() - time1a); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } break; } clpSolver->setSpecialOptions(clpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound) #elif CBC_OTHER_SOLVER==1 #endif if (!noPrinting_) { sprintf(generalPrint, "Continuous objective value is %g - %.2f seconds", solver->getObjValue(), CoinCpuTime() - time1a); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } if (model_.getMaximumNodes() == -987654321) { // See if No objective! int numberColumns = clpSolver->getNumCols(); const double * obj = clpSolver->getObjCoefficients(); const double * lower = clpSolver->getColLower(); const double * upper = clpSolver->getColUpper(); int nObj = 0; for (int i = 0; i < numberColumns; i++) { if (upper[i] > lower[i] && obj[i]) nObj++; } if (!nObj) { printf("************No objective!!\n"); model_.setMaximumSolutions(1); // Column copy CoinPackedMatrix matrixByCol(*model_.solver()->getMatrixByCol()); //const double * element = matrixByCol.getElements(); //const int * row = matrixByCol.getIndices(); //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); const int * columnLength = matrixByCol.getVectorLengths(); for (int i = 0; i < numberColumns; i++) { double value = (CoinDrand48() + 0.5) * 10000; value = 10; value *= columnLength[i]; int iValue = static_cast (value) / 10; //iValue=1; clpSolver->setObjCoeff(i, iValue); } } } #ifndef CBC_OTHER_SOLVER if (!complicatedInteger && preProcess == 0 && clpSolver->tightenPrimalBounds(0.0, 0, true) != 0) { #ifndef DISALLOW_PRINTING std::cout << "Problem is infeasible - tightenPrimalBounds!" << std::endl; #endif model_.setProblemStatus(0); model_.setSecondaryStatus(1); // and in babModel if exists if (babModel_) { babModel_->setProblemStatus(0); babModel_->setSecondaryStatus(1); } break; } if (clpSolver->dualBound() == 1.0e10) { ClpSimplex temp = *clpSolver; temp.setLogLevel(0); temp.dual(0, 7); // user did not set - so modify // get largest scaled away from bound double largest = 1.0e-12; double largestScaled = 1.0e-12; int numberRows = temp.numberRows(); const double * rowPrimal = temp.primalRowSolution(); const double * rowLower = temp.rowLower(); const double * rowUpper = temp.rowUpper(); const double * rowScale = temp.rowScale(); int iRow; for (iRow = 0; iRow < numberRows; iRow++) { double value = rowPrimal[iRow]; double above = value - rowLower[iRow]; double below = rowUpper[iRow] - value; if (above < 1.0e12) { largest = CoinMax(largest, above); } if (below < 1.0e12) { largest = CoinMax(largest, below); } if (rowScale) { double multiplier = rowScale[iRow]; above *= multiplier; below *= multiplier; } if (above < 1.0e12) { largestScaled = CoinMax(largestScaled, above); } if (below < 1.0e12) { largestScaled = CoinMax(largestScaled, below); } } int numberColumns = temp.numberColumns(); const double * columnPrimal = temp.primalColumnSolution(); const double * columnLower = temp.columnLower(); const double * columnUpper = temp.columnUpper(); const double * columnScale = temp.columnScale(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = columnPrimal[iColumn]; double above = value - columnLower[iColumn]; double below = columnUpper[iColumn] - value; if (above < 1.0e12) { largest = CoinMax(largest, above); } if (below < 1.0e12) { largest = CoinMax(largest, below); } if (columnScale) { double multiplier = 1.0 / columnScale[iColumn]; above *= multiplier; below *= multiplier; } if (above < 1.0e12) { largestScaled = CoinMax(largestScaled, above); } if (below < 1.0e12) { largestScaled = CoinMax(largestScaled, below); } } #ifdef COIN_DEVELOP if (!noPrinting_) std::cout << "Largest (scaled) away from bound " << largestScaled << " unscaled " << largest << std::endl; #endif clpSolver->setDualBound(CoinMax(1.0001e8, CoinMin(100.0*largest, 1.00001e10))); } si->resolve(); // clean up #endif } // If user made settings then use them if (!defaultSettings) { OsiSolverInterface * solver = model_.solver(); if (!doScaling) solver->setHintParam(OsiDoScale, false, OsiHintTry); #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * si = dynamic_cast(solver) ; assert (si != NULL); // get clp itself ClpSimplex * modelC = si->getModelPtr(); //if (modelC->tightenPrimalBounds()!=0) { //std::cout<<"Problem is infeasible!"<tightenPrimalBounds(tightenFactor) != 0) { #ifndef DISALLOW_PRINTING std::cout << "Problem is infeasible!" << std::endl; #endif model_.setProblemStatus(0); model_.setSecondaryStatus(1); // and in babModel if exists if (babModel_) { babModel_->setProblemStatus(0); babModel_->setSecondaryStatus(1); } break; } } #endif } // See if we want preprocessing OsiSolverInterface * saveSolver = NULL; CglPreProcess process; // Say integers in sync bool integersOK = true; delete babModel_; babModel_ = new CbcModel(model_); #ifndef CBC_OTHER_SOLVER int numberChanged = 0; OsiSolverInterface * solver3 = clpSolver->clone(); babModel_->assignSolver(solver3); OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); if (clpSolver2->messageHandler()->logLevel()) clpSolver2->messageHandler()->setLogLevel(1); if (logLevel > -1) clpSolver2->messageHandler()->setLogLevel(logLevel); lpSolver = clpSolver2->getModelPtr(); if (lpSolver->factorizationFrequency() == 200 && !miplib) { // User did not touch preset int numberRows = lpSolver->numberRows(); const int cutoff1 = 10000; const int cutoff2 = 100000; const int base = 75; const int freq0 = 50; const int freq1 = 200; const int freq2 = 400; const int maximum = 1000; int frequency; if (numberRows < cutoff1) frequency = base + numberRows / freq0; else if (numberRows < cutoff2) frequency = base + cutoff1 / freq0 + (numberRows - cutoff1) / freq1; else frequency = base + cutoff1 / freq0 + (cutoff2 - cutoff1) / freq1 + (numberRows - cutoff2) / freq2; lpSolver->setFactorizationFrequency(CoinMin(maximum, frequency)); } #elif CBC_OTHER_SOLVER==1 OsiSolverInterface * solver3 = model_.solver()->clone(); babModel_->assignSolver(solver3); #endif time2 = CoinCpuTime(); totalTime += time2 - time1; //time1 = time2; double timeLeft = babModel_->getMaximumSeconds(); int numberOriginalColumns = babModel_->solver()->getNumCols(); if (preProcess == 7) { // use strategy instead preProcess = 0; useStrategy = true; #ifdef COIN_HAS_LINK // empty out any cuts if (storedAmpl.sizeRowCuts()) { printf("Emptying ampl stored cuts as internal preprocessing\n"); CglStored temp; storedAmpl = temp; } #endif } if (preProcess && type == CBC_PARAM_ACTION_BAB) { // see whether to switch off preprocessing // only allow SOS and integer OsiObject ** objects = babModel_->objects(); int numberObjects = babModel_->numberObjects(); for (int iObj = 0; iObj < numberObjects; iObj++) { CbcSOS * objSOS = dynamic_cast (objects[iObj]) ; CbcSimpleInteger * objSimpleInteger = dynamic_cast (objects[iObj]) ; if (!objSimpleInteger&&!objSOS) { // find all integers anyway babModel_->findIntegers(true); preProcess=0; break; } } } if (type == CBC_PARAM_ACTION_BAB) { double limit; clpSolver->getDblParam(OsiDualObjectiveLimit, limit); if (clpSolver->getObjValue()*clpSolver->getObjSense() >= limit*clpSolver->getObjSense()) preProcess = 0; } if (mipStartBefore.size()) { CbcModel tempModel=*babModel_; std::vector< std::string > colNames; for ( int i=0 ; (isolver()->getNumCols()) ; ++i ) colNames.push_back( model_.solver()->getColName(i) ); std::vector< double > x( babModel_->getNumCols(), 0.0 ); double obj; int status = computeCompleteSolution( &tempModel, colNames, mipStartBefore, &x[0], obj ); // set cutoff if (!status) babModel_->setCutoff(CoinMin(babModel_->getCutoff(),obj+1.0e-4)); } if (preProcess && type == CBC_PARAM_ACTION_BAB) { #ifndef CBC_OTHER_SOLVER // See if sos from mps file if (numberSOS == 0 && clpSolver->numberSOS() && doSOS) { // SOS numberSOS = clpSolver->numberSOS(); const CoinSet * setInfo = clpSolver->setInfo(); sosStart = new int [numberSOS+1]; sosType = new char [numberSOS]; int i; int nTotal = 0; sosStart[0] = 0; for ( i = 0; i < numberSOS; i++) { int type = setInfo[i].setType(); int n = setInfo[i].numberEntries(); sosType[i] = static_cast(type); nTotal += n; sosStart[i+1] = nTotal; } sosIndices = new int[nTotal]; sosReference = new double [nTotal]; for (i = 0; i < numberSOS; i++) { int n = setInfo[i].numberEntries(); const int * which = setInfo[i].which(); const double * weights = setInfo[i].weights(); int base = sosStart[i]; for (int j = 0; j < n; j++) { int k = which[j]; sosIndices[j+base] = k; sosReference[j+base] = weights ? weights[j] : static_cast (j); } } } #endif saveSolver = babModel_->solver()->clone(); /* Do not try and produce equality cliques and do up to 10 passes */ OsiSolverInterface * solver2; { // Tell solver we are in Branch and Cut saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ; // Default set of cut generators CglProbing generator1; generator1.setUsingObjective(1); generator1.setMaxPass(1); generator1.setMaxPassRoot(1); generator1.setMaxProbeRoot(CoinMin(3000, saveSolver->getNumCols())); generator1.setMaxElements(100); generator1.setMaxElementsRoot(200); generator1.setMaxLookRoot(50); if (saveSolver->getNumCols() > 3000) generator1.setMaxProbeRoot(123); generator1.setRowCuts(3); if ((tunePreProcess&1) != 0) { // heavy probing generator1.setMaxPassRoot(2); generator1.setMaxElements(300); generator1.setMaxProbeRoot(saveSolver->getNumCols()); } if ((babModel_->specialOptions()&65536) != 0) process.setOptions(1); // Add in generators if ((model_.moreSpecialOptions()&65536)==0) process.addCutGenerator(&generator1); int translate[] = {9999, 0, 0, -3, 2, 3, -2, 9999, 4, 5}; process.passInMessageHandler(babModel_->messageHandler()); //process.messageHandler()->setLogLevel(babModel_->logLevel()); #ifdef COIN_HAS_ASL if (info.numberSos && doSOS && statusUserFunction_[0]) { // SOS numberSOS = info.numberSos; sosStart = info.sosStart; sosIndices = info.sosIndices; } #endif if (numberSOS && doSOS) { // SOS int numberColumns = saveSolver->getNumCols(); char * prohibited = new char[numberColumns]; memset(prohibited, 0, numberColumns); int n = sosStart[numberSOS]; for (int i = 0; i < n; i++) { int iColumn = sosIndices[i]; prohibited[iColumn] = 1; } process.passInProhibited(prohibited, numberColumns); delete [] prohibited; } if (0) { // Special integers int numberColumns = saveSolver->getNumCols(); char * prohibited = new char[numberColumns]; memset(prohibited, 0, numberColumns); const CoinPackedMatrix * matrix = saveSolver->getMatrixByCol(); const int * columnLength = matrix->getVectorLengths(); int numberProhibited=0; for (int iColumn = numberColumns-1; iColumn >=0; iColumn--) { if (!saveSolver->isInteger(iColumn)|| columnLength[iColumn]>1) break; numberProhibited++; prohibited[iColumn] = 1; } if (numberProhibited) { process.passInProhibited(prohibited, numberColumns); printf("**** Treating last %d integers as special - give high priority?\n",numberProhibited); } delete [] prohibited; } if (!model_.numberObjects() && true) { /* model may not have created objects If none then create */ model_.findIntegers(true); } if (model_.numberObjects()) { OsiObject ** oldObjects = babModel_->objects(); int numberOldObjects = babModel_->numberObjects(); // SOS int numberColumns = saveSolver->getNumCols(); char * prohibited = new char[numberColumns]; memset(prohibited, 0, numberColumns); int numberProhibited = 0; for (int iObj = 0; iObj < numberOldObjects; iObj++) { CbcSOS * obj = dynamic_cast (oldObjects[iObj]) ; if (obj) { int n = obj->numberMembers(); const int * which = obj->members(); for (int i = 0; i < n; i++) { int iColumn = which[i]; prohibited[iColumn] = 1; numberProhibited++; } } CbcLotsize * obj2 = dynamic_cast (oldObjects[iObj]) ; if (obj2) { int iColumn = obj2->columnNumber(); prohibited[iColumn] = 1; numberProhibited++; } } if (numberProhibited) process.passInProhibited(prohibited, numberColumns); delete [] prohibited; } int numberPasses = 10; if (tunePreProcess >= 1000000) { numberPasses = (tunePreProcess / 1000000) - 1; tunePreProcess = tunePreProcess % 1000000; } else if (tunePreProcess >= 10000) { numberPasses = (tunePreProcess / 10000) - 1; tunePreProcess = tunePreProcess % 10000; } #ifndef CBC_OTHER_SOLVER if (doSprint > 0) { // Sprint for primal solves ClpSolve::SolveType method = ClpSolve::usePrimalorSprint; ClpSolve::PresolveType presolveType = ClpSolve::presolveOff; int numberPasses = 5; int options[] = {0, 3, 0, 0, 0, 0}; int extraInfo[] = { -1, 20, -1, -1, -1, -1}; extraInfo[1] = doSprint; int independentOptions[] = {0, 0, 3}; ClpSolve clpSolve(method, presolveType, numberPasses, options, extraInfo, independentOptions); // say use in OsiClp clpSolve.setSpecialOption(6, 1); OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver); osiclp->setSolveOptions(clpSolve); osiclp->setHintParam(OsiDoDualInResolve, false); // switch off row copy osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256); osiclp->getModelPtr()->setInfeasibilityCost(1.0e11); } #endif #ifndef CBC_OTHER_SOLVER { OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver); osiclp->setSpecialOptions(osiclp->specialOptions() | 1024); int savePerturbation = osiclp->getModelPtr()->perturbation(); //#define CBC_TEMP1 #ifdef CBC_TEMP1 if (savePerturbation == 50) osiclp->getModelPtr()->setPerturbation(52); // try less #endif if ((model_.moreSpecialOptions()&65536)!=0) process.setOptions(2+4+8); // no cuts cbcPreProcessPointer = & process; solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses, tunePreProcess); /*solver2->writeMps("after"); saveSolver->writeMps("before");*/ osiclp->getModelPtr()->setPerturbation(savePerturbation); } #elif CBC_OTHER_SOLVER==1 cbcPreProcessPointer = & process; solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses, tunePreProcess); #endif integersOK = false; // We need to redo if CbcObjects exist // Tell solver we are not in Branch and Cut saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (solver2) solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; } #ifdef COIN_HAS_ASL if (!solver2 && statusUserFunction_[0]) { // infeasible info.problemStatus = 1; info.objValue = 1.0e100; sprintf(info.buffer, "infeasible/unbounded by pre-processing"); info.primalSolution = NULL; info.dualSolution = NULL; break; } #endif if (!noPrinting_) { if (!solver2) { sprintf(generalPrint, "Pre-processing says infeasible or unbounded"); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } else { //printf("processed model has %d rows, %d columns and %d elements\n", // solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements()); } } if (!solver2) { // say infeasible for solution integerStatus = 6; model_.setProblemStatus(0); model_.setSecondaryStatus(1); babModel_->setProblemStatus(0); babModel_->setSecondaryStatus(1); } else { statistics_nprocessedrows = solver2->getNumRows(); statistics_nprocessedcols = solver2->getNumCols(); model_.setProblemStatus(-1); babModel_->setProblemStatus(-1); } int returnCode = callBack(babModel_, 2); if (returnCode) { // exit if user wants delete babModel_; babModel_ = NULL; return returnCode; } if (!solver2) break; if (model_.bestSolution()) { // need to redo - in case no better found in BAB // just get integer part right const int * originalColumns = process.originalColumns(); int numberColumns = solver2->getNumCols(); double * bestSolution = babModel_->bestSolution(); const double * oldBestSolution = model_.bestSolution(); for (int i = 0; i < numberColumns; i++) { int jColumn = originalColumns[i]; bestSolution[i] = oldBestSolution[jColumn]; } } //solver2->resolve(); if (preProcess == 2) { OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (solver2); #if 1 ClpSimplex * lpSolver = clpSolver2->getModelPtr(); lpSolver->writeMps("presolved.mps", 0, 1, lpSolver->optimizationDirection()); #else // put back names ClpSimplex lpSolver(*clpSolver2->getModelPtr()); //OsiClpSolverInterface * originalSolver = dynamic_cast< OsiClpSolverInterface*> (olver); ClpSimplex * originalLp = clpSolver->getModelPtr(); const int * originalColumns = process.originalColumns(); int numberColumns = lpSolver.getNumCols(); for (int i = 0; i < numberColumns; i++) { int jColumn = originalColumns[i]; std::string name = originalLp->getColumnName(jColumn); lpSolver.setColumnName(i,name); } lpSolver.writeMps("presolved.mps", 0, 1, lpSolver.optimizationDirection()); #endif printf("Preprocessed model (minimization) on presolved.mps\n"); } { // look at new integers int numberOriginalColumns = process.originalModel()->getNumCols(); const int * originalColumns = process.originalColumns(); OsiClpSolverInterface * osiclp2 = dynamic_cast< OsiClpSolverInterface*> (solver2); int numberColumns = osiclp2->getNumCols(); OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver); for (int i = 0; i < numberColumns; i++) { int iColumn = originalColumns[i]; if (iColumn < numberOriginalColumns) { if (osiclp2->isInteger(i) && !osiclp->isInteger(iColumn)) osiclp2->setOptionalInteger(i); // say optional } } } // we have to keep solver2 so pass clone solver2 = solver2->clone(); // see if extra variables wanted int threshold = parameters_[whichParam(CBC_PARAM_INT_EXTRA_VARIABLES, numberParameters_, parameters_)].intValue(); if (threshold) { int numberColumns = solver2->getNumCols(); int highPriority=0; /* normal - no priorities >10000 equal high priority >20000 higher priority for higher cost */ if (threshold>10000) { highPriority=threshold/10000; threshold -= 10000*highPriority; } const double * columnLower = solver2->getColLower(); const double * columnUpper = solver2->getColUpper(); const double * objective = solver2->getObjCoefficients(); int numberIntegers = 0; int numberBinary = 0; int numberTotalIntegers=0; double * obj = new double [numberColumns]; int * which = new int [numberColumns]; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (solver2->isInteger(iColumn)) { numberTotalIntegers++; if (columnUpper[iColumn] > columnLower[iColumn]) { numberIntegers++; if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1) numberBinary++; } } } int numberSort=0; int numberZero=0; int numberZeroContinuous=0; int numberDifferentObj=0; int numberContinuous=0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] > columnLower[iColumn]) { if (solver2->isInteger(iColumn)) { if (!objective[iColumn]) { numberZero++; } else { obj[numberSort]= fabs(objective[iColumn]); which[numberSort++]=iColumn; } } else if (objective[iColumn]) { numberContinuous++; } else { numberZeroContinuous++; } } } CoinSort_2(obj,obj+numberSort,which); double last=obj[0]; for (int jColumn = 1; jColumn < numberSort; jColumn++) { if (fabs(obj[jColumn]-last)>1.0e-12) { numberDifferentObj++; last=obj[jColumn]; } } numberDifferentObj++; sprintf(generalPrint,"Problem has %d integers (%d of which binary) and %d continuous", numberIntegers,numberBinary,numberColumns-numberIntegers); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; if (numberColumns>numberIntegers) { sprintf(generalPrint,"%d continuous have nonzero objective, %d have zero objective", numberContinuous,numberZeroContinuous); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } sprintf(generalPrint,"%d integer have nonzero objective, %d have zero objective, %d different nonzero (taking abs)", numberSort,numberZero,numberDifferentObj); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; if (numberDifferentObj<=threshold + (numberZero) ? 1 : 0 && numberDifferentObj) { int * backward=NULL; if (highPriority) { newPriorities = new int [numberTotalIntegers+numberDifferentObj+numberColumns]; backward=newPriorities+numberTotalIntegers+numberDifferentObj; numberTotalIntegers=0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (solver2->isInteger(iColumn)) { backward[iColumn]=numberTotalIntegers; newPriorities[numberTotalIntegers++]=10000; } } } int iLast=0; double last=obj[0]; for (int jColumn = 1; jColumn < numberSort; jColumn++) { if (fabs(obj[jColumn]-last)>1.0e-12) { sprintf(generalPrint,"%d variables have objective of %g", jColumn-iLast,last); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; iLast=jColumn; last=obj[jColumn]; } } sprintf(generalPrint,"%d variables have objective of %g", numberSort-iLast,last); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; int spaceNeeded=numberSort+numberDifferentObj; int * columnAdd = new int[spaceNeeded+numberDifferentObj+1]; double * elementAdd = new double[spaceNeeded]; int * rowAdd = new int[numberDifferentObj+1]; double * objectiveNew = new double[3*numberDifferentObj]; double * lowerNew = objectiveNew+numberDifferentObj; double * upperNew = lowerNew+numberDifferentObj; memset(columnAdd+spaceNeeded,0, (numberDifferentObj+1)*sizeof(int)); iLast=0; last=obj[0]; numberDifferentObj=0; int priorityLevel=9999; int numberElements=0; rowAdd[0]=0; for (int jColumn = 1; jColumn < numberSort+1; jColumn++) { if (jColumn==numberSort||fabs(obj[jColumn]-last)>1.0e-12) { // not if just one if (jColumn-iLast>1) { // do priority if (highPriority==1) { newPriorities[numberTotalIntegers+numberDifferentObj] = 500; } else if (highPriority==2) { newPriorities[numberTotalIntegers+numberDifferentObj] = priorityLevel; priorityLevel--; } int iColumn=which[iLast]; objectiveNew[numberDifferentObj]=objective[iColumn]; double lower=0.0; double upper=0.0; for (int kColumn=iLast;kColumnsetObjCoeff(iColumn,0.0); double lowerValue=columnLower[iColumn]; double upperValue=columnUpper[iColumn]; double elementValue=-1.0; if (objectiveNew[numberDifferentObj]*objective[iColumn]<0.0) { lowerValue=-columnUpper[iColumn]; upperValue=-columnLower[iColumn]; elementValue=1.0; } columnAdd[numberElements]=iColumn; elementAdd[numberElements++]=elementValue; if (lower!=-COIN_DBL_MAX) { if (lowerValue!=-COIN_DBL_MAX) lower += lowerValue; else lower=-COIN_DBL_MAX; } if (upper!=COIN_DBL_MAX) { if (upperValue!=COIN_DBL_MAX) upper += upperValue; else upper=COIN_DBL_MAX; } } columnAdd[numberElements]=numberColumns+numberDifferentObj; elementAdd[numberElements++]=1.0; lowerNew[numberDifferentObj]=lower; upperNew[numberDifferentObj]=upper; numberDifferentObj++; rowAdd[numberDifferentObj]=numberElements; } else if (highPriority) { // just one // do priority int iColumn=which[iLast]; int iInt=backward[iColumn]; if (highPriority==1) { newPriorities[iInt] = 500; } else { newPriorities[iInt] = priorityLevel; priorityLevel--; } } if (jColumnaddCols(numberDifferentObj, columnAdd+spaceNeeded, NULL, NULL, lowerNew, upperNew,objectiveNew); // add constraints and make integer if all integer in group for (int iObj=0; iObj < numberDifferentObj; iObj++) { lowerNew[iObj]=0.0; upperNew[iObj]=0.0; solver2->setInteger(numberColumns+iObj); } solver2->addRows(numberDifferentObj, rowAdd,columnAdd,elementAdd, lowerNew, upperNew); sprintf(generalPrint,"Replacing model - %d new variables",numberDifferentObj); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; truncateColumns=numberColumns; } delete [] columnAdd; delete [] elementAdd; delete [] rowAdd; delete [] objectiveNew; } delete [] which; delete [] obj; } babModel_->assignSolver(solver2); babModel_->setOriginalColumns(process.originalColumns(), truncateColumns); babModel_->initialSolve(); babModel_->setMaximumSeconds(timeLeft - (CoinCpuTime() - time2)); } // now tighten bounds if (!miplib) { #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * si = dynamic_cast(babModel_->solver()) ; assert (si != NULL); // get clp itself ClpSimplex * modelC = si->getModelPtr(); //if (noPrinting_) //modelC->setLogLevel(0); if (!complicatedInteger && modelC->tightenPrimalBounds() != 0) { #ifndef DISALLOW_PRINTING std::cout << "Problem is infeasible!" << std::endl; #endif model_.setProblemStatus(0); model_.setSecondaryStatus(1); // say infeasible for solution integerStatus = 6; // and in babModel_ if exists if (babModel_) { babModel_->setProblemStatus(0); babModel_->setSecondaryStatus(1); } break; } si->resolve(); #elif CBC_OTHER_SOLVER==1 #endif } if (debugValues) { // for debug std::string problemName ; babModel_->solver()->getStrParam(OsiProbName, problemName) ; babModel_->solver()->activateRowCutDebugger(problemName.c_str()) ; twomirGen.probname_ = CoinStrdup(problemName.c_str()); // checking seems odd //redsplitGen.set_given_optsol(babModel_->solver()->getRowCutDebuggerAlways()->optimalSolution(), // babModel_->getNumCols()); } int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].intValue(); //#ifdef COIN_HAS_ASL #ifndef JJF_ONE // If linked then see if expansion wanted { OsiSolverLink * solver3 = dynamic_cast (babModel_->solver()); int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].intValue() / 10000; if (solver3 || (options&16) != 0) { if (options) { /* 1 - force mini branch and bound 2 - set priorities high on continuous 4 - try adding OA cuts 8 - try doing quadratic linearization 16 - try expanding knapsacks */ if ((options&16)) { int numberColumns = saveCoinModel.numberColumns(); int numberRows = saveCoinModel.numberRows(); whichColumn = new int[numberColumns]; knapsackStart = new int[numberRows+1]; knapsackRow = new int[numberRows]; numberKnapsack = 10000; int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue(); int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, numberParameters_, parameters_)].intValue(); int logLevel = parameters_[log].intValue(); OsiSolverInterface * solver = expandKnapsack(saveCoinModel, whichColumn, knapsackStart, knapsackRow, numberKnapsack, storedAmpl, logLevel, extra1, extra2, saveTightenedModel); if (solver) { #ifndef CBC_OTHER_SOLVER clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); assert (clpSolver); lpSolver = clpSolver->getModelPtr(); #endif babModel_->assignSolver(solver); testOsiOptions = 0; // allow gomory complicatedInteger = 0; #ifdef COIN_HAS_ASL // Priorities already done free(info.priorities); info.priorities = NULL; #endif } else { numberKnapsack = 0; delete [] whichColumn; delete [] knapsackStart; delete [] knapsackRow; whichColumn = NULL; knapsackStart = NULL; knapsackRow = NULL; } } } } } #endif if (useCosts && testOsiOptions < 0) { int numberColumns = babModel_->getNumCols(); int * sort = new int[numberColumns]; double * dsort = new double[numberColumns]; int * priority = new int [numberColumns]; const double * objective = babModel_->getObjCoefficients(); const double * lower = babModel_->getColLower() ; const double * upper = babModel_->getColUpper() ; const CoinPackedMatrix * matrix = babModel_->solver()->getMatrixByCol(); const int * columnLength = matrix->getVectorLengths(); int iColumn; int n = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (babModel_->isInteger(iColumn)) { sort[n] = n; if (useCosts == 1) dsort[n++] = -fabs(objective[iColumn]); else if (useCosts == 2) dsort[n++] = iColumn; else if (useCosts == 3) dsort[n++] = upper[iColumn] - lower[iColumn]; else if (useCosts == 4) dsort[n++] = -(upper[iColumn] - lower[iColumn]); else if (useCosts == 5) dsort[n++] = -columnLength[iColumn]; else if (useCosts == 6) dsort[n++] = (columnLength[iColumn]==1) ? -1.0 : 0.0; else if (useCosts == 7) dsort[n++] = (objective[iColumn]) ? -1.0 : 0.0; } } CoinSort_2(dsort, dsort + n, sort); int level = 0; double last = -1.0e100; for (int i = 0; i < n; i++) { int iPut = sort[i]; if (dsort[i] != last) { level++; last = dsort[i]; } priority[iPut] = level; } if(newPriorities ) { // get rid of delete [] newPriorities; newPriorities = NULL; } babModel_->passInPriorities( priority, false); integersOK = true; delete [] priority; delete [] sort; delete [] dsort; } // Set up heuristics doHeuristics(babModel_, ((!miplib) ? 1 : 10), parameters_, numberParameters_, noPrinting_, initialPumpTune); if (!miplib) { if (parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, numberParameters_, parameters_)].currentOptionAsInteger()) { CbcTreeLocal localTree(babModel_, NULL, 10, 0, 0, 10000, 2000); babModel_->passInTreeHandler(localTree); } } if (type == CBC_PARAM_ACTION_MIPLIB) { if (babModel_->numberStrong() == 5 && babModel_->numberBeforeTrust() == 5) babModel_->setNumberBeforeTrust(10); } int experimentFlag = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, numberParameters_, parameters_)].intValue(); int strategyFlag = parameters_[whichParam(CBC_PARAM_INT_STRATEGY, numberParameters_, parameters_)].intValue(); int bothFlags = CoinMax(CoinMin(experimentFlag, 1), strategyFlag); // add cut generators if wanted int switches[30]; int accuracyFlag[30]; char doAtEnd[30]; memset(doAtEnd,0,30); int numberGenerators = 0; int translate[] = { -100, -1, -99, -98, 1, -1098, -999, 1, 1, 1, -1}; int maximumSlowPasses = parameters_[whichParam(CBC_PARAM_INT_MAX_SLOW_CUTS, numberParameters_, parameters_)].intValue(); if (probingAction) { int numberColumns = babModel_->solver()->getNumCols(); if (probingAction > 7) { probingGen.setMaxElements(numberColumns); probingGen.setMaxElementsRoot(numberColumns); } probingGen.setMaxProbeRoot(CoinMin(2000, numberColumns)); probingGen.setMaxProbeRoot(123); probingGen.setMaxProbe(123); probingGen.setMaxLookRoot(20); if (probingAction == 7 || probingAction == 9) probingGen.setRowCuts(-3); // strengthening etc just at root if (probingAction == 8 || probingAction == 9) { // Number of unsatisfied variables to look at probingGen.setMaxProbeRoot(numberColumns); probingGen.setMaxProbe(numberColumns); // How far to follow the consequences probingGen.setMaxLook(50); probingGen.setMaxLookRoot(50); } if (probingAction == 10) { probingGen.setMaxPassRoot(2); probingGen.setMaxProbeRoot(numberColumns); probingGen.setMaxLookRoot(100); } // If 5 then force on int iAction = translate[probingAction]; if (probingAction == 5) iAction = 1; babModel_->addCutGenerator(&probingGen, iAction, "Probing"); accuracyFlag[numberGenerators] = 5; switches[numberGenerators++] = 0; } if (gomoryAction && (complicatedInteger != 1 || (gomoryAction == 1 || gomoryAction >= 4))) { // try larger limit int numberColumns = babModel_->getNumCols(); if (gomoryAction == 7) { gomoryAction = 4; gomoryGen.setLimitAtRoot(numberColumns); gomoryGen.setLimit(numberColumns); } else if (gomoryAction == 8) { gomoryAction = 3; gomoryGen.setLimitAtRoot(numberColumns); gomoryGen.setLimit(200); } else if (numberColumns > 5000) { //#define MORE_CUTS2 #ifdef MORE_CUTS2 // try larger limit gomoryGen.setLimitAtRoot(numberColumns); gomoryGen.setLimit(200); #else gomoryGen.setLimitAtRoot(2000); //gomoryGen.setLimit(200); #endif } else { #ifdef MORE_CUTS2 // try larger limit gomoryGen.setLimitAtRoot(numberColumns); gomoryGen.setLimit(200); #endif } int cutLength = parameters_[whichParam(CBC_PARAM_INT_CUTLENGTH, numberParameters_, parameters_)].intValue(); if (cutLength != -1) { gomoryGen.setLimitAtRoot(cutLength); if (cutLength < 10000000) { gomoryGen.setLimit(cutLength); } else { gomoryGen.setLimit(cutLength % 10000000); } } int laGomory = parameters_[whichParam(CBC_PARAM_STR_LAGOMORYCUTS, numberParameters_, parameters_)].currentOptionAsInteger(); int gType = translate[gomoryAction]; if (!laGomory) { // Normal babModel_->addCutGenerator(&gomoryGen, translate[gomoryAction], "Gomory"); accuracyFlag[numberGenerators] = 3; switches[numberGenerators++] = 0; } else { laGomory--; int type = (laGomory % 3)+1; int when = laGomory/3; char atEnd = (when<2) ? 1 : 0; int gomoryTypeMajor = 10; if (when<3) { // normal as well babModel_->addCutGenerator(&gomoryGen, gType, "Gomory"); accuracyFlag[numberGenerators] = 3; switches[numberGenerators++] = 0; if (when==2) gomoryTypeMajor=20; } else { when--; // so on gomoryTypeMajor=20; } if (!when) gType=-99; // root gomoryGen.passInOriginalSolver(babModel_->solver()); if ((type&1) !=0) { // clean gomoryGen.setGomoryType(gomoryTypeMajor+1); babModel_->addCutGenerator(&gomoryGen, gType, "GomoryL1"); accuracyFlag[numberGenerators] = 3; doAtEnd[numberGenerators]=atEnd; if (atEnd) { babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999); babModel_->cutGenerator(numberGenerators)->setHowOften(1); } switches[numberGenerators++] = 0; } if ((type&2) !=0) { // simple gomoryGen.setGomoryType(gomoryTypeMajor+2); babModel_->addCutGenerator(&gomoryGen, gType, "GomoryL2"); accuracyFlag[numberGenerators] = 3; doAtEnd[numberGenerators]=atEnd; if (atEnd) { babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999); babModel_->cutGenerator(numberGenerators)->setHowOften(1); } switches[numberGenerators++] = 0; } } } #ifdef CLIQUE_ANALYSIS if (miplib && !storedAmpl.sizeRowCuts()) { printf("looking at probing\n"); babModel_->addCutGenerator(&storedAmpl, 1, "Stored"); } #endif if (knapsackAction) { babModel_->addCutGenerator(&knapsackGen, translate[knapsackAction], "Knapsack"); accuracyFlag[numberGenerators] = 1; switches[numberGenerators++] = -2; } if (redsplitAction && !complicatedInteger) { babModel_->addCutGenerator(&redsplitGen, translate[redsplitAction], "Reduce-and-split"); accuracyFlag[numberGenerators] = 5; // slow ? - just do a few times if (redsplitAction!=1) { babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses); babModel_->cutGenerator(numberGenerators)->setHowOften(10); } switches[numberGenerators++] = 1; } if (redsplit2Action && !complicatedInteger) { int maxLength=256; if (redsplit2Action>2) { redsplit2Action-=2; maxLength=COIN_INT_MAX; } CglRedSplit2Param & parameters = redsplit2Gen.getParam(); parameters.setMaxNonzeroesTab(maxLength); babModel_->addCutGenerator(&redsplit2Gen, translate[redsplit2Action], "Reduce-and-split(2)"); accuracyFlag[numberGenerators] = 5; // slow ? - just do a few times if (redsplit2Action!=1) { babModel_->cutGenerator(numberGenerators)->setHowOften(maximumSlowPasses); babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses); babModel_->cutGenerator(numberGenerators)->setHowOften(5); } switches[numberGenerators++] = 1; } if (GMIAction && !complicatedInteger) { if (GMIAction>5) { // long GMIAction-=5; CglGMIParam & parameters = GMIGen.getParam(); parameters.setMaxSupportRel(1.0); } babModel_->addCutGenerator(&GMIGen, translate[GMIAction], "Gomory(2)"); if (GMIAction==5) { // just at end and root GMIAction=2; doAtEnd[numberGenerators]=1; babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999); babModel_->cutGenerator(numberGenerators)->setHowOften(1); } accuracyFlag[numberGenerators] = 5; switches[numberGenerators++] = 0; } if (cliqueAction) { babModel_->addCutGenerator(&cliqueGen, translate[cliqueAction], "Clique"); accuracyFlag[numberGenerators] = 0; switches[numberGenerators++] = 0; } if (mixedAction) { babModel_->addCutGenerator(&mixedGen, translate[mixedAction], "MixedIntegerRounding2"); accuracyFlag[numberGenerators] = 2; switches[numberGenerators++] = 0; } if (flowAction) { babModel_->addCutGenerator(&flowGen, translate[flowAction], "FlowCover"); accuracyFlag[numberGenerators] = 2; switches[numberGenerators++] = 1; } if (twomirAction && (complicatedInteger != 1 || (twomirAction == 1 || twomirAction >= 4))) { // try larger limit int numberColumns = babModel_->getNumCols(); if (twomirAction == 7) { twomirAction = 4; twomirGen.setMaxElements(numberColumns); } else if (numberColumns > 5000 && twomirAction == 4) { twomirGen.setMaxElements(2000); } int laTwomir = parameters_[whichParam(CBC_PARAM_STR_LATWOMIRCUTS, numberParameters_, parameters_)].currentOptionAsInteger(); int twomirType = translate[twomirAction]; if (!laTwomir) { // Normal babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts"); accuracyFlag[numberGenerators] = 4; switches[numberGenerators++] = 1; } else { laTwomir--; int type = (laTwomir % 3)+1; int when = laTwomir/3; char atEnd = (when<2) ? 1 : 0; int twomirTypeMajor = 10; if (when<3) { // normal as well babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts"); accuracyFlag[numberGenerators] = 4; switches[numberGenerators++] = 1; if (when==2) twomirTypeMajor=10; } else { when--; // so on twomirTypeMajor=20; } if (!when) twomirType=-99; // root twomirGen.passInOriginalSolver(babModel_->solver()); if ((type&1) !=0) { // clean twomirGen.setTwomirType(twomirTypeMajor+1); babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL1"); accuracyFlag[numberGenerators] = 4; doAtEnd[numberGenerators]=atEnd; switches[numberGenerators++] = atEnd ? 0 : 1; } if ((type&2) !=0) { // simple twomirGen.setTwomirType(twomirTypeMajor+2); babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL2"); accuracyFlag[numberGenerators] = 4; doAtEnd[numberGenerators]=atEnd; switches[numberGenerators++] = atEnd ? 0 : 1; } } } #ifndef DEBUG_MALLOC if (landpAction) { babModel_->addCutGenerator(&landpGen, translate[landpAction], "LiftAndProject"); accuracyFlag[numberGenerators] = 5; // slow ? - just do a few times if (landpAction!=1) { babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses); babModel_->cutGenerator(numberGenerators)->setHowOften(10); } switches[numberGenerators++] = 1; } #endif if (residualCapacityAction) { babModel_->addCutGenerator(&residualCapacityGen, translate[residualCapacityAction], "ResidualCapacity"); accuracyFlag[numberGenerators] = 5; switches[numberGenerators++] = 1; } if (zerohalfAction) { if (zerohalfAction > 4) { //zerohalfAction -=4; zerohalfGen.setFlags(1); } babModel_->addCutGenerator(&zerohalfGen, translate[zerohalfAction], "ZeroHalf"); accuracyFlag[numberGenerators] = 5; switches[numberGenerators++] = 2; } if (dominatedCuts) babModel_->setSpecialOptions(babModel_->specialOptions() | 64); // Say we want timings numberGenerators = babModel_->numberCutGenerators(); int iGenerator; int cutDepth = parameters_[whichParam(CBC_PARAM_INT_CUTDEPTH, numberParameters_, parameters_)].intValue(); for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = babModel_->cutGenerator(iGenerator); int howOften = generator->howOften(); if (howOften == -98 || howOften == -99 || generator->maximumTries()>0) generator->setSwitchOffIfLessThan(switches[iGenerator]); // Use if any at root as more likely later and fairly cheap //if (switches[iGenerator]==-2) //generator->setWhetherToUse(true); generator->setInaccuracy(accuracyFlag[iGenerator]); if (doAtEnd[iGenerator]) { generator->setWhetherCallAtEnd(true); //generator->setMustCallAgain(true); } generator->setTiming(true); if (cutDepth >= 0) generator->setWhatDepth(cutDepth) ; } // Could tune more if (!miplib) { double minimumDrop = fabs(babModel_->solver()->getObjValue()) * 1.0e-5 + 1.0e-5; babModel_->setMinimumDrop(CoinMin(5.0e-2, minimumDrop)); if (cutPass == -1234567) { if (babModel_->getNumCols() < 500) babModel_->setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (babModel_->getNumCols() < 5000) babModel_->setMaximumCutPassesAtRoot(100); // use minimum drop else babModel_->setMaximumCutPassesAtRoot(20); } else { babModel_->setMaximumCutPassesAtRoot(cutPass); } if (cutPassInTree == -1234567) babModel_->setMaximumCutPasses(4); else babModel_->setMaximumCutPasses(cutPassInTree); } else if (cutPass != -1234567) { babModel_->setMaximumCutPassesAtRoot(cutPass); } // Do more strong branching if small //if (babModel_->getNumCols()<5000) //babModel_->setNumberStrong(20); // Switch off strong branching if wanted //if (babModel_->getNumCols()>10*babModel_->getNumRows()) //babModel_->setNumberStrong(0); if (!noPrinting_) { int iLevel = parameters_[log].intValue(); if (iLevel < 0) { if (iLevel > -10) { babModel_->setPrintingMode(1); } else { babModel_->setPrintingMode(2); iLevel += 10; parameters_[log].setIntValue(iLevel); } iLevel = -iLevel; } babModel_->messageHandler()->setLogLevel(iLevel); if (babModel_->getNumCols() > 2000 || babModel_->getNumRows() > 1500 || babModel_->messageHandler()->logLevel() > 1) babModel_->setPrintFrequency(100); } babModel_->solver()->setIntParam(OsiMaxNumIterationHotStart, parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].intValue()); #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); // go faster stripes if ((osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500)) { osiclp->setupForRepeatedUse(2, parameters_[slog].intValue()); if (bothFlags >= 1) { ClpSimplex * lp = osiclp->getModelPtr(); int specialOptions = lp->specialOptions(); lp->setSpecialOptions(specialOptions | (2048 + 4096)); } } else { osiclp->setupForRepeatedUse(0, parameters_[slog].intValue()); } if (bothFlags >= 2) { ClpSimplex * lp = osiclp->getModelPtr(); int specialOptions = lp->specialOptions(); lp->setSpecialOptions(specialOptions | (2048 + 4096)); } double increment = babModel_->getCutoffIncrement();; int * changed = NULL; if (!miplib && increment == normalIncrement) changed = analyze( osiclp, numberChanged, increment, false, generalMessageHandler, noPrinting); #elif CBC_OTHER_SOLVER==1 double increment = babModel_->getCutoffIncrement();; #endif if (debugValues) { int numberColumns = babModel_->solver()->getNumCols(); if (numberDebugValues == numberColumns) { // for debug babModel_->solver()->activateRowCutDebugger(debugValues) ; } else { int numberOriginalColumns = process.originalModel()->getNumCols(); if (numberDebugValues <= numberOriginalColumns) { const int * originalColumns = process.originalColumns(); double * newValues = new double [numberColumns]; // in case preprocess added columns! // need to find values OsiSolverInterface * siCopy = babModel_->solver()->clone(); for (int i = 0; i < numberColumns; i++) { int jColumn = originalColumns[i]; if (jColumn < numberDebugValues && siCopy->isInteger(i)) { // integer variable double soln = floor(debugValues[jColumn] + 0.5); // Set bounds to fix variable to its solution siCopy->setColUpper(i, soln); siCopy->setColLower(i, soln); } } // All integers have been fixed at optimal value. // Now solve to get continuous values siCopy->setHintParam(OsiDoScale, false); siCopy->initialSolve(); if (siCopy->isProvenOptimal()) { memcpy(newValues, siCopy->getColSolution(), numberColumns*sizeof(double)); } else { printf("BAD debug file\n"); siCopy->writeMps("Bad"); exit(22); } delete siCopy; // for debug babModel_->solver()->activateRowCutDebugger(newValues) ; delete [] newValues; } else { printf("debug file has incorrect number of columns\n"); } } } babModel_->setCutoffIncrement(CoinMax(babModel_->getCutoffIncrement(), increment)); // Turn this off if you get problems // Used to be automatically set int mipOptions = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].intValue() % 10000; if (mipOptions != (1057)) { sprintf(generalPrint, "mip options %d", mipOptions); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } #ifndef CBC_OTHER_SOLVER osiclp->setSpecialOptions(mipOptions); #elif CBC_OTHER_SOLVER==1 #endif // probably faster to use a basis to get integer solutions babModel_->setSpecialOptions(babModel_->specialOptions() | 2); currentBranchModel = babModel_; //OsiSolverInterface * strengthenedModel=NULL; if (type == CBC_PARAM_ACTION_BAB || type == CBC_PARAM_ACTION_MIPLIB) { if (strategyFlag == 1) { // try reduced model babModel_->setSpecialOptions(babModel_->specialOptions() | 512); } if (experimentFlag >= 5 || strategyFlag == 2) { // try reduced model at root babModel_->setSpecialOptions(babModel_->specialOptions() | 32768); } { int depthMiniBab = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, numberParameters_, parameters_)].intValue(); if (depthMiniBab != -1) babModel_->setFastNodeDepth(depthMiniBab); } int extra4 = parameters_[whichParam(CBC_PARAM_INT_EXTRA4, numberParameters_, parameters_)].intValue(); if (extra4 >= 0) { int strategy = extra4 % 10; extra4 /= 10; int method = extra4 % 100; extra4 /= 100; extra4 = strategy + method * 8 + extra4 * 1024; babModel_->setMoreSpecialOptions(extra4); } int moreMipOptions = parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, numberParameters_, parameters_)].intValue(); if (moreMipOptions >= 0) { sprintf(generalPrint, "more mip options %d", moreMipOptions); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; #if 1 // some options may have been set already // e.g. use elapsed time babModel_->setMoreSpecialOptions(moreMipOptions|babModel_->moreSpecialOptions()); #else OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); if (moreMipOptions == 10000) { // test memory saving moreMipOptions -= 10000; ClpSimplex * lpSolver = osiclp->getModelPtr(); lpSolver->setPersistenceFlag(1); // switch off row copy if few rows if (lpSolver->numberRows() < 150) lpSolver->setSpecialOptions(lpSolver->specialOptions() | 256); } if (moreMipOptions < 10000 && moreMipOptions) { if (((moreMipOptions + 1) % 1000000) != 0) babModel_->setSearchStrategy(moreMipOptions % 1000000); } else if (moreMipOptions < 100000) { // try reduced model babModel_->setSpecialOptions(babModel_->specialOptions() | 512); } // go faster stripes if ( moreMipOptions >= 999999) { if (osiclp) { int save = osiclp->specialOptions(); osiclp->setupForRepeatedUse(2, 0); osiclp->setSpecialOptions(save | osiclp->specialOptions()); } } #endif } } { int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue(); if (extra1 != -1) { if (extra1 < 0) { if (extra1 == -7777) extra1 = -1; else if (extra1 == -8888) extra1 = 1; babModel_->setWhenCuts(-extra1); } else if (extra1 < 19000) { babModel_->setSearchStrategy(extra1); printf("XXXXX searchStrategy %d\n", extra1); } else { int n = extra1 - 20000; if (!n) n--; babModel_->setNumberAnalyzeIterations(n); printf("XXXXX analyze %d\n", extra1); } } else if (bothFlags >= 1) { babModel_->setWhenCuts(999998); } } if (type == CBC_PARAM_ACTION_BAB) { #ifdef COIN_HAS_ASL if (statusUserFunction_[0]) { priorities = info.priorities; branchDirection = info.branchDirection; pseudoDown = info.pseudoDown; pseudoUp = info.pseudoUp; solutionIn = info.primalSolution; prioritiesIn = info.priorities; if (info.numberSos && doSOS) { // SOS numberSOS = info.numberSos; sosStart = info.sosStart; sosIndices = info.sosIndices; sosType = info.sosType; sosReference = info.sosReference; sosPriority = info.sosPriority; } } #endif const int * originalColumns = preProcess ? process.originalColumns() : NULL; if (mipStart.size() && !mipStartBefore.size()) { std::vector< std::string > colNames; if (preProcess) { std::vector< std::pair< std::string, double > > mipStart2; for ( int i=0 ; (isolver()->getNumCols()) ; ++i ) { int iColumn = babModel_->originalColumns()[i]; if (iColumn>=0) { colNames.push_back( model_.solver()->getColName( iColumn ) ); babModel_->solver()->setColName(i,model_.solver()->getColName(iColumn)); mipStart2.push_back(mipStart[iColumn]); } else { // created variable char newName[15]; sprintf(newName,"C%7.7d",i); colNames.push_back( newName ); } } mipStart = mipStart2; } else { for ( int i=0 ; (isolver()->getNumCols()) ; ++i ) colNames.push_back( model_.solver()->getColName(i) ); } //printf("--- %s %d\n", babModel_->solver()->getColName(0).c_str(), babModel_->solver()->getColNames().size() ); //printf("-- SIZES of models %d %d %d\n", model_.getNumCols(), babModel_->solver()->getNumCols(), babModel_->solver()->getColNames().size() ); std::vector< double > x( babModel_->getNumCols(), 0.0 ); double obj; int status = computeCompleteSolution( babModel_, colNames, mipStart, &x[0], obj ); if (!status) babModel_->setBestSolution( &x[0], static_cast(x.size()), obj, false ); } if (solutionIn && useSolution >= 0) { if (!prioritiesIn) { int n; if (preProcess) { int numberColumns = babModel_->getNumCols(); // extend arrays in case SOS n = originalColumns[numberColumns-1] + 1; } else { n = babModel_->getNumCols(); } prioritiesIn = reinterpret_cast (malloc(n * sizeof(int))); for (int i = 0; i < n; i++) prioritiesIn[i] = 100; } if (preProcess) { int numberColumns = babModel_->getNumCols(); // extend arrays in case SOS int n = originalColumns[numberColumns-1] + 1; int nSmaller = CoinMin(n, numberOriginalColumns); double * solutionIn2 = new double [n]; int * prioritiesIn2 = new int[n]; int i; for (i = 0; i < nSmaller; i++) { solutionIn2[i] = solutionIn[i]; prioritiesIn2[i] = prioritiesIn[i]; } for (; i < n; i++) { solutionIn2[i] = 0.0; prioritiesIn2[i] = 1000000; } #ifndef NDEBUG int iLast = -1; #endif for (i = 0; i < numberColumns; i++) { int iColumn = originalColumns[i]; #ifndef NDEBUG assert (iColumn > iLast); iLast = iColumn; #endif solutionIn2[i] = solutionIn2[iColumn]; if (prioritiesIn) prioritiesIn2[i] = prioritiesIn2[iColumn]; } if (useSolution) babModel_->setHotstartSolution(solutionIn2, prioritiesIn2); else babModel_->setBestSolution(solutionIn2, numberColumns, COIN_DBL_MAX, true); delete [] solutionIn2; delete [] prioritiesIn2; } else { if (useSolution) babModel_->setHotstartSolution(solutionIn, prioritiesIn); else babModel_->setBestSolution(solutionIn, babModel_->getNumCols(), COIN_DBL_MAX, true); } } OsiSolverInterface * testOsiSolver = (testOsiOptions >= 0) ? babModel_->solver() : NULL; if (!testOsiSolver) { // ************************************************************* // CbcObjects if (preProcess && (process.numberSOS() || babModel_->numberObjects())) { int numberSOS = process.numberSOS(); int numberIntegers = babModel_->numberIntegers(); /* model may not have created objects If none then create */ if (!numberIntegers || !babModel_->numberObjects()) { int type = (pseudoUp) ? 1 : 0; babModel_->findIntegers(true, type); numberIntegers = babModel_->numberIntegers(); integersOK = true; } OsiObject ** oldObjects = babModel_->objects(); // Do sets and priorities OsiObject ** objects = new OsiObject * [numberSOS]; // set old objects to have low priority int numberOldObjects = babModel_->numberObjects(); int numberColumns = babModel_->getNumCols(); // backward pointer to new variables // extend arrays in case SOS assert (originalColumns); int n = CoinMin(truncateColumns,numberColumns); n = originalColumns[n-1] + 1; n = CoinMax(n, CoinMax(numberColumns, numberOriginalColumns)); int * newColumn = new int[n]; int i; for (i = 0; i < numberOriginalColumns; i++) newColumn[i] = -1; for (i = 0; i < CoinMin(truncateColumns,numberColumns); i++) newColumn[originalColumns[i]] = i; if (!integersOK) { // Change column numbers etc int n = 0; for (int iObj = 0; iObj < numberOldObjects; iObj++) { int iColumn = oldObjects[iObj]->columnNumber(); if (iColumn < 0 || iColumn >= numberOriginalColumns) { oldObjects[n++] = oldObjects[iObj]; } else { iColumn = newColumn[iColumn]; if (iColumn >= 0) { CbcSimpleInteger * obj = dynamic_cast (oldObjects[iObj]) ; if (obj) { obj->setColumnNumber(iColumn); } else { // only other case allowed is lotsizing CbcLotsize * obj2 = dynamic_cast (oldObjects[iObj]) ; assert (obj2); obj2->setModelSequence(iColumn); } oldObjects[n++] = oldObjects[iObj]; } else { delete oldObjects[iObj]; } } } babModel_->setNumberObjects(n); numberOldObjects = n; babModel_->zapIntegerInformation(); } int nMissing = 0; for (int iObj = 0; iObj < numberOldObjects; iObj++) { if (process.numberSOS()) oldObjects[iObj]->setPriority(numberColumns + 1); int iColumn = oldObjects[iObj]->columnNumber(); if (iColumn < 0 || iColumn >= numberOriginalColumns) { CbcSOS * obj = dynamic_cast (oldObjects[iObj]) ; if (obj) { int n = obj->numberMembers(); int * which = obj->mutableMembers(); double * weights = obj->mutableWeights(); int nn = 0; for (i = 0; i < n; i++) { int iColumn = which[i]; int jColumn = newColumn[iColumn]; if (jColumn >= 0) { which[nn] = jColumn; weights[nn++] = weights[i]; } else { nMissing++; } } obj->setNumberMembers(nn); } continue; } if (originalColumns) iColumn = originalColumns[iColumn]; if (branchDirection) { CbcSimpleInteger * obj = dynamic_cast (oldObjects[iObj]) ; if (obj) { obj->setPreferredWay(branchDirection[iColumn]); } else { CbcObject * obj = dynamic_cast (oldObjects[iObj]) ; assert (obj); obj->setPreferredWay(branchDirection[iColumn]); } } if (pseudoUp) { CbcSimpleIntegerPseudoCost * obj1a = dynamic_cast (oldObjects[iObj]) ; assert (obj1a); if (pseudoDown[iColumn] > 0.0) obj1a->setDownPseudoCost(pseudoDown[iColumn]); if (pseudoUp[iColumn] > 0.0) obj1a->setUpPseudoCost(pseudoUp[iColumn]); } } if (nMissing) { sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } delete [] newColumn; const int * starts = process.startSOS(); const int * which = process.whichSOS(); const int * type = process.typeSOS(); const double * weight = process.weightSOS(); int iSOS; for (iSOS = 0; iSOS < numberSOS; iSOS++) { int iStart = starts[iSOS]; int n = starts[iSOS+1] - iStart; objects[iSOS] = new CbcSOS(babModel_, n, which + iStart, weight + iStart, iSOS, type[iSOS]); // branch on long sets first objects[iSOS]->setPriority(numberColumns - n); } if (numberSOS) babModel_->addObjects(numberSOS, objects); for (iSOS = 0; iSOS < numberSOS; iSOS++) delete objects[iSOS]; delete [] objects; } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) { // do anyway for priorities etc int numberIntegers = babModel_->numberIntegers(); /* model may not have created objects If none then create */ if (!numberIntegers || !babModel_->numberObjects()) { int type = (pseudoUp) ? 1 : 0; babModel_->findIntegers(true, type); } if (numberSOS) { // Do sets and priorities OsiObject ** objects = new OsiObject * [numberSOS]; int iSOS; if (originalColumns) { // redo sequence numbers int numberColumns = babModel_->getNumCols(); int nOld = originalColumns[numberColumns-1] + 1; int * back = new int[nOld]; int i; for (i = 0; i < nOld; i++) back[i] = -1; for (i = 0; i < numberColumns; i++) back[originalColumns[i]] = i; // Really need better checks int nMissing = 0; int n = sosStart[numberSOS]; for (i = 0; i < n; i++) { int iColumn = sosIndices[i]; int jColumn = back[iColumn]; if (jColumn >= 0) sosIndices[i] = jColumn; else nMissing++; } delete [] back; if (nMissing) { sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } for (iSOS = 0; iSOS < numberSOS; iSOS++) { int iStart = sosStart[iSOS]; int n = sosStart[iSOS+1] - iStart; objects[iSOS] = new CbcSOS(babModel_, n, sosIndices + iStart, sosReference + iStart, iSOS, sosType[iSOS]); if (sosPriority) objects[iSOS]->setPriority(sosPriority[iSOS]); else if (!prioritiesIn) objects[iSOS]->setPriority(10); // rather than 1000 } // delete any existing SOS objects int numberObjects = babModel_->numberObjects(); OsiObject ** oldObjects = babModel_->objects(); int nNew = 0; for (int i = 0; i < numberObjects; i++) { OsiObject * objThis = oldObjects[i]; CbcSOS * obj1 = dynamic_cast (objThis) ; OsiSOS * obj2 = dynamic_cast (objThis) ; if (!obj1 && !obj2) { oldObjects[nNew++] = objThis; } else { delete objThis; } } babModel_->setNumberObjects(nNew); babModel_->addObjects(numberSOS, objects); for (iSOS = 0; iSOS < numberSOS; iSOS++) delete objects[iSOS]; delete [] objects; } } OsiObject ** objects = babModel_->objects(); int numberObjects = babModel_->numberObjects(); for (int iObj = 0; iObj < numberObjects; iObj++) { // skip sos CbcSOS * objSOS = dynamic_cast (objects[iObj]) ; if (objSOS) continue; int iColumn = objects[iObj]->columnNumber(); assert (iColumn >= 0); if (originalColumns) iColumn = originalColumns[iColumn]; if (branchDirection) { CbcSimpleInteger * obj = dynamic_cast (objects[iObj]) ; if (obj) { obj->setPreferredWay(branchDirection[iColumn]); } else { CbcObject * obj = dynamic_cast (objects[iObj]) ; assert (obj); obj->setPreferredWay(branchDirection[iColumn]); } } if (priorities) { int iPriority = priorities[iColumn]; if (iPriority > 0) objects[iObj]->setPriority(iPriority); } if (pseudoUp && pseudoUp[iColumn]) { CbcSimpleIntegerPseudoCost * obj1a = dynamic_cast (objects[iObj]) ; assert (obj1a); if (pseudoDown[iColumn] > 0.0) obj1a->setDownPseudoCost(pseudoDown[iColumn]); if (pseudoUp[iColumn] > 0.0) obj1a->setUpPseudoCost(pseudoUp[iColumn]); } } // ************************************************************* } else { // ************************************************************* // OsiObjects // Find if none int numberIntegers = testOsiSolver->getNumIntegers(); /* model may not have created objects If none then create */ if (!numberIntegers || !testOsiSolver->numberObjects()) { //int type = (pseudoUp) ? 1 : 0; testOsiSolver->findIntegers(false); numberIntegers = testOsiSolver->getNumIntegers(); } if (preProcess && process.numberSOS()) { int numberSOS = process.numberSOS(); OsiObject ** oldObjects = testOsiSolver->objects(); // Do sets and priorities OsiObject ** objects = new OsiObject * [numberSOS]; // set old objects to have low priority int numberOldObjects = testOsiSolver->numberObjects(); int numberColumns = testOsiSolver->getNumCols(); for (int iObj = 0; iObj < numberOldObjects; iObj++) { oldObjects[iObj]->setPriority(numberColumns + 1); int iColumn = oldObjects[iObj]->columnNumber(); assert (iColumn >= 0); if (iColumn >= numberOriginalColumns) continue; if (originalColumns) iColumn = originalColumns[iColumn]; if (branchDirection) { OsiSimpleInteger * obj = dynamic_cast (oldObjects[iObj]) ; if (obj) { obj->setPreferredWay(branchDirection[iColumn]); } else { OsiObject2 * obj = dynamic_cast (oldObjects[iObj]) ; if (obj) obj->setPreferredWay(branchDirection[iColumn]); } } if (pseudoUp) { abort(); } } const int * starts = process.startSOS(); const int * which = process.whichSOS(); const int * type = process.typeSOS(); const double * weight = process.weightSOS(); int iSOS; for (iSOS = 0; iSOS < numberSOS; iSOS++) { int iStart = starts[iSOS]; int n = starts[iSOS+1] - iStart; objects[iSOS] = new OsiSOS(testOsiSolver, n, which + iStart, weight + iStart, type[iSOS]); // branch on long sets first objects[iSOS]->setPriority(numberColumns - n); } testOsiSolver->addObjects(numberSOS, objects); for (iSOS = 0; iSOS < numberSOS; iSOS++) delete objects[iSOS]; delete [] objects; } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) { if (numberSOS) { // Do sets and priorities OsiObject ** objects = new OsiObject * [numberSOS]; int iSOS; if (originalColumns) { // redo sequence numbers int numberColumns = testOsiSolver->getNumCols(); int nOld = originalColumns[numberColumns-1] + 1; int * back = new int[nOld]; int i; for (i = 0; i < nOld; i++) back[i] = -1; for (i = 0; i < numberColumns; i++) back[originalColumns[i]] = i; // Really need better checks int nMissing = 0; int n = sosStart[numberSOS]; for (i = 0; i < n; i++) { int iColumn = sosIndices[i]; int jColumn = back[iColumn]; if (jColumn >= 0) sosIndices[i] = jColumn; else nMissing++; } delete [] back; if (nMissing) { sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } for (iSOS = 0; iSOS < numberSOS; iSOS++) { int iStart = sosStart[iSOS]; int n = sosStart[iSOS+1] - iStart; objects[iSOS] = new OsiSOS(testOsiSolver, n, sosIndices + iStart, sosReference + iStart, sosType[iSOS]); if (sosPriority) objects[iSOS]->setPriority(sosPriority[iSOS]); else if (!prioritiesIn) objects[iSOS]->setPriority(10); // rather than 1000 } // delete any existing SOS objects int numberObjects = testOsiSolver->numberObjects(); OsiObject ** oldObjects = testOsiSolver->objects(); int nNew = 0; for (int i = 0; i < numberObjects; i++) { OsiObject * objThis = oldObjects[i]; OsiSOS * obj1 = dynamic_cast (objThis) ; OsiSOS * obj2 = dynamic_cast (objThis) ; if (!obj1 && !obj2) { oldObjects[nNew++] = objThis; } else { delete objThis; } } testOsiSolver->setNumberObjects(nNew); testOsiSolver->addObjects(numberSOS, objects); for (iSOS = 0; iSOS < numberSOS; iSOS++) delete objects[iSOS]; delete [] objects; } } OsiObject ** objects = testOsiSolver->objects(); int numberObjects = testOsiSolver->numberObjects(); int logLevel = parameters_[log].intValue(); for (int iObj = 0; iObj < numberObjects; iObj++) { // skip sos OsiSOS * objSOS = dynamic_cast (objects[iObj]) ; if (objSOS) { if (logLevel > 2) printf("Set %d is SOS - priority %d\n", iObj, objSOS->priority()); continue; } int iColumn = objects[iObj]->columnNumber(); if (iColumn >= 0) { if (originalColumns) iColumn = originalColumns[iColumn]; if (branchDirection) { OsiSimpleInteger * obj = dynamic_cast (objects[iObj]) ; if (obj) { obj->setPreferredWay(branchDirection[iColumn]); } else { OsiObject2 * obj = dynamic_cast (objects[iObj]) ; if (obj) obj->setPreferredWay(branchDirection[iColumn]); } } if (priorities) { int iPriority = priorities[iColumn]; if (iPriority > 0) objects[iObj]->setPriority(iPriority); } if (logLevel > 2) printf("Obj %d is int? - priority %d\n", iObj, objects[iObj]->priority()); if (pseudoUp && pseudoUp[iColumn]) { abort(); } } } // ************************************************************* } int statistics = (printOptions > 0) ? printOptions : 0; #ifdef COIN_HAS_ASL if (!statusUserFunction_[0]) { #endif free(priorities); priorities = NULL; free(branchDirection); branchDirection = NULL; free(pseudoDown); pseudoDown = NULL; free(pseudoUp); pseudoUp = NULL; free(solutionIn); solutionIn = NULL; free(prioritiesIn); prioritiesIn = NULL; free(sosStart); sosStart = NULL; free(sosIndices); sosIndices = NULL; free(sosType); sosType = NULL; free(sosReference); sosReference = NULL; free(cut); cut = NULL; free(sosPriority); sosPriority = NULL; #ifdef COIN_HAS_ASL } #endif if (nodeStrategy) { // change default if (nodeStrategy > 2) { // up or down int way = (((nodeStrategy - 1) % 1) == 1) ? -1 : +1; babModel_->setPreferredWay(way); #ifdef JJF_ZERO OsiObject ** objects = babModel_->objects(); int numberObjects = babModel_->numberObjects(); for (int iObj = 0; iObj < numberObjects; iObj++) { CbcObject * obj = dynamic_cast (objects[iObj]) ; assert (obj); obj->setPreferredWay(way); } #endif } if (nodeStrategy == 2 || nodeStrategy > 4) { // depth CbcCompareDefault compare; compare.setWeight(-3.0); babModel_->setNodeComparison(compare); } else if (nodeStrategy == 0) { // hybrid was default i.e. mixture of low depth and infeasibility } else if (nodeStrategy == 1) { // real fewest CbcCompareDefault compare; compare.setWeight(-2.0); babModel_->setNodeComparison(compare); } } if (cppValue >= 0) { int prepro = useStrategy ? -1 : preProcess; // generate code FILE * fp = fopen("user_driver.cpp", "w"); if (fp) { // generate enough to do BAB babModel_->generateCpp(fp, 1); OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); // Make general so do factorization int factor = osiclp->getModelPtr()->factorizationFrequency(); osiclp->getModelPtr()->setFactorizationFrequency(200); osiclp->generateCpp(fp); osiclp->getModelPtr()->setFactorizationFrequency(factor); //solveOptions.generateCpp(fp); fclose(fp); // now call generate code generateCode(babModel_, "user_driver.cpp", cppValue, prepro); } else { std::cout << "Unable to open file user_driver.cpp" << std::endl; } } if (!babModel_->numberStrong() && babModel_->numberBeforeTrust() > 0) babModel_->setNumberBeforeTrust(0); if (useStrategy) { CbcStrategyDefault strategy(1, babModel_->numberStrong(), babModel_->numberBeforeTrust()); strategy.setupPreProcessing(1); babModel_->setStrategy(strategy); } if (testOsiOptions >= 0) { sprintf(generalPrint, "Testing OsiObject options %d", testOsiOptions); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; if (!numberSOS) { babModel_->solver()->findIntegersAndSOS(false); #ifdef COIN_HAS_LINK // If linked then pass in model OsiSolverLink * solver3 = dynamic_cast (babModel_->solver()); if (solver3) { CbcHeuristicDynamic3 serendipity(*babModel_); serendipity.setHeuristicName("linked"); babModel_->addHeuristic(&serendipity); double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue(); if (dextra3) solver3->setMeshSizes(dextra3); int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].intValue() / 10000; CglStored stored; if (options) { printf("nlp options %d\n", options); /* 1 - force mini branch and bound 2 - set priorities high on continuous 4 - try adding OA cuts 8 - try doing quadratic linearization 16 - try expanding knapsacks 32 - OA cuts strictly concave 64 - no branching at all on bilinear x-x! */ if ((options&2)) { solver3->setBiLinearPriorities(10, tightenFactor > 0.0 ? tightenFactor : 1.0); } else if (tightenFactor > 0.0) { // set grid size for all continuous bi-linear solver3->setMeshSizes(tightenFactor); } if ((options&4)) { solver3->setSpecialOptions2(solver3->specialOptions2() | (8 + 4)); // say convex solver3->sayConvex((options&32) == 0); } int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue(); if ((options&1) != 0 && extra1 > 0) solver3->setFixedPriority(extra1); double cutoff = COIN_DBL_MAX; if ((options&8)) cutoff = solver3->linearizedBAB(&stored); if (cutoff < babModel_->getCutoff()) { babModel_->setCutoff(cutoff); // and solution //babModel_->setBestObjectiveValue(solver3->bestObjectiveValue()); babModel_->setBestSolution(solver3->bestSolution(), solver3->getNumCols(), solver3->bestObjectiveValue()); } if ((options&64)) solver3->setBranchingStrategyOnVariables(16, -1, 4); } solver3->setCbcModel(babModel_); if (stored.sizeRowCuts()) babModel_->addCutGenerator(&stored, 1, "Stored"); CglTemporary temp; babModel_->addCutGenerator(&temp, 1, "OnceOnly"); //choose.setNumberBeforeTrusted(2000); //choose.setNumberStrong(20); } // For temporary testing of heuristics //int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI,numberParameters_,parameters_)].intValue(); if (testOsiOptions >= 10) { if (testOsiOptions >= 20) testOsiOptions -= 10; printf("*** Temp heuristic with mode %d\n", testOsiOptions - 10); OsiSolverLink * solver3 = dynamic_cast (babModel_->solver()); assert (solver3) ; int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue(); solver3->setBiLinearPriority(extra1); printf("bilinear priority now %d\n", extra1); int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, numberParameters_, parameters_)].intValue(); double saveDefault = solver3->defaultBound(); solver3->setDefaultBound(static_cast (extra2)); double * solution = solver3->heuristicSolution(slpValue > 0 ? slpValue : 40 , 1.0e-5, testOsiOptions - 10); solver3->setDefaultBound(saveDefault); if (!solution) printf("Heuristic failed\n"); } #endif } else { // move across babModel_->deleteObjects(false); //babModel_->addObjects(babModel_->solver()->numberObjects(),babModel_->solver()->objects()); } CbcBranchDefaultDecision decision; if (babModel_->numberStrong()) { OsiChooseStrong choose(babModel_->solver()); choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust()); choose.setNumberStrong(babModel_->numberStrong()); choose.setShadowPriceMode(testOsiOptions); decision.setChooseMethod(choose); } else { OsiChooseVariable choose(babModel_->solver()); decision.setChooseMethod(choose); } babModel_->setBranchingMethod(decision); if (useCosts && testOsiOptions >= 0) { if(newPriorities ) { // get rid of delete [] newPriorities; newPriorities = NULL; } int numberColumns = babModel_->getNumCols(); int * sort = new int[numberColumns]; double * dsort = new double[numberColumns]; int * priority = new int [numberColumns]; const double * objective = babModel_->getObjCoefficients(); const double * lower = babModel_->getColLower() ; const double * upper = babModel_->getColUpper() ; const CoinPackedMatrix * matrix = babModel_->solver()->getMatrixByCol(); const int * columnLength = matrix->getVectorLengths(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { sort[iColumn] = iColumn; if (useCosts == 1) dsort[iColumn] = -fabs(objective[iColumn]); else if (useCosts == 2) dsort[iColumn] = iColumn; else if (useCosts == 3) dsort[iColumn] = upper[iColumn] - lower[iColumn]; else if (useCosts == 4) dsort[iColumn] = -(upper[iColumn] - lower[iColumn]); else if (useCosts == 5) dsort[iColumn] = -columnLength[iColumn]; } CoinSort_2(dsort, dsort + numberColumns, sort); int level = 0; double last = -1.0e100; for (int i = 0; i < numberColumns; i++) { int iPut = sort[i]; if (dsort[i] != last) { level++; last = dsort[i]; } priority[iPut] = level; } OsiObject ** objects = babModel_->objects(); int numberObjects = babModel_->numberObjects(); for (int iObj = 0; iObj < numberObjects; iObj++) { OsiObject * obj = objects[iObj] ; int iColumn = obj->columnNumber(); if (iColumn >= 0) obj->setPriority(priority[iColumn]); } delete [] priority; delete [] sort; delete [] dsort; } } checkSOS(babModel_, babModel_->solver()); if (doSprint > 0) { // Sprint for primal solves ClpSolve::SolveType method = ClpSolve::usePrimalorSprint; ClpSolve::PresolveType presolveType = ClpSolve::presolveOff; int numberPasses = 5; int options[] = {0, 3, 0, 0, 0, 0}; int extraInfo[] = { -1, 20, -1, -1, -1, -1}; extraInfo[1] = doSprint; int independentOptions[] = {0, 0, 3}; ClpSolve clpSolve(method, presolveType, numberPasses, options, extraInfo, independentOptions); // say use in OsiClp clpSolve.setSpecialOption(6, 1); OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); osiclp->setSolveOptions(clpSolve); osiclp->setHintParam(OsiDoDualInResolve, false); // switch off row copy osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256); osiclp->getModelPtr()->setInfeasibilityCost(1.0e11); } #ifdef COIN_HAS_LINK if (storedAmpl.sizeRowCuts()) { if (preProcess) { const int * originalColumns = process.originalColumns(); int numberColumns = babModel_->getNumCols(); int * newColumn = new int[numberOriginalColumns]; int i; for (i = 0; i < numberOriginalColumns; i++) newColumn[i] = -1; for (i = 0; i < numberColumns; i++) { int iColumn = originalColumns[i]; newColumn[iColumn] = i; } int * buildColumn = new int[numberColumns]; // Build up valid cuts int nBad = 0; int nCuts = storedAmpl.sizeRowCuts(); CglStored newCuts; for (i = 0; i < nCuts; i++) { const OsiRowCut * cut = storedAmpl.rowCutPointer(i); double lb = cut->lb(); double ub = cut->ub(); int n = cut->row().getNumElements(); const int * column = cut->row().getIndices(); const double * element = cut->row().getElements(); bool bad = false; for (int i = 0; i < n; i++) { int iColumn = column[i]; iColumn = newColumn[iColumn]; if (iColumn >= 0) { buildColumn[i] = iColumn; } else { bad = true; break; } } if (!bad) { newCuts.addCut(lb, ub, n, buildColumn, element); } else { nBad++; } } storedAmpl = newCuts; if (nBad) printf("%d cuts dropped\n", nBad); delete [] newColumn; delete [] buildColumn; } } #endif #ifdef CLP_MALLOC_STATISTICS malloc_stats(); malloc_stats2(); #endif #ifndef CBC_OTHER_SOLVER if (outputFormat == 5) { osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); lpSolver = osiclp->getModelPtr(); lpSolver->setPersistenceFlag(1); } #endif #ifdef COIN_HAS_ASL // add in lotsizing if (statusUserFunction_[0] && info.special) { int numberColumns = babModel_->getNumCols(); int i; int n = 0; if (preProcess) { const int * originalColumns = process.originalColumns(); for (i = 0; i < numberColumns; i++) { int iColumn = originalColumns[i]; assert (iColumn >= i); int iType = info.special[iColumn]; if (iType) { assert (iType == 1); n++; } info.special[i] = iType; } } if (n) { int numberIntegers = 0; int numberOldObjects = 0; OsiObject ** oldObjects = NULL; const double * lower = babModel_->solver()->getColLower(); const double * upper = babModel_->solver()->getColUpper(); if (testOsiOptions < 0) { // ************************************************************* // CbcObjects numberIntegers = babModel_->numberIntegers(); /* model may not have created objects If none then create */ if (!numberIntegers || !babModel_->numberObjects()) { int type = (pseudoUp) ? 1 : 0; babModel_->findIntegers(true, type); numberIntegers = babModel_->numberIntegers(); } oldObjects = babModel_->objects(); numberOldObjects = babModel_->numberObjects(); } else { numberIntegers = testOsiSolver->getNumIntegers(); if (!numberIntegers || !testOsiSolver->numberObjects()) { /* model may not have created objects If none then create */ testOsiSolver->findIntegers(false); numberIntegers = testOsiSolver->getNumIntegers(); } oldObjects = testOsiSolver->objects(); numberOldObjects = testOsiSolver->numberObjects(); } OsiObject ** objects = new OsiObject * [n]; n = 0; // set new objects to have one lower priority double ranges[] = { -COIN_DBL_MAX, -1.0, 1.0, COIN_DBL_MAX}; for (int iObj = 0; iObj < numberOldObjects; iObj++) { int iColumn = oldObjects[iObj]->columnNumber(); if (iColumn >= 0 && info.special[iColumn]) { if (lower[iColumn] <= -1.0 && upper[iColumn] >= 0.0) { ranges[0] = lower[iColumn]; ranges[3] = upper[iColumn]; int priority = oldObjects[iObj]->priority(); if (testOsiOptions < 0) { objects[n] = new CbcLotsize(babModel_, iColumn, 2, ranges, true); } else { objects[n] = new OsiLotsize(testOsiSolver, iColumn, 2, ranges, true); } objects[n++]->setPriority (priority - 1); } } } if (testOsiOptions < 0) { babModel_->addObjects(n, objects); } else { testOsiSolver->addObjects(n, objects); } for (i = 0; i < n; i++) delete objects[i]; delete [] objects; } } #endif if (storedAmpl.sizeRowCuts()) { //babModel_->addCutGenerator(&storedAmpl,1,"AmplStored"); int numberRowCuts = storedAmpl.sizeRowCuts(); for (int i = 0; i < numberRowCuts; i++) { const OsiRowCut * rowCutPointer = storedAmpl.rowCutPointer(i); babModel_->makeGlobalCut(rowCutPointer); } } // If defaults then increase trust for small models if (!strongChanged) { int numberColumns = babModel_->getNumCols(); if (numberColumns <= 50) babModel_->setNumberBeforeTrust(1000); else if (numberColumns <= 100) babModel_->setNumberBeforeTrust(100); else if (numberColumns <= 300) babModel_->setNumberBeforeTrust(50); } #ifdef CBC_THREAD int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].intValue(); babModel_->setNumberThreads(numberThreads % 100); babModel_->setThreadMode(numberThreads / 100); #endif int returnCode = callBack(babModel_, 3); if (returnCode) { // exit if user wants delete babModel_; babModel_ = NULL; return returnCode; } #ifndef CBC_OTHER_SOLVER osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); lpSolver = osiclp->getModelPtr(); #elif CBC_OTHER_SOLVER==1 #endif if ((experimentFlag >= 1 || strategyFlag >= 1) && babModel_->fastNodeDepth() == -1) { if (babModel_->solver()->getNumCols() + babModel_->solver()->getNumRows() < 500) babModel_->setFastNodeDepth(-12); } else if (babModel_->fastNodeDepth() == -999) { babModel_->setFastNodeDepth(-1); } int heurOptions = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue(); if (heurOptions > 100) babModel_->setSpecialOptions(babModel_->specialOptions() | 8192); #ifndef CBC_OTHER_SOLVER #ifdef CLP_MULTIPLE_FACTORIZATIONS int denseCode = parameters_[whichParam(CBC_PARAM_INT_DENSE, numberParameters_, parameters_)].intValue(); int smallCode = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, numberParameters_, parameters_)].intValue(); if (bothFlags >= 1) { if (denseCode < 0) denseCode = 40; if (smallCode < 0 && !lpSolver->factorization()->isDenseOrSmall()) smallCode = 40; } if (denseCode > 0) { lpSolver->factorization()->setGoDenseThreshold(denseCode); assert (osiclp == babModel_->solver()); osiclp->setSpecialOptions(osiclp->specialOptions() | 1024); } if (smallCode > 0 && smallCode > denseCode) lpSolver->factorization()->setGoSmallThreshold(smallCode); //if (denseCode>=lpSolver->numberRows()) { //lpSolver->factorization()->goDense(); //} if (lpSolver->factorization()->goOslThreshold() > 1000) { // use osl in gomory (may not if CglGomory decides not to) int numberGenerators = babModel_->numberCutGenerators(); int nGomory=0; for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = babModel_->cutGenerator(iGenerator); CglGomory * gomory = dynamic_cast (generator->generator()); if (gomory) { if (nGomory<2) { gomory->useAlternativeFactorization(); } else if (gomory->originalSolver()) { OsiClpSolverInterface * clpSolver = dynamic_cast(gomory->originalSolver()); if (clpSolver) { ClpSimplex * simplex = clpSolver->getModelPtr(); simplex->factorization()->setGoOslThreshold(0); } } nGomory++; } } } #endif #endif #ifdef CLIQUE_ANALYSIS if (!storedAmpl.sizeRowCuts()) { printf("looking at probing\n"); babModel_->addCutGenerator(&storedAmpl, 1, "Stored"); } #endif if (useSolution > 1) { // use hotstart to try and find solution CbcHeuristicPartial partial(*babModel_, 10000, useSolution); partial.setHeuristicName("Partial solution given"); babModel_->addHeuristic(&partial); } if (logLevel <= 1) babModel_->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); #ifdef CBC_TEMP1 if (osiclp->getModelPtr()->perturbation() == 50) osiclp->getModelPtr()->setPerturbation(52); // try less #endif #ifdef JJF_ZERO if (osiclp->getNumCols() == 29404) { void restoreSolution(ClpSimplex * lpSolver, std::string fileName, int mode); restoreSolution(osiclp->getModelPtr(), "debug.file", 0); int numberColumns = osiclp->getNumCols(); const double * solution = osiclp->getColSolution(); const int * originalColumns = process.originalColumns(); for (int i = 0; i < numberColumns; i++) { int iColumn = originalColumns[i]; if (saveSolver->isInteger(iColumn)) { double value = solution[i]; double value2 = floor(value + 0.5); assert (fabs(value - value2) < 1.0e-3); saveSolver->setColLower(iColumn, value2); saveSolver->setColUpper(iColumn, value2); } } saveSolver->writeMps("fixed"); babModel_->setBestSolution(osiclp->getColSolution(), osiclp->getNumCols(), 1.5325e10); } else { babModel_->branchAndBound(statistics); } #else #ifdef ORBITAL CbcOrbital orbit(babModel_); orbit.morph(); exit(1); #endif int hOp1 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue() / 100000; if (hOp1 % 10) { CbcCompareDefault compare; compare.setBreadthDepth(hOp1 % 10); babModel_->setNodeComparison(compare); } #if CBC_OTHER_SOLVER==1 if (dynamic_cast (babModel_->solver())) babModel_->solver()->messageHandler()->setLogLevel(0); #endif if (parameters_[whichParam(CBC_PARAM_STR_CPX, numberParameters_, parameters_)].currentOptionAsInteger()) { babModel_->setSpecialOptions(babModel_->specialOptions() | 16384); //if (babModel_->fastNodeDepth()==-1) babModel_->setFastNodeDepth(-2); // Use Cplex at root } int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue() / 10000; if (hOp2 % 10) { babModel_->setSpecialOptions(babModel_->specialOptions() | 16384); if (babModel_->fastNodeDepth() == -1) babModel_->setFastNodeDepth(-2); // Use Cplex at root } if (experimentFlag >= 5) { CbcModel donor(*babModel_); int options = babModel_->specialOptions(); donor.setSpecialOptions(options | 262144); ClpSimplex * lpSolver2; OsiClpSolverInterface * clpSolver2; clpSolver2 = dynamic_cast (donor.solver()); assert (clpSolver2); lpSolver2 = clpSolver2->getModelPtr(); assert (lpSolver2); if (lpSolver->factorization()->isDenseOrSmall()) { lpSolver2->factorization()->forceOtherFactorization(0); lpSolver2->factorization()->setGoOslThreshold(0); lpSolver2->factorization()->setGoDenseThreshold(0); lpSolver2->factorization()->setGoSmallThreshold(0); lpSolver2->allSlackBasis(); lpSolver2->initialSolve(); int numberGenerators = donor.numberCutGenerators(); for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = donor.cutGenerator(iGenerator); CglGomory * gomory = dynamic_cast (generator->generator()); if (gomory) gomory->useAlternativeFactorization(false); } } else { printf("code this\n"); abort(); } babModel_->setSpecialOptions(options | 524288); CglStored * stored = new CglStored(donor.getNumCols()); donor.setStoredRowCuts(stored); donor.branchAndBound(0); babModel_->setStoredRowCuts(donor.storedRowCuts()); donor.setStoredRowCuts(NULL); } // We may have priorities from extra variables if(newPriorities ) { if (truncateColumnsgetNumCols()) { // set new ones as high prority babModel_->passInPriorities(newPriorities,false); } delete [] newPriorities; } #ifdef JJF_ZERO int extra5 = parameters_[whichParam(EXTRA5, numberParameters_, parameters_)].intValue(); if (extra5 > 0) { int numberGenerators = babModel_->numberCutGenerators(); for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = babModel_->cutGenerator(iGenerator); CglGomory * gomory = dynamic_cast (generator->generator()); if (gomory) { CglGomory gomory2(*gomory); gomory2.useAlternativeFactorization(!gomory->alternativeFactorization()); babModel_->addCutGenerator(&gomory2, -99, "Gomory2"); } } } #endif int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, numberParameters_, parameters_)].intValue(); if (specialOptions>=0) babModel_->setStrongStrategy(specialOptions); int jParam = whichParam(CBC_PARAM_STR_CUTOFF_CONSTRAINT, numberParameters_, parameters_); if(parameters_[jParam].currentOptionAsInteger()) babModel_->setCutoffAsConstraint(true); int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, numberParameters_, parameters_)].intValue(); if (multipleRoot<10000) { babModel_->setMultipleRootTries(multipleRoot); } else { // will be doing repeated solves and saves int numberGoes=multipleRoot/10000; multipleRoot-=10000*numberGoes; int moreOptions=babModel_->moreSpecialOptions(); if (numberGoes<100) { remove("global.cuts"); remove("global.fix"); moreOptions |= (67108864|134217728); } else { moreOptions |= 67108864*(numberGoes/100); numberGoes=numberGoes%100; } babModel_->setMultipleRootTries(multipleRoot); babModel_->setMoreSpecialOptions(moreOptions); int numberColumns=babModel_->getNumCols(); double * bestValues=new double [numberGoes]; double ** bestSolutions=new double * [numberGoes]; int * which=new int[numberGoes]; int numberSolutions=0; sprintf(generalPrint,"Starting %d passes each with %d solvers", numberGoes, multipleRoot%10); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; for (int iGo=0;iGomessage(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; CbcModel tempModel=*babModel_; tempModel.setMaximumNodes(0); // switch off cuts if none generated int numberGenerators = tempModel.numberCutGenerators(); for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = tempModel.cutGenerator(iGenerator); generator->setSwitchOffIfLessThan(1); } // random tempModel.setRandomSeed(tempModel.getRandomSeed()+100000000*(iGo+1+5*numberGoes)); for (int i=0;isetSeed(tempModel.heuristic(i)->getSeed()+100000000*iGo); #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * solver = dynamic_cast (tempModel.solver()); ClpSimplex * simplex = solver->getModelPtr(); int solverSeed=simplex->randomNumberGenerator()->getSeed(); simplex->setRandomSeed(solverSeed+100000000*(iGo+1)); #endif tempModel.branchAndBound(); if (tempModel.bestSolution()) { bestSolutions[numberSolutions]= CoinCopyOfArray(tempModel.bestSolution(), numberColumns); bestValues[numberSolutions]=-tempModel.getMinimizationObjValue(); which[numberSolutions]=numberSolutions; numberSolutions++; } } // allow solutions double sense = babModel_->solver()->getObjSense();; CoinSort_2(bestValues,bestValues+numberSolutions,which); babModel_->setMoreSpecialOptions(moreOptions&(~16777216)); for (int i=0;igetCutoff()) { babModel_->setBestSolution(bestSolutions[k],numberColumns, -bestValues[i]*sense,true); babModel_->incrementUsed(bestSolutions[k]); } delete [] bestSolutions[k]; } babModel_->setMoreSpecialOptions(moreOptions); if (numberSolutions) sprintf(generalPrint,"Ending major passes - best solution %g",-bestValues[numberSolutions-1]); else sprintf(generalPrint,"Ending major passes - no solution found"); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; delete [] which; delete [] bestValues; delete [] bestSolutions; } if (biLinearProblem) babModel_->setSpecialOptions(babModel_->specialOptions() &(~(512|32768))); babModel_->branchAndBound(statistics); if (truncateColumnssolver()->getNumCols()) { OsiSolverInterface * solverX = babModel_->solver(); int numberColumns=solverX->getNumCols(); int numberRows=solverX->getNumRows(); int numberDelete = numberColumns-truncateColumns; int * delStuff=new int [numberDelete]; for (int i=0;ideleteCols(numberDelete,delStuff); for (int i=0;ideleteRows(numberDelete,delStuff); delete [] delStuff; } //#define CLP_FACTORIZATION_INSTRUMENT #ifdef CLP_FACTORIZATION_INSTRUMENT extern double factorization_instrument(int type); double facTime = factorization_instrument(0); printf("Factorization %g seconds\n", facTime); #endif #endif #ifdef COIN_DEVELOP #ifndef JJF_ONE { int numberColumns = babModel_->getNumCols(); const double * solution = babModel_->bestSolution(); if (solution && numberColumns < 1000) { for (int i = 0; i < numberColumns; i++) { if (solution[i]) printf("SOL %d %.18g\n", i, solution[i]); } } } #endif void printHistory(const char * file/*,CbcModel * model*/); printHistory("branch.log"/*,babModel_*/); #endif returnCode = callBack(babModel_, 4); if (returnCode) { // exit if user wants model_.moveInfo(*babModel_); delete babModel_; babModel_ = NULL; return returnCode; } else { int numberSolutions = babModel_->numberSavedSolutions(); if (numberSolutions>1) { for (int iSolution=numberSolutions-1;iSolution>=0;iSolution--) { model_.setBestSolution(babModel_->savedSolution(iSolution), model_.solver()->getNumCols(), babModel_->savedSolutionObjective(iSolution)); } } } #ifdef CLP_MALLOC_STATISTICS malloc_stats(); malloc_stats2(); #endif checkSOS(babModel_, babModel_->solver()); } else if (type == CBC_PARAM_ACTION_MIPLIB) { int typeOfCuts = babModel_->numberCutGenerators() ? 1 : -1; CbcStrategyDefault strategy(typeOfCuts, babModel_->numberStrong(), babModel_->numberBeforeTrust()); // Set up pre-processing int translate2[] = {9999, 1, 1, 3, 2, 4, 5, 6, 6}; if (preProcess) strategy.setupPreProcessing(translate2[ preProcess ]); babModel_->setStrategy(strategy); #ifdef CBC_THREAD int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].intValue(); babModel_->setNumberThreads(numberThreads % 100); babModel_->setThreadMode(numberThreads / 100); #endif #ifndef CBC_OTHER_SOLVER if (outputFormat == 5) { osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); lpSolver = osiclp->getModelPtr(); lpSolver->setPersistenceFlag(1); } #endif if (testOsiOptions >= 0) { printf("Testing OsiObject options %d\n", testOsiOptions); CbcBranchDefaultDecision decision; OsiChooseStrong choose(babModel_->solver()); choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust()); choose.setNumberStrong(babModel_->numberStrong()); choose.setShadowPriceMode(testOsiOptions); //babModel_->deleteObjects(false); decision.setChooseMethod(choose); babModel_->setBranchingMethod(decision); } model_ = *babModel_; #ifndef CBC_OTHER_SOLVER { osiclp = dynamic_cast< OsiClpSolverInterface*> (model_.solver()); lpSolver = osiclp->getModelPtr(); lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound) if (lpSolver->factorization()->goOslThreshold() > 1000) { // use osl in gomory (may not if CglGomory decides not to) int numberGenerators = model_.numberCutGenerators(); for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = model_.cutGenerator(iGenerator); CglGomory * gomory = dynamic_cast (generator->generator()); if (gomory) gomory->useAlternativeFactorization(); } } } #endif /* LL: this was done in CoinSolve.cpp: main(argc, argv). I have moved it here so that the miplib directory location could be passed to CbcClpUnitTest. */ /* JJF: No need to have 777 flag at all - user says -miplib */ int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, numberParameters_, parameters_)].intValue(); double stuff[11]; stuff[0] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, numberParameters_, parameters_)].doubleValue(); stuff[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, numberParameters_, parameters_)].doubleValue(); stuff[2] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue(); stuff[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, numberParameters_, parameters_)].doubleValue(); stuff[4] = parameters_[whichParam(CBC_PARAM_INT_DENSE, numberParameters_, parameters_)].intValue(); stuff[5] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue(); stuff[6] = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, numberParameters_, parameters_)].intValue(); stuff[7] = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, numberParameters_, parameters_)].intValue(); stuff[8] = bothFlags; stuff[9] = doVector; stuff[10] = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, numberParameters_, parameters_)].intValue(); if ( dominatedCuts) model_.setSpecialOptions(model_.specialOptions() | 64); if (parameters_[whichParam(CBC_PARAM_STR_CPX, numberParameters_, parameters_)].currentOptionAsInteger()) { model_.setSpecialOptions(model_.specialOptions() | 16384); //if (model_.fastNodeDepth()==-1) model_.setFastNodeDepth(-2); // Use Cplex at root } int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue() / 10000; if (hOp2 % 10) { model_.setSpecialOptions(model_.specialOptions() | 16384); if (model_.fastNodeDepth() == -1) model_.setFastNodeDepth(-2); // Use Cplex at root } int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, numberParameters_, parameters_)].intValue(); model_.setMultipleRootTries(multipleRoot); int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, numberParameters_, parameters_)].intValue(); if (specialOptions>=0) model_.setStrongStrategy(specialOptions); if (!pumpChanged) { // Make more lightweight for (int iHeur = 0; iHeur < model_.numberHeuristics(); iHeur++) { CbcHeuristic * heuristic = model_.heuristic(iHeur); CbcHeuristicFPump* pump = dynamic_cast(heuristic); if (pump) { CbcHeuristicFPump heuristic4(model_); heuristic4.setFractionSmall(0.5); heuristic4.setMaximumPasses(5); heuristic4.setFeasibilityPumpOptions(30); heuristic4.setWhen(13); heuristic4.setHeuristicName("feasibility pump"); //CbcHeuristicFPump & pump2 = pump; *pump = heuristic4; } } } int returnCode = CbcClpUnitTest(model_, dirMiplib, extra2, stuff); babModel_ = NULL; return returnCode; } else { abort(); // can't get here //strengthenedModel = babModel_->strengthenedModel(); } currentBranchModel = NULL; #ifndef CBC_OTHER_SOLVER osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); if (debugFile == "createAfterPre" && babModel_->bestSolution()) { lpSolver = osiclp->getModelPtr(); //move best solution (should be there -- but ..) int n = lpSolver->getNumCols(); memcpy(lpSolver->primalColumnSolution(), babModel_->bestSolution(), n*sizeof(double)); saveSolution(osiclp->getModelPtr(), "debug.file"); } #endif statistics_cut_time = 0.0; if (!noPrinting_) { // Print more statistics sprintf(generalPrint, "Cuts at root node changed objective from %g to %g", babModel_->getContinuousObjective(), babModel_->rootObjectiveAfterCuts()); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; numberGenerators = babModel_->numberCutGenerators(); statistics_number_cuts = new int [numberGenerators];; statistics_number_generators = numberGenerators; statistics_name_generators = new const char *[numberGenerators]; char timing[30]; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CbcCutGenerator * generator = babModel_->cutGenerator(iGenerator); statistics_name_generators[iGenerator] = generator->cutGeneratorName(); statistics_number_cuts[iGenerator] = generator->numberCutsInTotal(); sprintf(generalPrint, "%s was tried %d times and created %d cuts of which %d were active after adding rounds of cuts", generator->cutGeneratorName(), generator->numberTimesEntered(), generator->numberCutsInTotal() + generator->numberColumnCuts(), generator->numberCutsActive()); if (generator->timing()) { sprintf(timing, " (%.3f seconds)", generator->timeInCutGenerator()); strcat(generalPrint, timing); statistics_cut_time += generator->timeInCutGenerator(); } CglStored * stored = dynamic_cast(generator->generator()); if (stored && !generator->numberCutsInTotal()) continue; #ifndef CLP_INVESTIGATE CglImplication * implication = dynamic_cast(generator->generator()); if (implication) continue; #endif generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } #ifdef COIN_DEVELOP printf("%d solutions found by heuristics\n", babModel_->getNumberHeuristicSolutions()); // Not really generator but I am feeling lazy for (iGenerator = 0; iGenerator < babModel_->numberHeuristics(); iGenerator++) { CbcHeuristic * heuristic = babModel_->heuristic(iGenerator); if (heuristic->numRuns()) { // Need to bring others inline sprintf(generalPrint, "%s was tried %d times out of %d and created %d solutions\n", heuristic->heuristicName(), heuristic->numRuns(), heuristic->numCouldRun(), heuristic->numberSolutionsFound()); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } #endif } // adjust time to allow for children on some systems time2 = CoinCpuTime() + CoinCpuTimeJustChildren(); totalTime += time2 - time1; // For best solution double * bestSolution = NULL; // Say in integer if (babModel_->status()) { // treat as stopped integerStatus = 3; } else { if (babModel_->isProvenOptimal()) { integerStatus = 0; } else { // infeasible integerStatus = 6; } } if (babModel_->getMinimizationObjValue() < 1.0e50 && type == CBC_PARAM_ACTION_BAB) { // post process int n; if (preProcess) { n = saveSolver->getNumCols(); bestSolution = new double [n]; #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); #else OsiCpxSolverInterface * clpSolver = dynamic_cast< OsiCpxSolverInterface*> (babModel_->solver()); #endif // Save bounds on processed model const int * originalColumns = process.originalColumns(); int numberColumns2 = clpSolver->getNumCols(); double * solution2 = new double[n]; double * lower2 = new double [n]; double * upper2 = new double [n]; for (int i = 0; i < n; i++) { solution2[i] = COIN_DBL_MAX; lower2[i] = COIN_DBL_MAX; upper2[i] = -COIN_DBL_MAX; } const double *columnLower = clpSolver->getColLower() ; const double * columnUpper = clpSolver->getColUpper() ; const double * solution = babModel_->bestSolution(); for (int i = 0; i < numberColumns2; i++) { int jColumn = originalColumns[i]; if (jColumn < n) { solution2[jColumn] = solution[i]; lower2[jColumn] = columnLower[i]; upper2[jColumn] = columnUpper[i]; } } #ifndef CBC_OTHER_SOLVER ClpSimplex * lpSolver = clpSolver->getModelPtr(); lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound) #endif // put back any saved solutions putBackOtherSolutions(babModel_,&model_,&process); process.postProcess(*babModel_->solver()); #ifdef COIN_DEVELOP if (model_.bestSolution() && fabs(model_.getMinimizationObjValue() - babModel_->getMinimizationObjValue()) < 1.0e-8) { const double * b1 = model_.bestSolution(); const double * b2 = saveSolver->getColSolution(); const double * columnLower = saveSolver->getColLower() ; const double * columnUpper = saveSolver->getColUpper() ; for (int i = 0; i < n; i++) { if (fabs(b1[i] - b2[i]) > 1.0e-7) { printf("%d %g %g %g %g\n", i, b1[i], b2[i], columnLower[i], columnUpper[i]); } } } #endif bool tightenB = false; { int n = babModel_->numberObjects(); for (int i = 0; i < n; i++) { const OsiObject * obj = babModel_->object(i); if (!dynamic_cast(obj)) { tightenB = true; break; } } } // Solution now back in saveSolver // Double check bounds columnLower = saveSolver->getColLower() ; columnUpper = saveSolver->getColUpper() ; solution = saveSolver->getColSolution(); int numberChanged = 0; for (int i = 0; i < n; i++) { if (!saveSolver->isInteger(i) && !tightenB) continue; if (lower2[i] != COIN_DBL_MAX) { if (lower2[i] != columnLower[i] || upper2[i] != columnUpper[i]) { if (lower2[i] < columnLower[i] || upper2[i] > columnUpper[i]) { #ifdef COIN_DEVELOP printf("odd bounds tighter"); printf("%d bab bounds %g %g now %g %g\n", i, lower2[i], upper2[i], columnLower[i], columnUpper[i]); #endif } else { #ifdef COIN_DEVELOP printf("%d bab bounds %g %g now %g %g\n", i, lower2[i], upper2[i], columnLower[i], columnUpper[i]); #endif numberChanged++; saveSolver->setColLower(i, lower2[i]); saveSolver->setColUpper(i, upper2[i]); } } } } #ifdef JJF_ZERO // See if sos so we can fix OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver); if (osiclp && osiclp->numberSOS()) { // SOS numberSOS = osiclp->numberSOS(); const CoinSet * setInfo = osiclp->setInfo(); int i; for ( i = 0; i < numberSOS; i++) { int type = setInfo[i].setType(); int n = setInfo[i].numberEntries(); const int * which = setInfo[i].which(); int first = -1; int last = -1; for (int j = 0; j < n; j++) { int iColumn = which[j]; if (fabs(solution[iColumn]) > 1.0e-7) { last = j; if (first < 0) first = j; } } assert (last - first < type); for (int j = 0; j < n; j++) { if (j < first || j > last) { int iColumn = which[j]; saveSolver->setColLower(iColumn, 0.0); saveSolver->setColUpper(iColumn, 0.0); } } } } #endif delete [] solution2; delete [] lower2; delete [] upper2; if (numberChanged) { sprintf(generalPrint, "%d bounds tightened after postprocessing\n", numberChanged); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } saveSolver->resolve(); if (!saveSolver->isProvenOptimal()) { // try all slack CoinWarmStartBasis * basis = dynamic_cast (babModel_->solver()->getEmptyWarmStart()); saveSolver->setWarmStart(basis); delete basis; saveSolver->initialSolve(); #ifdef COIN_DEVELOP saveSolver->writeMps("inf2"); #endif OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver); if (osiclp) osiclp->getModelPtr()->checkUnscaledSolution(); } assert (saveSolver->isProvenOptimal()); #ifndef CBC_OTHER_SOLVER // and original solver originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); assert (n >= originalSolver->getNumCols()); n = originalSolver->getNumCols(); originalSolver->setColLower(saveSolver->getColLower()); originalSolver->setColUpper(saveSolver->getColUpper()); // basis CoinWarmStartBasis * basis = dynamic_cast (babModel_->solver()->getWarmStart()); originalSolver->setBasis(*basis); delete basis; originalSolver->resolve(); if (!originalSolver->isProvenOptimal()) { // try all slack CoinWarmStartBasis * basis = dynamic_cast (babModel_->solver()->getEmptyWarmStart()); originalSolver->setBasis(*basis); delete basis; originalSolver->initialSolve(); OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (originalSolver); if (osiclp) osiclp->getModelPtr()->checkUnscaledSolution(); } assert (originalSolver->isProvenOptimal()); #endif babModel_->assignSolver(saveSolver); memcpy(bestSolution, babModel_->solver()->getColSolution(), n*sizeof(double)); } else { n = babModel_->solver()->getNumCols(); bestSolution = new double [n]; memcpy(bestSolution, babModel_->solver()->getColSolution(), n*sizeof(double)); } if (returnMode == 1&&model_.numberSavedSolutions()<2) { model_.deleteSolutions(); model_.setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue()); } babModel_->deleteSolutions(); babModel_->setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue()); #ifndef CBC_OTHER_SOLVER // and put back in very original solver { ClpSimplex * original = originalSolver->getModelPtr(); double * lower = original->columnLower(); double * upper = original->columnUpper(); double * solution = original->primalColumnSolution(); int n = original->numberColumns(); //assert (!n||n==babModel_->solver()->getNumCols()); for (int i = 0; i < n; i++) { solution[i] = bestSolution[i]; if (originalSolver->isInteger(i)) { lower[i] = solution[i]; upper[i] = solution[i]; } } // basis CoinWarmStartBasis * basis = dynamic_cast (babModel_->solver()->getWarmStart()); originalSolver->setBasis(*basis); delete basis; originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); originalSolver->resolve(); if (!originalSolver->isProvenOptimal()) { // try all slack CoinWarmStartBasis * basis = dynamic_cast (babModel_->solver()->getEmptyWarmStart()); originalSolver->setBasis(*basis); delete basis; originalSolver->initialSolve(); OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (originalSolver); if (osiclp) osiclp->getModelPtr()->checkUnscaledSolution(); #ifdef CLP_INVESTIGATE if (!originalSolver->isProvenOptimal()) { if (saveSolver) { printf("saveSolver and originalSolver matrices saved\n"); saveSolver->writeMps("infA"); } else { printf("originalSolver matrix saved\n"); originalSolver->writeMps("infB"); } } #endif } assert (originalSolver->isProvenOptimal()); } #endif checkSOS(babModel_, babModel_->solver()); } else if (model_.bestSolution() && type == CBC_PARAM_ACTION_BAB && model_.getMinimizationObjValue() < 1.0e50 && preProcess) { sprintf(generalPrint, "Restoring heuristic best solution of %g", model_.getMinimizationObjValue()); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; int n = saveSolver->getNumCols(); bestSolution = new double [n]; // Put solution now back in saveSolver saveSolver->setColSolution(model_.bestSolution()); babModel_->assignSolver(saveSolver); saveSolver=NULL; babModel_->setMinimizationObjValue(model_.getMinimizationObjValue()); memcpy(bestSolution, babModel_->solver()->getColSolution(), n*sizeof(double)); #ifndef CBC_OTHER_SOLVER // and put back in very original solver { ClpSimplex * original = originalSolver->getModelPtr(); double * lower = original->columnLower(); double * upper = original->columnUpper(); double * solution = original->primalColumnSolution(); int n = original->numberColumns(); //assert (!n||n==babModel_->solver()->getNumCols()); for (int i = 0; i < n; i++) { solution[i] = bestSolution[i]; if (originalSolver->isInteger(i)) { lower[i] = solution[i]; upper[i] = solution[i]; } } // basis CoinWarmStartBasis * basis = dynamic_cast (babModel_->solver()->getWarmStart()); originalSolver->setBasis(*basis); delete basis; } #endif } #ifndef CBC_OTHER_SOLVER //if (type==CBC_PARAM_ACTION_STRENGTHEN&&strengthenedModel) //clpSolver = dynamic_cast< OsiClpSolverInterface*> (strengthenedModel); #ifdef COIN_HAS_ASL else if (statusUserFunction_[0]) clpSolver = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); #endif lpSolver = clpSolver->getModelPtr(); if (numberChanged) { for (int i = 0; i < numberChanged; i++) { int iColumn = changed[i]; clpSolver->setContinuous(iColumn); } delete [] changed; } #endif if (type == CBC_PARAM_ACTION_BAB) { #ifndef CBC_OTHER_SOLVER //move best solution (should be there -- but ..) int n = lpSolver->getNumCols(); if (bestSolution) { memcpy(lpSolver->primalColumnSolution(), bestSolution, n*sizeof(double)); // now see what that does to row solution int numberRows = lpSolver->numberRows(); double * rowSolution = lpSolver->primalRowSolution(); memset (rowSolution, 0, numberRows*sizeof(double)); lpSolver->clpMatrix()->times(1.0, bestSolution, rowSolution); lpSolver->setObjectiveValue(babModel_->getObjValue()); } if (debugFile == "create" && bestSolution) { saveSolution(lpSolver, "debug.file"); } #else if (bestSolution) { model_.solver()->setColSolution(bestSolution); } #endif delete saveSolver; delete [] bestSolution; std::string statusName[] = {"", "Stopped on ", "Run abandoned", "", "", "User ctrl-c"}; std::string minor[] = {"Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "Problem proven infeasible"}; int iStat = babModel_->status(); int iStat2 = babModel_->secondaryStatus(); if (!iStat && !iStat2 && !bestSolution) iStat2 = 8; if (!iStat && iStat2==1 && bestSolution) iStat2 = 0; // solution and search completed statistics_seconds = time2 - time1; statistics_sys_seconds = CoinSysTime(); statistics_elapsed_seconds = CoinWallclockTime(); statistics_obj = babModel_->getObjValue(); statistics_continuous = babModel_->getContinuousObjective(); statistics_tighter = babModel_->rootObjectiveAfterCuts(); statistics_nodes = babModel_->getNodeCount(); statistics_iterations = babModel_->getIterationCount();; statistics_result = statusName[iStat];; if (!noPrinting_) { sprintf(generalPrint, "\nResult - %s%s\n", statusName[iStat].c_str(), minor[iStat2].c_str()); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; if (babModel_->bestSolution()){ sprintf(generalPrint, "Objective value: %.8f\n", babModel_->getObjValue()); }else{ sprintf(generalPrint, "No feasible solution found\n"); } if (iStat2 >= 2 && iStat2 <=6){ sprintf(generalPrint + strlen(generalPrint), "Lower bound: %.3f\n", babModel_->getBestPossibleObjValue()); if (babModel_->bestSolution()){ sprintf(generalPrint + strlen(generalPrint), "Gap: %.2f\n", (babModel_->getObjValue()-babModel_->getBestPossibleObjValue())/babModel_->getBestPossibleObjValue()); } } sprintf(generalPrint + strlen(generalPrint), "Enumerated nodes: %d\n", babModel_->getNodeCount()); sprintf(generalPrint + strlen(generalPrint), "Total iterations: %d\n", babModel_->getIterationCount()); #if CBC_QUIET == 0 sprintf(generalPrint + strlen(generalPrint), "Time (CPU seconds): %.2f\n", CoinCpuTime() - time1); sprintf(generalPrint + strlen(generalPrint), "Time (Wallclock seconds): %.2f\n", CoinGetTimeOfDay() - time1Elapsed); #endif generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } int returnCode = callBack(babModel_, 5); if (returnCode) { // exit if user wants model_.moveInfo(*babModel_); delete babModel_; babModel_ = NULL; return returnCode; } #ifdef COIN_HAS_ASL if (statusUserFunction_[0]) { clpSolver = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); lpSolver = clpSolver->getModelPtr(); double value = babModel_->getObjValue()*lpSolver->getObjSense(); char buf[300]; int pos=0; if (iStat==0) { if (babModel_->getObjValue()<1.0e40) { pos += sprintf(buf+pos,"optimal," ); } else { // infeasible iStat=1; pos += sprintf(buf+pos,"infeasible,"); } } else if (iStat==1) { if (iStat2!=6) iStat=3; else iStat=4; pos += sprintf(buf+pos,"stopped on %s,",minor[iStat2].c_str()); } else if (iStat==2) { iStat = 7; pos += sprintf(buf+pos,"stopped on difficulties,"); } else if (iStat==5) { iStat = 3; pos += sprintf(buf+pos,"stopped on ctrl-c,"); } else { pos += sprintf(buf+pos,"status unknown,"); iStat=6; } info.problemStatus=iStat; info.objValue = value; if (babModel_->getObjValue()<1.0e40) { int precision = ampl_obj_prec(); if (precision>0) pos += sprintf(buf+pos," objective %.*g",precision, value); else pos += sprintf(buf+pos," objective %g",value); } sprintf(buf+pos,"\n%d nodes, %d iterations, %g seconds", babModel_->getNodeCount(), babModel_->getIterationCount(), totalTime); if (bestSolution) { free(info.primalSolution); if (!numberKnapsack) { info.primalSolution = (double *) malloc(n*sizeof(double)); CoinCopyN(lpSolver->primalColumnSolution(),n,info.primalSolution); int numberRows = lpSolver->numberRows(); free(info.dualSolution); info.dualSolution = (double *) malloc(numberRows*sizeof(double)); CoinCopyN(lpSolver->dualRowSolution(),numberRows,info.dualSolution); } else { // expanded knapsack info.dualSolution=NULL; int numberColumns = saveCoinModel.numberColumns(); info.primalSolution = (double *) malloc(numberColumns*sizeof(double)); // Fills in original solution (coinModel length) afterKnapsack(saveTightenedModel, whichColumn, knapsackStart, knapsackRow, numberKnapsack, lpSolver->primalColumnSolution(), info.primalSolution,1); } } else { info.primalSolution=NULL; info.dualSolution=NULL; } // put buffer into info strcpy(info.buffer,buf); } #endif } else { std::cout << "Model strengthened - now has " << clpSolver->getNumRows() << " rows" << std::endl; } time1 = time2; #ifdef COIN_HAS_ASL if (statusUserFunction_[0]) { // keep if going to be destroyed OsiSolverInterface * solver = babModel_->solver(); OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); ClpSimplex * lpSolver2 = clpSolver->getModelPtr(); if (lpSolver == lpSolver2) babModel_->setModelOwnsSolver(false); } #endif //delete babModel_; //babModel_=NULL; } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl ; #endif } break ; case CLP_PARAM_ACTION_IMPORT: { #ifdef COIN_HAS_ASL if (!statusUserFunction_[0]) { #endif free(priorities); priorities = NULL; free(branchDirection); branchDirection = NULL; free(pseudoDown); pseudoDown = NULL; free(pseudoUp); pseudoUp = NULL; free(solutionIn); solutionIn = NULL; free(prioritiesIn); prioritiesIn = NULL; free(sosStart); sosStart = NULL; free(sosIndices); sosIndices = NULL; free(sosType); sosType = NULL; free(sosReference); sosReference = NULL; free(cut); cut = NULL; free(sosPriority); sosPriority = NULL; #ifdef COIN_HAS_ASL } #endif //delete babModel_; //babModel_=NULL; // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; bool canOpen = false; // See if gmpl file int gmpl = 0; std::string gmplData; if (field == "-" || field == "stdin") { // stdin canOpen = true; fileName = "-"; } else if (field == "stdin_lp") { // stdin canOpen = true; fileName = "-"; gmpl = -1; //.lp format } else { // See if .lp { const char * c_name = field.c_str(); size_t length = strlen(c_name); if (length > 3 && !strncmp(c_name + length - 3, ".lp", 3)) gmpl = -1; // .lp } bool absolutePath; if (dirsep == '/') { // non Windows (or cygwin) absolutePath = (field[0] == '/'); } else { //Windows (non cycgwin) absolutePath = (field[0] == '\\'); // but allow for : if (strchr(field.c_str(), ':')) absolutePath = true; } if (absolutePath) { fileName = field; size_t length = field.size(); size_t percent = field.find('%'); if (percent < length && percent > 0) { gmpl = 1; fileName = field.substr(0, percent); gmplData = field.substr(percent + 1); if (percent < length - 1) gmpl = 2; // two files printf("GMPL model file %s and data file %s\n", fileName.c_str(), gmplData.c_str()); } } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; // See if gmpl (model & data) - or even lp file size_t length = field.size(); size_t percent = field.find('%'); if (percent0) { gmpl = 1; fileName = directory + field.substr(0, percent); gmplData = directory + field.substr(percent + 1); if (percent < length - 1) gmpl = 2; // two files printf("GMPL model file %s and data file %s\n", fileName.c_str(), gmplData.c_str()); } } std::string name = fileName; if (fileCoinReadable(name)) { // can open - lets go for it canOpen = true; if (gmpl == 2) { FILE *fp; fp = fopen(gmplData.c_str(), "r"); if (fp) { fclose(fp); } else { canOpen = false; std::cout << "Unable to open file " << gmplData << std::endl; } } } else { std::cout << "Unable to open file " << fileName << std::endl; } } if (canOpen) { int status; #ifndef CBC_OTHER_SOLVER ClpSimplex * lpSolver = clpSolver->getModelPtr(); if (!gmpl) { status = clpSolver->readMps(fileName.c_str(), keepImportNames != 0, allowImportErrors != 0); } else if (gmpl > 0) { status = lpSolver->readGMPL(fileName.c_str(), (gmpl == 2) ? gmplData.c_str() : NULL, keepImportNames != 0); } else { #ifdef KILL_ZERO_READLP status = lpSolver->readLp(fileName.c_str(), lpSolver->getSmallElementValue()); #else status = lpSolver->readLp(fileName.c_str(), 1.0e-12); #endif } #else status = clpSolver->readMps(fileName.c_str(), ""); #endif if (!status || (status > 0 && allowImportErrors)) { #ifndef CBC_OTHER_SOLVER if (keepImportNames) { lengthName = lpSolver->lengthNames(); rowNames = *(lpSolver->rowNames()); columnNames = *(lpSolver->columnNames()); } else { lengthName = 0; } goodModel = true; // sets to all slack (not necessary?) lpSolver->createStatus(); // make sure integer int numberColumns = lpSolver->numberColumns(); for (int i = 0; i < numberColumns; i++) { if (lpSolver->isInteger(i)) clpSolver->setInteger(i); } #else lengthName = 0; goodModel = true; #endif time2 = CoinCpuTime(); totalTime += time2 - time1; time1 = time2; // Go to canned file if just input file if (CbcOrClpRead_mode == 2 && argc == 2) { // only if ends .mps char * find = const_cast(strstr(fileName.c_str(), ".mps")); if (find && find[4] == '\0') { find[1] = 'p'; find[2] = 'a'; find[3] = 'r'; FILE *fp = fopen(fileName.c_str(), "r"); if (fp) { CbcOrClpReadCommand = fp; // Read from that file CbcOrClpRead_mode = -1; } } } } else { // errors std::cout << "There were " << status << " errors on input" << std::endl; } } } break; case CLP_PARAM_ACTION_MODELIN: #ifndef CBC_OTHER_SOLVER #ifdef COIN_HAS_LINK { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; bool canOpen = false; if (field == "-") { // stdin canOpen = true; fileName = "-"; } else { bool absolutePath; if (dirsep == '/') { // non Windows (or cygwin) absolutePath = (field[0] == '/'); } else { //Windows (non cycgwin) absolutePath = (field[0] == '\\'); // but allow for : if (strchr(field.c_str(), ':')) absolutePath = true; } if (absolutePath) { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } FILE *fp = fopen(fileName.c_str(), "r"); if (fp) { // can open - lets go for it fclose(fp); canOpen = true; } else { std::cout << "Unable to open file " << fileName << std::endl; } } if (canOpen) { CoinModel coinModel(fileName.c_str(), 2); // load from coin model OsiSolverLink solver1; OsiSolverInterface * solver2 = solver1.clone(); model_.assignSolver(solver2, false); OsiSolverLink * si = dynamic_cast(model_.solver()) ; assert (si != NULL); si->setDefaultMeshSize(0.001); // need some relative granularity si->setDefaultBound(100.0); double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue(); if (dextra3) si->setDefaultMeshSize(dextra3); si->setDefaultBound(100.0); si->setIntegerPriority(1000); si->setBiLinearPriority(10000); CoinModel * model2 = &coinModel; si->load(*model2); // redo solver = model_.solver(); clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); lpSolver = clpSolver->getModelPtr(); clpSolver->messageHandler()->setLogLevel(0) ; testOsiParameters = 0; complicatedInteger = 2; } } #endif #endif break; case CLP_PARAM_ACTION_EXPORT: if (goodModel) { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; bool canOpen = false; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } FILE *fp = fopen(fileName.c_str(), "w"); if (fp) { // can open - lets go for it fclose(fp); canOpen = true; } else { std::cout << "Unable to open file " << fileName << std::endl; } if (canOpen) { // If presolve on then save presolved bool deleteModel2 = false; ClpSimplex * model2 = lpSolver; if (dualize && dualize < 3) { model2 = static_cast (model2)->dualOfModel(); sprintf(generalPrint, "Dual of model has %d rows and %d columns", model2->numberRows(), model2->numberColumns()); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; model2->setOptimizationDirection(1.0); } #ifndef CBC_OTHER_SOLVER #ifdef COIN_HAS_ASL if (info.numberSos && doSOS && statusUserFunction_[0]) { // SOS numberSOS = info.numberSos; sosStart = info.sosStart; sosIndices = info.sosIndices; sosReference = info.sosReference; preSolve = false; clpSolver->setSOSData(numberSOS, info.sosType, sosStart, sosIndices, sosReference); } #endif #endif if (preSolve) { ClpPresolve pinfo; int presolveOptions2 = presolveOptions&~0x40000000; if ((presolveOptions2&0xffff) != 0) pinfo.setPresolveActions(presolveOptions2); if ((printOptions&1) != 0) pinfo.statistics(); double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].doubleValue(); model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, true, preSolve); if (model2) { printf("Saving presolved model on %s\n", fileName.c_str()); deleteModel2 = true; } else { printf("Presolved model looks infeasible - saving original on %s\n", fileName.c_str()); deleteModel2 = false; model2 = lpSolver; } model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1)&1)); if (deleteModel2) delete model2; } else { printf("Saving model on %s\n", fileName.c_str()); if (numberSOS) { // Convert names int iRow; int numberRows = model2->numberRows(); int iColumn; int numberColumns = model2->numberColumns(); char ** rowNames = NULL; char ** columnNames = NULL; if (model2->lengthNames()) { rowNames = new char * [numberRows]; for (iRow = 0; iRow < numberRows; iRow++) { rowNames[iRow] = CoinStrdup(model2->rowName(iRow).c_str()); } columnNames = new char * [numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) { columnNames[iColumn] = CoinStrdup(model2->columnName(iColumn).c_str()); } } clpSolver->writeMpsNative(fileName.c_str(), const_cast (rowNames), const_cast (columnNames), (outputFormat - 1) / 2, 1 + ((outputFormat - 1)&1)); if (rowNames) { for (iRow = 0; iRow < numberRows; iRow++) { free(rowNames[iRow]); } delete [] rowNames; for (iColumn = 0; iColumn < numberColumns; iColumn++) { free(columnNames[iColumn]); } delete [] columnNames; } } else { #ifdef COIN_HAS_LINK OsiSolverLink * linkSolver = dynamic_cast< OsiSolverLink*> (clpSolver); if (!linkSolver || !linkSolver->quadraticModel()) model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1)&1)); else linkSolver->quadraticModel()->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1)&1)); #endif } } time2 = CoinCpuTime(); totalTime += time2 - time1; time1 = time2; } } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_BASISIN: if (goodModel) { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; bool canOpen = false; if (field == "-") { // stdin canOpen = true; fileName = "-"; } else { if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } FILE *fp = fopen(fileName.c_str(), "r"); if (fp) { // can open - lets go for it fclose(fp); canOpen = true; } else { std::cout << "Unable to open file " << fileName << std::endl; } } if (canOpen) { #ifndef CBC_OTHER_SOLVER int values = lpSolver->readBasis(fileName.c_str()); if (values == 0) basisHasValues = -1; else basisHasValues = 1; assert (lpSolver == clpSolver->getModelPtr()); clpSolver->setWarmStart(NULL); #endif } } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CBC_PARAM_ACTION_PRIORITYIN: if (goodModel) { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } FILE *fp = fopen(fileName.c_str(), "r"); if (fp) { // can open - lets go for it std::string headings[] = {"name", "number", "direction", "priority", "up", "down", "solution", "priin" }; int got[] = { -1, -1, -1, -1, -1, -1, -1, -1}; int order[8]; assert(sizeof(got) == sizeof(order)); int nAcross = 0; char line[1000]; int numberColumns = lpSolver->numberColumns(); if (!fgets(line, 1000, fp)) { std::cout << "Odd file " << fileName << std::endl; } else { char * pos = line; char * put = line; while (*pos >= ' ' && *pos != '\n') { if (*pos != ' ' && *pos != '\t') { *put = static_cast(tolower(*pos)); put++; } pos++; } *put = '\0'; pos = line; int i; bool good = true; while (pos) { char * comma = strchr(pos, ','); if (comma) *comma = '\0'; for (i = 0; i < static_cast (sizeof(got) / sizeof(int)); i++) { if (headings[i] == pos) { if (got[i] < 0) { order[nAcross] = i; got[i] = nAcross++; } else { // duplicate good = false; } break; } } if (i == static_cast (sizeof(got) / sizeof(int))) good = false; if (comma) { *comma = ','; pos = comma + 1; } else { break; } } if (got[0] < 0 && got[1] < 0) good = false; if (got[0] >= 0 && got[1] >= 0) good = false; if (got[0] >= 0 && !lpSolver->lengthNames()) good = false; int numberFields = 99; if (good && (strstr(fileName.c_str(), ".mst") || strstr(fileName.c_str(), ".MST") || strstr(fileName.c_str(), ".csv"))) { numberFields = 0; for (i = 2; i < static_cast (sizeof(got) / sizeof(int)); i++) { if (got[i] >= 0) numberFields++; } if (!numberFields) { // Like Cplex format order[nAcross] = 6; got[6] = nAcross++; } } if (good) { char ** columnNames = new char * [numberColumns]; pseudoDown = reinterpret_cast (malloc(numberColumns * sizeof(double))); pseudoUp = reinterpret_cast (malloc(numberColumns * sizeof(double))); branchDirection = reinterpret_cast (malloc(numberColumns * sizeof(int))); priorities = reinterpret_cast (malloc(numberColumns * sizeof(int))); free(solutionIn); solutionIn = NULL; free(prioritiesIn); prioritiesIn = NULL; int iColumn; if (got[6] >= 0) { solutionIn = reinterpret_cast (malloc(numberColumns * sizeof(double))); for (iColumn = 0; iColumn < numberColumns; iColumn++) solutionIn[iColumn] = -COIN_DBL_MAX; } if (got[7] >= 0 || !numberFields) { prioritiesIn = reinterpret_cast (malloc(numberColumns * sizeof(int))); for (iColumn = 0; iColumn < numberColumns; iColumn++) prioritiesIn[iColumn] = 10000; } for (iColumn = 0; iColumn < numberColumns; iColumn++) { columnNames[iColumn] = CoinStrdup(lpSolver->columnName(iColumn).c_str()); pseudoDown[iColumn] = 0.0; pseudoUp[iColumn] = 0.0; branchDirection[iColumn] = 0; priorities[iColumn] = 0; } int nBadPseudo = 0; int nBadDir = 0; int nBadPri = 0; int nBadName = 0; int nBadLine = 0; int nLine = 0; while (fgets(line, 1000, fp)) { if (!strncmp(line, "ENDATA", 6)) break; nLine++; iColumn = -1; double up = 0.0; double down = 0.0; int pri = 0; int dir = 0; double solValue = COIN_DBL_MAX; int priValue = 1000000; char * pos = line; char * put = line; if (!numberFields) { // put in , for (i = 4; i < 100; i++) { if (line[i] == ' ' || line[i] == '\t') { line[i] = ','; break; } } } while (*pos >= ' ' && *pos != '\n') { if (*pos != ' ' && *pos != '\t') { *put = *pos; put++; } pos++; } *put = '\0'; pos = line; for (int i = 0; i < nAcross; i++) { char * comma = strchr(pos, ','); if (comma) { *comma = '\0'; } else if (i < nAcross - 1) { nBadLine++; break; } switch (order[i]) { // name case 0: for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (!strcmp(columnNames[iColumn], pos)) break; } if (iColumn == numberColumns) iColumn = -1; break; // number case 1: iColumn = atoi(pos); if (iColumn < 0 || iColumn >= numberColumns) iColumn = -1; break; // direction case 2: if (*pos == 'D') dir = -1; else if (*pos == 'U') dir = 1; else if (*pos == 'N') dir = 0; else if (*pos == '1' && *(pos + 1) == '\0') dir = 1; else if (*pos == '0' && *(pos + 1) == '\0') dir = 0; else if (*pos == '1' && *(pos + 1) == '1' && *(pos + 2) == '\0') dir = -1; else dir = -2; // bad break; // priority case 3: pri = atoi(pos); break; // up case 4: up = atof(pos); break; // down case 5: down = atof(pos); break; // sol value case 6: solValue = atof(pos); break; // priority in value case 7: priValue = atoi(pos); break; } if (comma) { *comma = ','; pos = comma + 1; } } if (iColumn >= 0) { if (down < 0.0) { nBadPseudo++; down = 0.0; } if (up < 0.0) { nBadPseudo++; up = 0.0; } if (!up) up = down; if (!down) down = up; if (dir < -1 || dir > 1) { nBadDir++; dir = 0; } if (pri < 0) { nBadPri++; pri = 0; } pseudoDown[iColumn] = down; pseudoUp[iColumn] = up; branchDirection[iColumn] = dir; priorities[iColumn] = pri; if (solValue != COIN_DBL_MAX) { assert (solutionIn); solutionIn[iColumn] = solValue; } if (priValue != 1000000) { assert (prioritiesIn); prioritiesIn[iColumn] = priValue; } } else { nBadName++; } } if (!noPrinting_) { printf("%d fields and %d records", nAcross, nLine); if (nBadPseudo) printf(" %d bad pseudo costs", nBadPseudo); if (nBadDir) printf(" %d bad directions", nBadDir); if (nBadPri) printf(" %d bad priorities", nBadPri); if (nBadName) printf(" ** %d records did not match on name/sequence", nBadName); printf("\n"); } for (iColumn = 0; iColumn < numberColumns; iColumn++) { free(columnNames[iColumn]); } delete [] columnNames; } else { std::cout << "Duplicate or unknown keyword - or name/number fields wrong" << line << std::endl; } } fclose(fp); } else { std::cout << "Unable to open file " << fileName << std::endl; } } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CBC_PARAM_ACTION_MIPSTART: if (goodModel) { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } sprintf(generalPrint,"will open mipstart file %s.",fileName.c_str() ); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; double msObj; readMIPStart( &model_, fileName.c_str(), mipStart, msObj ); // copy to before preprocess if has .before. if (strstr(fileName.c_str(),".before.")) { mipStartBefore = mipStart; sprintf(generalPrint,"file %s will be used before preprocessing.",fileName.c_str() ); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_DEBUG: if (goodModel) { delete [] debugValues; debugValues = NULL; // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); debugFile = field; if (debugFile == "create" || debugFile == "createAfterPre") { printf("Will create a debug file so this run should be a good one\n"); break; } } std::string fileName; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } FILE *fp = fopen(fileName.c_str(), "rb"); if (fp) { // can open - lets go for it int numRows; double obj; size_t nRead; nRead = fread(&numRows, sizeof(int), 1, fp); if (nRead != 1) throw("Error in fread"); nRead = fread(&numberDebugValues, sizeof(int), 1, fp); if (nRead != 1) throw("Error in fread"); nRead = fread(&obj, sizeof(double), 1, fp); if (nRead != 1) throw("Error in fread"); debugValues = new double[numberDebugValues+numRows]; nRead = fread(debugValues, sizeof(double), numRows, fp); if (nRead != static_cast(numRows)) throw("Error in fread"); nRead = fread(debugValues, sizeof(double), numRows, fp); if (nRead != static_cast(numRows)) throw("Error in fread"); nRead = fread(debugValues, sizeof(double), numberDebugValues, fp); if (nRead != static_cast(numberDebugValues)) throw("Error in fread"); printf("%d doubles read into debugValues\n", numberDebugValues); #ifdef CGL_WRITEMPS debugSolution = debugValues; debugNumberColumns = numberDebugValues; #endif if (numberDebugValues < 200) { for (int i = 0; i < numberDebugValues; i++) { if (clpSolver->isInteger(i) && debugValues[i]) printf("%d %g\n", i, debugValues[i]); } } fclose(fp); } else { std::cout << "Unable to open file " << fileName << std::endl; } } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_PRINTMASK: // get next field { std::string name = CoinReadGetString(argc, argv); if (name != "EOL") { parameters_[iParam].setStringValue(name); printMask = name; } else { parameters_[iParam].printString(); } } break; case CLP_PARAM_ACTION_BASISOUT: if (goodModel) { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; bool canOpen = false; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } FILE *fp = fopen(fileName.c_str(), "w"); if (fp) { // can open - lets go for it fclose(fp); canOpen = true; } else { std::cout << "Unable to open file " << fileName << std::endl; } if (canOpen) { ClpSimplex * model2 = lpSolver; model2->writeBasis(fileName.c_str(), outputFormat > 1, outputFormat - 2); time2 = CoinCpuTime(); totalTime += time2 - time1; time1 = time2; } } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_SAVE: { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; bool canOpen = false; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } FILE *fp = fopen(fileName.c_str(), "wb"); if (fp) { // can open - lets go for it fclose(fp); canOpen = true; } else { std::cout << "Unable to open file " << fileName << std::endl; } if (canOpen) { int status; // If presolve on then save presolved bool deleteModel2 = false; ClpSimplex * model2 = lpSolver; if (preSolve) { ClpPresolve pinfo; double presolveTolerance = parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].doubleValue(); model2 = pinfo.presolvedModel(*lpSolver, presolveTolerance, false, preSolve); if (model2) { printf("Saving presolved model on %s\n", fileName.c_str()); deleteModel2 = true; } else { printf("Presolved model looks infeasible - saving original on %s\n", fileName.c_str()); deleteModel2 = false; model2 = lpSolver; } } else { printf("Saving model on %s\n", fileName.c_str()); } status = model2->saveModel(fileName.c_str()); if (deleteModel2) delete model2; if (!status) { goodModel = true; time2 = CoinCpuTime(); totalTime += time2 - time1; time1 = time2; } else { // errors std::cout << "There were errors on output" << std::endl; } } } break; case CLP_PARAM_ACTION_RESTORE: { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; bool canOpen = false; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } FILE *fp = fopen(fileName.c_str(), "rb"); if (fp) { // can open - lets go for it fclose(fp); canOpen = true; } else { std::cout << "Unable to open file " << fileName << std::endl; } if (canOpen) { int status = lpSolver->restoreModel(fileName.c_str()); if (!status) { goodModel = true; time2 = CoinCpuTime(); totalTime += time2 - time1; time1 = time2; } else { // errors std::cout << "There were errors on input" << std::endl; } } } break; case CLP_PARAM_ACTION_MAXIMIZE: lpSolver->setOptimizationDirection(-1); break; case CLP_PARAM_ACTION_MINIMIZE: lpSolver->setOptimizationDirection(1); break; case CLP_PARAM_ACTION_ALLSLACK: lpSolver->allSlackBasis(true); break; case CLP_PARAM_ACTION_REVERSE: if (goodModel) { int iColumn; int numberColumns = lpSolver->numberColumns(); double * dualColumnSolution = lpSolver->dualColumnSolution(); ClpObjective * obj = lpSolver->objectiveAsObject(); assert(dynamic_cast (obj)); double offset; double * objective = obj->gradient(NULL, NULL, offset, true); for (iColumn = 0; iColumn < numberColumns; iColumn++) { dualColumnSolution[iColumn] = dualColumnSolution[iColumn]; objective[iColumn] = -objective[iColumn]; } int iRow; int numberRows = lpSolver->numberRows(); double * dualRowSolution = lpSolver->dualRowSolution(); for (iRow = 0; iRow < numberRows; iRow++) dualRowSolution[iRow] = dualRowSolution[iRow]; } break; case CLP_PARAM_ACTION_DIRECTORY: { std::string name = CoinReadGetString(argc, argv); if (name != "EOL") { size_t length = name.length(); if (length > 0 && name[length-1] == dirsep) { directory = name; } else { directory = name + dirsep; } parameters_[iParam].setStringValue(directory); } else { parameters_[iParam].printString(); } } break; case CLP_PARAM_ACTION_DIRSAMPLE: { std::string name = CoinReadGetString(argc, argv); if (name != "EOL") { size_t length = name.length(); if (length > 0 && name[length-1] == dirsep) { dirSample = name; } else { dirSample = name + dirsep; } parameters_[iParam].setStringValue(dirSample); } else { parameters_[iParam].printString(); } } break; case CLP_PARAM_ACTION_DIRNETLIB: { std::string name = CoinReadGetString(argc, argv); if (name != "EOL") { size_t length = name.length(); if (length > 0 && name[length-1] == dirsep) { dirNetlib = name; } else { dirNetlib = name + dirsep; } parameters_[iParam].setStringValue(dirNetlib); } else { parameters_[iParam].printString(); } } break; case CBC_PARAM_ACTION_DIRMIPLIB: { std::string name = CoinReadGetString(argc, argv); if (name != "EOL") { size_t length = name.length(); if (length > 0 && name[length-1] == dirsep) { dirMiplib = name; } else { dirMiplib = name + dirsep; } parameters_[iParam].setStringValue(dirMiplib); } else { parameters_[iParam].printString(); } } break; case CLP_PARAM_ACTION_STDIN: CbcOrClpRead_mode = -1; break; case CLP_PARAM_ACTION_NETLIB_DUAL: case CLP_PARAM_ACTION_NETLIB_EITHER: case CLP_PARAM_ACTION_NETLIB_BARRIER: case CLP_PARAM_ACTION_NETLIB_PRIMAL: case CLP_PARAM_ACTION_NETLIB_TUNE: { printf("unit test is now only from clp - does same thing\n"); //return(22); } break; case CLP_PARAM_ACTION_UNITTEST: { CbcClpUnitTest(model_, dirSample, -2, NULL); } break; case CLP_PARAM_ACTION_FAKEBOUND: if (goodModel) { // get bound double value = CoinReadGetDoubleField(argc, argv, &valid); if (!valid) { std::cout << "Setting " << parameters_[iParam].name() << " to DEBUG " << value << std::endl; int iRow; int numberRows = lpSolver->numberRows(); double * rowLower = lpSolver->rowLower(); double * rowUpper = lpSolver->rowUpper(); for (iRow = 0; iRow < numberRows; iRow++) { // leave free ones for now if (rowLower[iRow] > -1.0e20 || rowUpper[iRow] < 1.0e20) { rowLower[iRow] = CoinMax(rowLower[iRow], -value); rowUpper[iRow] = CoinMin(rowUpper[iRow], value); } } int iColumn; int numberColumns = lpSolver->numberColumns(); double * columnLower = lpSolver->columnLower(); double * columnUpper = lpSolver->columnUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { // leave free ones for now if (columnLower[iColumn] > -1.0e20 || columnUpper[iColumn] < 1.0e20) { columnLower[iColumn] = CoinMax(columnLower[iColumn], -value); columnUpper[iColumn] = CoinMin(columnUpper[iColumn], value); } } } else if (valid == 1) { abort(); } else { std::cout << "enter value for " << parameters_[iParam].name() << std::endl; } } break; case CLP_PARAM_ACTION_REALLY_SCALE: if (goodModel) { ClpSimplex newModel(*lpSolver, lpSolver->scalingFlag()); printf("model really really scaled\n"); *lpSolver = newModel; } break; case CLP_PARAM_ACTION_USERCLP: #ifdef USER_HAS_FAKE_CLP // Replace the sample code by whatever you want if (goodModel) { // Way of using an existing piece of code OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver()); ClpSimplex * lpSolver = clpSolver->getModelPtr(); // set time from integer model double timeToGo = model_.getMaximumSeconds(); lpSolver->setMaximumSeconds(timeToGo); int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue(); fakeMain2(*lpSolver, *clpSolver, extra1); lpSolver = clpSolver->getModelPtr(); #ifdef COIN_HAS_ASL // My actual usage has objective only in clpSolver //double objectiveValue=clpSolver->getObjValue(); //int iStat = lpSolver->status(); //int iStat2 = lpSolver->secondaryStatus(); #endif } #endif break; case CBC_PARAM_ACTION_USERCBC: #ifdef USER_HAS_FAKE_CBC // Replace the sample code by whatever you want if (goodModel) { // Way of using an existing piece of code OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver()); ClpSimplex * lpSolver = clpSolver->getModelPtr(); // set time from integer model double timeToGo = model_.getMaximumSeconds(); lpSolver->setMaximumSeconds(timeToGo); fakeMain(*lpSolver, *clpSolver, model); #ifdef COIN_HAS_ASL // My actual usage has objective only in clpSolver double objectiveValue = clpSolver->getObjValue(); int iStat = lpSolver->status(); int iStat2 = lpSolver->secondaryStatus(); #endif // make sure solution back in correct place clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver()); lpSolver = clpSolver->getModelPtr(); #ifdef COIN_HAS_ASL if (statusUserFunction_[0]) { int n = clpSolver->getNumCols(); double value = objectiveValue * lpSolver->getObjSense(); char buf[300]; int pos = 0; std::string minor[] = {"", "", "gap", "nodes", "time", "", "solutions", "user ctrl-c"}; if (iStat == 0) { if (objectiveValue < 1.0e40) { pos += sprintf(buf + pos, "optimal," ); } else { // infeasible iStat = 1; pos += sprintf(buf + pos, "infeasible,"); } } else if (iStat == 1) { if (iStat2 != 6) iStat = 3; else iStat = 4; pos += sprintf(buf + pos, "stopped on %s,", minor[iStat2].c_str()); } else if (iStat == 2) { iStat = 7; pos += sprintf(buf + pos, "stopped on difficulties,"); } else if (iStat == 5) { iStat = 3; pos += sprintf(buf + pos, "stopped on ctrl-c,"); } else if (iStat == 6) { // bab infeasible pos += sprintf(buf + pos, "integer infeasible,"); iStat = 1; } else { pos += sprintf(buf + pos, "status unknown,"); iStat = 6; } info.problemStatus = iStat; info.objValue = value; if (objectiveValue < 1.0e40) pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(), value); sprintf(buf + pos, "\n%d nodes, %d iterations", model_.getNodeCount(), model_.getIterationCount()); if (objectiveValue < 1.0e50) { free(info.primalSolution); info.primalSolution = (double *) malloc(n * sizeof(double)); CoinCopyN(lpSolver->primalColumnSolution(), n, info.primalSolution); int numberRows = lpSolver->numberRows(); free(info.dualSolution); info.dualSolution = (double *) malloc(numberRows * sizeof(double)); CoinCopyN(lpSolver->dualRowSolution(), numberRows, info.dualSolution); } else { info.primalSolution = NULL; info.dualSolution = NULL; } // put buffer into info strcpy(info.buffer, buf); } #endif } #endif break; case CLP_PARAM_ACTION_HELP: std::cout << "Cbc version " << CBC_VERSION << ", build " << __DATE__ << std::endl; std::cout << "Non default values:-" << std::endl; std::cout << "Perturbation " << lpSolver->perturbation() << " (default 100)" << std::endl; CoinReadPrintit( "Presolve being done with 5 passes\n\ Dual steepest edge steep/partial on matrix shape and factorization density\n\ Clpnnnn taken out of messages\n\ If Factorization frequency default then done on size of matrix\n\n\ (-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\ You can switch to interactive mode at any time so\n\ clp watson.mps -scaling off -primalsimplex\nis the same as\n\ clp watson.mps -\nscaling off\nprimalsimplex" ); break; case CLP_PARAM_ACTION_CSVSTATISTICS: { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } int state = 0; char buffer[1000]; FILE *fp = fopen(fileName.c_str(), "r"); if (fp) { // file already there state = 1; char * getBuffer = fgets(buffer, 1000, fp); if (getBuffer) { // assume header there state = 2; } fclose(fp); } fp = fopen(fileName.c_str(), "a"); if (fp) { // can open - lets go for it // first header if needed if (state != 2) { fprintf(fp, "Name,result,time,sys,elapsed,objective,continuous,tightened,cut_time,nodes,iterations,rows,columns,processed_rows,processed_columns"); for (int i = 0; i < statistics_number_generators; i++) fprintf(fp, ",%s", statistics_name_generators[i]); fprintf(fp, ",runtime_options"); fprintf(fp, "\n"); } strcpy(buffer, argv[1]); char * slash = buffer; for (int i = 0; i < static_cast(strlen(buffer)); i++) { if (buffer[i] == '/' || buffer[i] == '\\') slash = buffer + i + 1; } fprintf(fp, "%s,%s,%.2f,%.2f,%.2f,%.16g,%g,%g,%.2f,%d,%d,%d,%d,%d,%d", slash, statistics_result.c_str(), statistics_seconds, statistics_sys_seconds, statistics_elapsed_seconds, statistics_obj, statistics_continuous, statistics_tighter, statistics_cut_time, statistics_nodes, statistics_iterations, statistics_nrows, statistics_ncols, statistics_nprocessedrows, statistics_nprocessedcols); for (int i = 0; i < statistics_number_generators; i++) fprintf(fp, ",%d", statistics_number_cuts[i]); fprintf(fp, ","); for (int i = 1; i < argc; i++) { if (strstr(argv[i], ".gz") || strstr(argv[i], ".mps")) continue; if (!argv[i] || !strncmp(argv[i], "-csv", 4)) break; fprintf(fp, "%s ", argv[i]); } fprintf(fp, "\n"); fclose(fp); } else { std::cout << "Unable to open file " << fileName << std::endl; } } break; case CLP_PARAM_ACTION_SOLUTION: case CLP_PARAM_ACTION_NEXTBESTSOLUTION: case CLP_PARAM_ACTION_GMPL_SOLUTION: if (goodModel) { ClpSimplex * saveLpSolver = NULL; // get next field field = CoinReadGetString(argc, argv); bool append = false; if (field == "append$") { field = "$"; append = true; } if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; FILE *fp = NULL; if (field == "-" || field == "EOL" || field == "stdout") { // stdout fp = stdout; } else if (field == "stderr") { // stderr fp = stderr; } else { bool absolutePath; if (dirsep == '/') { // non Windows (or cygwin) absolutePath = (field[0] == '/'); } else { //Windows (non cycgwin) absolutePath = (field[0] == '\\'); // but allow for : if (strchr(field.c_str(), ':')) absolutePath = true; } if (absolutePath) { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } if (!append) fp = fopen(fileName.c_str(), "w"); else fp = fopen(fileName.c_str(), "a"); } if (fp) { #ifndef CBC_OTHER_SOLVER // See if Glpk if (type == CLP_PARAM_ACTION_GMPL_SOLUTION) { int numberRows = lpSolver->getNumRows(); int numberColumns = lpSolver->getNumCols(); int numberGlpkRows=numberRows+1; #ifdef COIN_HAS_GLPK if (cbc_glp_prob) { // from gmpl numberGlpkRows=glp_get_num_rows(cbc_glp_prob); if (numberGlpkRows!=numberRows) printf("Mismatch - cbc %d rows, glpk %d\n", numberRows,numberGlpkRows); } #endif fprintf(fp,"%d %d\n",numberGlpkRows, numberColumns); int iStat = lpSolver->status(); int iStat2 = GLP_UNDEF; bool integerProblem = false; if (integerStatus >= 0){ iStat = integerStatus; integerProblem = true; } if (iStat == 0) { // optimal if (integerProblem) iStat2 = GLP_OPT; else iStat2 = GLP_FEAS; } else if (iStat == 1) { // infeasible iStat2 = GLP_NOFEAS; } else if (iStat == 2) { // unbounded // leave as 1 } else if (iStat >= 3 && iStat <= 5) { if (babModel_ && !babModel_->bestSolution()) iStat2 = GLP_NOFEAS; else iStat2 = GLP_FEAS; } else if (iStat == 6) { // bab infeasible iStat2 = GLP_NOFEAS; } lpSolver->computeObjectiveValue(false); double objValue = clpSolver->getObjValue(); if (integerProblem) fprintf(fp,"%d %g\n",iStat2,objValue); else fprintf(fp,"%d 2 %g\n",iStat2,objValue); if (numberGlpkRows > numberRows) { // objective as row if (integerProblem) { fprintf(fp,"%g\n",objValue); } else { fprintf(fp,"4 %g 1.0\n",objValue); } } int lookup[6]= {4,1,3,2,4,5}; const double * primalRowSolution = lpSolver->primalRowSolution(); const double * dualRowSolution = lpSolver->dualRowSolution(); for (int i=0;igetRowStatus(i)], primalRowSolution[i],dualRowSolution[i]); } } const double * primalColumnSolution = lpSolver->primalColumnSolution(); const double * dualColumnSolution = lpSolver->dualColumnSolution(); for (int i=0;igetColumnStatus(i)], primalColumnSolution[i],dualColumnSolution[i]); } } fclose(fp); #ifdef COIN_HAS_GLPK if (cbc_glp_prob) { if (integerProblem) { glp_read_mip(cbc_glp_prob,fileName.c_str()); glp_mpl_postsolve(cbc_glp_tran, cbc_glp_prob, GLP_MIP); } else { glp_read_sol(cbc_glp_prob,fileName.c_str()); glp_mpl_postsolve(cbc_glp_tran, cbc_glp_prob, GLP_SOL); } // free up as much as possible glp_free(cbc_glp_prob); glp_mpl_free_wksp(cbc_glp_tran); cbc_glp_prob = NULL; cbc_glp_tran = NULL; //gmp_free_mem(); /* check that no memory blocks are still allocated */ glp_free_env(); } #endif break; } if (printMode < 5) { if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) { // save const double * nextBestSolution = model_.savedSolution(1); if (!nextBestSolution) { sprintf(generalPrint, "All alternative solutions printed"); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; break; } else { sprintf(generalPrint, "Alternative solution - %d remaining",model_.numberSavedSolutions()-2); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } saveLpSolver = lpSolver; assert (clpSolver->getModelPtr()==saveLpSolver); lpSolver = new ClpSimplex(*saveLpSolver); #ifndef NDEBUG ClpSimplex * oldSimplex = clpSolver->swapModelPtr(lpSolver); assert (oldSimplex==saveLpSolver); #else clpSolver->swapModelPtr(lpSolver); #endif double * solution = lpSolver->primalColumnSolution(); double * lower = lpSolver->columnLower(); double * upper = lpSolver->columnUpper(); int numberColumns=lpSolver->numberColumns(); memcpy(solution,nextBestSolution,numberColumns*sizeof(double)); model_.deleteSavedSolution(1); for (int i = 0; i < numberColumns; i++) { if (clpSolver->isInteger(i)) { double value=floor(solution[i]+0.5); lower[i]=value; upper[i]=value; } } lpSolver->allSlackBasis(); lpSolver->initialSolve(); } // Write solution header (suggested by Luigi Poderico) // Refresh solver lpSolver = clpSolver->getModelPtr(); lpSolver->computeObjectiveValue(false); double objValue = lpSolver->getObjValue(); int iStat = lpSolver->status(); int iStat2 = -1; if (integerStatus >= 0){ iStat = integerStatus; iStat2 = babModel_->secondaryStatus(); } if (iStat == 0) { fprintf(fp, "Optimal" ); if (iStat2 == 2){ fprintf(fp, " (within gap tolerance)" ); } } else if (iStat == 1) { // infeasible fprintf(fp, "Infeasible" ); } else if (iStat == 2) { // unbounded fprintf(fp, "Unbounded" ); } else if (iStat >= 3 && iStat <= 5) { if (iStat == 3) { if (iStat2 == 4){ fprintf(fp, "Stopped on time" ); }else{ fprintf(fp, "Stopped on iterations" ); } } else if (iStat == 4){ fprintf(fp, "Stopped on difficulties" ); } else { fprintf(fp, "Stopped on ctrl-c" ); } if (babModel_ && !babModel_->bestSolution()) fprintf(fp, " (no integer solution - continuous used)"); } else if (iStat == 6) { // bab infeasible fprintf(fp, "Integer infeasible" ); } else { fprintf(fp, "Status unknown" ); } fprintf(fp, " - objective value %.8f\n", objValue); } #endif // make fancy later on int iRow; int numberRows = clpSolver->getNumRows(); const double * dualRowSolution = clpSolver->getRowPrice(); const double * primalRowSolution = clpSolver->getRowActivity(); const double * rowLower = clpSolver->getRowLower(); const double * rowUpper = clpSolver->getRowUpper(); double primalTolerance ; clpSolver->getDblParam(OsiPrimalTolerance, primalTolerance); size_t lengthPrint = static_cast(CoinMax(lengthName, 8)); bool doMask = (printMask != "" && lengthName); int * maskStarts = NULL; int maxMasks = 0; char ** masks = NULL; if (doMask) { int nAst = 0; const char * pMask2 = printMask.c_str(); char pMask[100]; size_t iChar; size_t lengthMask = strlen(pMask2); assert (lengthMask < 100); if (*pMask2 == '"') { if (pMask2[lengthMask-1] != '"') { printf("mismatched \" in mask %s\n", pMask2); break; } else { strcpy(pMask, pMask2 + 1); *strchr(pMask, '"') = '\0'; } } else if (*pMask2 == '\'') { if (pMask2[lengthMask-1] != '\'') { printf("mismatched ' in mask %s\n", pMask2); break; } else { strcpy(pMask, pMask2 + 1); *strchr(pMask, '\'') = '\0'; } } else { strcpy(pMask, pMask2); } if (lengthMask > static_cast(lengthName)) { printf("mask %s too long - skipping\n", pMask); break; } maxMasks = 1; for (iChar = 0; iChar < lengthMask; iChar++) { if (pMask[iChar] == '*') { nAst++; maxMasks *= (lengthName + 1); } } int nEntries = 1; maskStarts = new int[lengthName+2]; masks = new char * [maxMasks]; char ** newMasks = new char * [maxMasks]; int i; for (i = 0; i < maxMasks; i++) { masks[i] = new char[lengthName+1]; newMasks[i] = new char[lengthName+1]; } strcpy(masks[0], pMask); for (int iAst = 0; iAst < nAst; iAst++) { int nOldEntries = nEntries; nEntries = 0; for (int iEntry = 0; iEntry < nOldEntries; iEntry++) { char * oldMask = masks[iEntry]; char * ast = strchr(oldMask, '*'); assert (ast); size_t length = strlen(oldMask) - 1; size_t nBefore = ast - oldMask; size_t nAfter = length - nBefore; // and add null nAfter++; for (int i = 0; i <= lengthName - static_cast(length); i++) { char * maskOut = newMasks[nEntries]; memcpy(maskOut, oldMask, nBefore); for (int k = 0; k < i; k++) maskOut[k+nBefore] = '?'; memcpy(maskOut + nBefore + i, ast + 1, nAfter); nEntries++; assert (nEntries <= maxMasks); } } char ** temp = masks; masks = newMasks; newMasks = temp; } // Now extend and sort int * sort = new int[nEntries]; for (i = 0; i < nEntries; i++) { char * maskThis = masks[i]; size_t length = strlen(maskThis); while (length > 0 && maskThis[length-1] == ' ') length--; maskThis[length] = '\0'; sort[i] = static_cast(length); } CoinSort_2(sort, sort + nEntries, masks); int lastLength = -1; for (i = 0; i < nEntries; i++) { int length = sort[i]; while (length > lastLength) maskStarts[++lastLength] = i; } maskStarts[++lastLength] = nEntries; delete [] sort; for (i = 0; i < maxMasks; i++) delete [] newMasks[i]; delete [] newMasks; } if (printMode > 5) { ClpSimplex * solver = clpSolver->getModelPtr(); int numberColumns = solver->numberColumns(); // column length unless rhs ranging int number = numberColumns; switch (printMode) { // bound ranging case 6: fprintf(fp,"Bound ranging"); break; // rhs ranging case 7: fprintf(fp,"Rhs ranging"); number = numberRows; break; // objective ranging case 8: fprintf(fp,"Objective ranging"); break; } if (printMode<9) { if (lengthName) fprintf(fp,",name"); fprintf(fp,",increase,variable,decrease,variable\n"); } int * which = new int [ number]; if (printMode != 7) { if (!doMask) { for (int i = 0; i < number;i ++) which[i]=i; } else { int n = 0; for (int i = 0; i < number;i ++) { if (maskMatches(maskStarts,masks,columnNames[i])) which[n++]=i; } if (n) { number=n; } else { printf("No names match - doing all\n"); for (int i = 0; i < number;i ++) which[i]=i; } } } else { if (!doMask) { for (int i = 0; i < number;i ++) which[i]=i+numberColumns; } else { int n = 0; for (int i = 0; i < number;i ++) { if (maskMatches(maskStarts,masks,rowNames[i])) which[n++]=i+numberColumns; } if (n) { number=n; } else { printf("No names match - doing all\n"); for (int i = 0; i < number;i ++) which[i]=i+numberColumns; } } } double * valueIncrease = new double [ number]; int * sequenceIncrease = new int [ number]; double * valueDecrease = new double [ number]; int * sequenceDecrease = new int [ number]; switch (printMode) { // bound or rhs ranging case 6: case 7: solver->primalRanging(numberRows, which, valueIncrease, sequenceIncrease, valueDecrease, sequenceDecrease); break; // objective ranging case 8: solver->dualRanging(number, which, valueIncrease, sequenceIncrease, valueDecrease, sequenceDecrease); break; } for (int i = 0; i < number; i++) { int iWhich = which[i]; fprintf(fp, "%d,", (iWhich 2 && printMode < 5) { for (iRow = 0; iRow < numberRows; iRow++) { int type = printMode - 3; if (primalRowSolution[iRow] > rowUpper[iRow] + primalTolerance || primalRowSolution[iRow] < rowLower[iRow] - primalTolerance) { fprintf(fp, "** "); type = 2; } else if (fabs(primalRowSolution[iRow]) > 1.0e-8) { type = 1; } else if (numberRows < 50) { type = 3; } if (doMask && !maskMatches(maskStarts, masks, rowNames[iRow])) type = 0; if (type) { fprintf(fp, "%7d ", iRow); if (lengthName) { const char * name = rowNames[iRow].c_str(); size_t n = strlen(name); size_t i; for (i = 0; i < n; i++) fprintf(fp, "%c", name[i]); for (; i < lengthPrint; i++) fprintf(fp, " "); } fprintf(fp, " %15.8g %15.8g\n", primalRowSolution[iRow], dualRowSolution[iRow]); } } } int iColumn; int numberColumns = clpSolver->getNumCols(); const double * dualColumnSolution = clpSolver->getReducedCost(); const double * primalColumnSolution = clpSolver->getColSolution(); const double * columnLower = clpSolver->getColLower(); const double * columnUpper = clpSolver->getColUpper(); if (printMode != 2) { if (printMode == 5) { if (lengthName) fprintf(fp, "name"); else fprintf(fp, "number"); fprintf(fp, ",solution\n"); } for (iColumn = 0; iColumn < numberColumns; iColumn++) { int type = (printMode > 3) ? 1 : 0; if (primalColumnSolution[iColumn] > columnUpper[iColumn] + primalTolerance || primalColumnSolution[iColumn] < columnLower[iColumn] - primalTolerance) { fprintf(fp, "** "); type = 2; } else if (fabs(primalColumnSolution[iColumn]) > 1.0e-8) { type = 1; } else if (numberColumns < 50) { type = 3; } // see if integer if ((!clpSolver->isInteger(iColumn) || fabs(primalColumnSolution[iColumn]) < 1.0e-8) && printMode == 1) type = 0; if (doMask && !maskMatches(maskStarts, masks, columnNames[iColumn])) type = 0; if (type) { if (printMode != 5) { fprintf(fp, "%7d ", iColumn); if (lengthName) { const char * name = columnNames[iColumn].c_str(); size_t n = strlen(name); size_t i; for (i = 0; i < n; i++) fprintf(fp, "%c", name[i]); for (; i < lengthPrint; i++) fprintf(fp, " "); } fprintf(fp, " %15.8g %15.8g\n", primalColumnSolution[iColumn], dualColumnSolution[iColumn]); } else { char temp[100]; if (lengthName) { const char * name = columnNames[iColumn].c_str(); for (int i = 0; i < lengthName; i++) temp[i] = name[i]; temp[lengthName] = '\0'; } else { sprintf(temp, "%7d", iColumn); } sprintf(temp + strlen(temp), ", %15.8g", primalColumnSolution[iColumn]); size_t n = strlen(temp); size_t k = 0; for (size_t i = 0; i < n + 1; i++) { if (temp[i] != ' ') temp[k++] = temp[i]; } fprintf(fp, "%s\n", temp); } } } if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) { if(saveLpSolver) { clpSolver->swapModelPtr(saveLpSolver); delete lpSolver; lpSolver=saveLpSolver; saveLpSolver=NULL; } } } else { // special format suitable for OsiRowCutDebugger int n = 0; bool comma = false; bool newLine = false; fprintf(fp, "\tint intIndicesV[]={\n"); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) { if (comma) fprintf(fp, ","); if (newLine) fprintf(fp, "\n"); fprintf(fp, "%d ", iColumn); comma = true; newLine = false; n++; if (n == 10) { n = 0; newLine = true; } } } fprintf(fp, "};\n"); n = 0; comma = false; newLine = false; fprintf(fp, "\tdouble intSolnV[]={\n"); for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) { if (comma) fprintf(fp, ","); if (newLine) fprintf(fp, "\n"); int value = static_cast (primalColumnSolution[iColumn] + 0.5); fprintf(fp, "%d. ", value); comma = true; newLine = false; n++; if (n == 10) { n = 0; newLine = true; } } } fprintf(fp, "};\n"); } if (fp != stdout) fclose(fp); if (masks) { delete [] maskStarts; for (int i = 0; i < maxMasks; i++) delete [] masks[i]; delete [] masks; } } else { std::cout << "Unable to open file " << fileName << std::endl; } } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_SAVESOL: if (goodModel) { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } saveSolution(lpSolver, fileName); } else { #ifndef DISALLOW_PRINTING std::cout << "** Current model not valid" << std::endl; #endif } break; case CLP_PARAM_ACTION_DUMMY: break; case CLP_PARAM_ACTION_ENVIRONMENT: CbcOrClpEnvironmentIndex = 0; break; case CLP_PARAM_ACTION_PARAMETRICS: if (goodModel) { // get next field field = CoinReadGetString(argc, argv); if (field == "$") { field = parameters_[iParam].stringValue(); } else if (field == "EOL") { parameters_[iParam].printString(); break; } else { parameters_[iParam].setStringValue(field); } std::string fileName; //bool canOpen = false; if (field[0] == '/' || field[0] == '\\') { fileName = field; } else if (field[0] == '~') { char * environVar = getenv("HOME"); if (environVar) { std::string home(environVar); field = field.erase(0, 1); fileName = home + field; } else { fileName = field; } } else { fileName = directory + field; } static_cast (lpSolver)->parametrics(fileName.c_str()); time2 = CoinCpuTime(); totalTime += time2 - time1; time1 = time2; } else { std::cout << "** Current model not valid" << std::endl; } break; default: abort(); } } } else if (!numberMatches) { std::cout << "No match for " << field << " - ? for list of commands" << std::endl; } else if (numberMatches == 1) { if (!numberQuery) { std::cout << "Short match for " << field << " - completion: "; std::cout << parameters_[firstMatch].matchName() << std::endl; } else if (numberQuery) { std::cout << parameters_[firstMatch].matchName() << " : "; std::cout << parameters_[firstMatch].shortHelp() << std::endl; if (numberQuery >= 2) parameters_[firstMatch].printLongHelp(); } } else { if (!numberQuery) std::cout << "Multiple matches for " << field << " - possible completions:" << std::endl; else std::cout << "Completions of " << field << ":" << std::endl; for ( iParam = 0; iParam < numberParameters_; iParam++ ) { int match = parameters_[iParam].matches(field); if (match && parameters_[iParam].displayThis()) { std::cout << parameters_[iParam].matchName(); if (numberQuery >= 2) std::cout << " : " << parameters_[iParam].shortHelp(); std::cout << std::endl; } } } } } #if CBC_QUIET == 0 sprintf(generalPrint , "Total time (CPU seconds): %.2f (Wallclock seconds): %.2f\n", CoinCpuTime() - time0, CoinGetTimeOfDay() - time0Elapsed); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; #endif #ifdef COIN_HAS_GLPK if (cbc_glp_prob) { // free up as much as possible glp_free(cbc_glp_prob); glp_mpl_free_wksp(cbc_glp_tran); glp_free_env(); cbc_glp_prob = NULL; cbc_glp_tran = NULL; } #endif delete [] statistics_number_cuts; delete [] statistics_name_generators; // By now all memory should be freed #ifdef DMALLOC //dmalloc_log_unfreed(); //dmalloc_shutdown(); #endif if (babModel_) { model_.moveInfo(*babModel_); #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * clpSolver0 = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver()); ClpSimplex * lpSolver0 = clpSolver0->getModelPtr(); OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver()); ClpSimplex * lpSolver = clpSolver->getModelPtr(); if (lpSolver0 != lpSolver && lpSolver != originalSolver->getModelPtr()) lpSolver->moveInfo(*lpSolver0); //babModel_->setModelOwnsSolver(false); #endif } #ifdef CBC_SIG_TRAP // On Sun sometimes seems to be error - try and get round it CoinSighandler_t saveSignal = SIG_DFL; // register signal handler saveSignal = signal(SIGSEGV, signal_handler_error); // to force failure!babModel_->setNumberObjects(20000); if (!sigsetjmp(cbc_seg_buffer, 1)) { #endif delete babModel_; #ifdef CBC_SIG_TRAP } else { std::cerr << "delete babModel_ failed" << std::endl; } #endif babModel_ = NULL; model_.solver()->setWarmStart(NULL); //sprintf(generalPrint, "Total time %.2f", CoinCpuTime() - time0); //generalMessageHandler->message(CLP_GENERAL, generalMessages) //<< generalPrint //<< CoinMessageEol; return 0; } int CbcMain (int argc, const char *argv[], CbcModel & model) { CbcMain0(model); return CbcMain1(argc, argv, model); } void CbcMain0 (CbcModel & model) { CbcMain0(model,staticParameterData); } void CbcMain0 (CbcModel & model, CbcSolverUsefulData & parameterData) { CbcOrClpParam * parameters = parameterData.parameters_; int numberParameters = parameterData.numberParameters_; #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface * originalSolver = dynamic_cast (model.solver()); #elif CBC_OTHER_SOLVER==1 OsiCpxSolverInterface * originalSolver = dynamic_cast (model.solver()); // Dummy solvers OsiClpSolverInterface dummySolver; ClpSimplex * lpSolver = dummySolver.getModelPtr(); OsiCpxSolverInterface * clpSolver = originalSolver; #endif assert (originalSolver); CoinMessageHandler * generalMessageHandler = originalSolver->messageHandler(); generalMessageHandler->setPrefix(true); #ifndef CBC_OTHER_SOLVER OsiSolverInterface * solver = model.solver(); OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); ClpSimplex * lpSolver = clpSolver->getModelPtr(); lpSolver->setPerturbation(50); lpSolver->messageHandler()->setPrefix(false); #endif //establishParams(numberParameters, parameters) ; const char dirsep = CoinFindDirSeparator(); std::string directory; std::string dirSample; std::string dirNetlib; std::string dirMiplib; if (dirsep == '/') { directory = "./"; dirSample = "../../Data/Sample/"; dirNetlib = "../../Data/Netlib/"; dirMiplib = "../../Data/miplib3/"; } else { directory = ".\\"; dirSample = "..\\..\\..\\..\\Data\\Sample\\"; dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; } std::string defaultDirectory = directory; std::string importFile = ""; std::string exportFile = "default.mps"; std::string importBasisFile = ""; std::string importPriorityFile = ""; std::string debugFile = ""; std::string printMask = ""; std::string exportBasisFile = "default.bas"; std::string saveFile = "default.prob"; std::string restoreFile = "default.prob"; std::string solutionFile = "stdout"; std::string solutionSaveFile = "solution.file"; int doIdiot = -1; int outputFormat = 2; int substitution = 3; int dualize = 3; int preSolve = 5; int doSprint = -1; int testOsiParameters = -1; parameters[whichParam(CLP_PARAM_ACTION_BASISIN, numberParameters, parameters)].setStringValue(importBasisFile); parameters[whichParam(CBC_PARAM_ACTION_PRIORITYIN, numberParameters, parameters)].setStringValue(importPriorityFile); parameters[whichParam(CLP_PARAM_ACTION_BASISOUT, numberParameters, parameters)].setStringValue(exportBasisFile); parameters[whichParam(CLP_PARAM_ACTION_DEBUG, numberParameters, parameters)].setStringValue(debugFile); parameters[whichParam(CLP_PARAM_ACTION_PRINTMASK, numberParameters, parameters)].setStringValue(printMask); parameters[whichParam(CLP_PARAM_ACTION_DIRECTORY, numberParameters, parameters)].setStringValue(directory); parameters[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, numberParameters, parameters)].setStringValue(dirSample); parameters[whichParam(CLP_PARAM_ACTION_DIRNETLIB, numberParameters, parameters)].setStringValue(dirNetlib); parameters[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, numberParameters, parameters)].setStringValue(dirMiplib); parameters[whichParam(CLP_PARAM_DBL_DUALBOUND, numberParameters, parameters)].setDoubleValue(lpSolver->dualBound()); parameters[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters, parameters)].setDoubleValue(lpSolver->dualTolerance()); parameters[whichParam(CLP_PARAM_ACTION_EXPORT, numberParameters, parameters)].setStringValue(exportFile); parameters[whichParam(CLP_PARAM_INT_IDIOT, numberParameters, parameters)].setIntValue(doIdiot); parameters[whichParam(CLP_PARAM_ACTION_IMPORT, numberParameters, parameters)].setStringValue(importFile); parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters, parameters)].setDoubleValue(1.0e-8); int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters, parameters); int log = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters, parameters); parameters[slog].setIntValue(1); clpSolver->messageHandler()->setLogLevel(1) ; model.messageHandler()->setLogLevel(1); lpSolver->setLogLevel(1); parameters[log].setIntValue(1); parameters[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters, parameters)].setIntValue(lpSolver->factorizationFrequency()); parameters[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters, parameters)].setIntValue(lpSolver->maximumIterations()); parameters[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, numberParameters, parameters)].setIntValue(outputFormat); parameters[whichParam(CLP_PARAM_INT_PRESOLVEPASS, numberParameters, parameters)].setIntValue(preSolve); parameters[whichParam(CLP_PARAM_INT_PERTVALUE, numberParameters, parameters)].setIntValue(lpSolver->perturbation()); parameters[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters, parameters)].setDoubleValue(lpSolver->primalTolerance()); parameters[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters, parameters)].setDoubleValue(lpSolver->infeasibilityCost()); parameters[whichParam(CLP_PARAM_ACTION_RESTORE, numberParameters, parameters)].setStringValue(restoreFile); parameters[whichParam(CLP_PARAM_ACTION_SAVE, numberParameters, parameters)].setStringValue(saveFile); //parameters[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters,parameters)].setDoubleValue(1.0e8); parameters[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, numberParameters, parameters)].setDoubleValue(1.0e8); parameters[whichParam(CLP_PARAM_ACTION_SOLUTION, numberParameters, parameters)].setStringValue(solutionFile); parameters[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, numberParameters, parameters)].setStringValue(solutionFile); parameters[whichParam(CLP_PARAM_ACTION_SAVESOL, numberParameters, parameters)].setStringValue(solutionSaveFile); parameters[whichParam(CLP_PARAM_INT_SPRINT, numberParameters, parameters)].setIntValue(doSprint); parameters[whichParam(CLP_PARAM_INT_SUBSTITUTION, numberParameters, parameters)].setIntValue(substitution); parameters[whichParam(CLP_PARAM_INT_DUALIZE, numberParameters, parameters)].setIntValue(dualize); model.setNumberBeforeTrust(10); parameters[whichParam(CBC_PARAM_INT_NUMBERBEFORE, numberParameters, parameters)].setIntValue(5); parameters[whichParam(CBC_PARAM_INT_MAXNODES, numberParameters, parameters)].setIntValue(model.getMaximumNodes()); model.setNumberStrong(5); parameters[whichParam(CBC_PARAM_INT_STRONGBRANCHING, numberParameters, parameters)].setIntValue(model.numberStrong()); parameters[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, numberParameters, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcInfeasibilityWeight)); parameters[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, numberParameters, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcIntegerTolerance)); parameters[whichParam(CBC_PARAM_DBL_INCREMENT, numberParameters, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcCutoffIncrement)); parameters[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters, parameters)].setIntValue(testOsiParameters); parameters[whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters, parameters)].setIntValue(1003); initialPumpTune = 1003; #ifdef CBC_THREAD parameters[whichParam(CBC_PARAM_INT_THREADS, numberParameters, parameters)].setIntValue(0); #endif // Set up likely cut generators and defaults parameters[whichParam(CBC_PARAM_STR_PREPROCESS, numberParameters, parameters)].setCurrentOption("sos"); parameters[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters, parameters)].setIntValue(1057); parameters[whichParam(CBC_PARAM_INT_CUTPASSINTREE, numberParameters, parameters)].setIntValue(1); parameters[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, numberParameters, parameters)].setIntValue(-1); parameters[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters, parameters)].setIntValue(100); parameters[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, numberParameters, parameters)].setCurrentOption("on"); parameters[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, numberParameters, parameters)].setCurrentOption("on"); parameters[whichParam(CBC_PARAM_STR_NODESTRATEGY, numberParameters, parameters)].setCurrentOption("fewest"); parameters[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters, parameters)].setCurrentOption("ifmove"); parameters[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters, parameters)].setCurrentOption("ifmove"); parameters[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters, parameters)].setCurrentOption("ifmove"); parameters[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_REDSPLITCUTS, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_GMICUTS, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_CLIQUECUTS, numberParameters, parameters)].setCurrentOption("ifmove"); parameters[whichParam(CBC_PARAM_STR_MIXEDCUTS, numberParameters, parameters)].setCurrentOption("ifmove"); parameters[whichParam(CBC_PARAM_STR_FLOWCUTS, numberParameters, parameters)].setCurrentOption("ifmove"); parameters[whichParam(CBC_PARAM_STR_TWOMIRCUTS, numberParameters, parameters)].setCurrentOption("root"); parameters[whichParam(CBC_PARAM_STR_LANDPCUTS, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_RESIDCUTS, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_ROUNDING, numberParameters, parameters)].setCurrentOption("on"); parameters[whichParam(CBC_PARAM_STR_FPUMP, numberParameters, parameters)].setCurrentOption("on"); parameters[whichParam(CBC_PARAM_STR_GREEDY, numberParameters, parameters)].setCurrentOption("on"); parameters[whichParam(CBC_PARAM_STR_COMBINE, numberParameters, parameters)].setCurrentOption("on"); parameters[whichParam(CBC_PARAM_STR_CROSSOVER2, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_PIVOTANDFIX, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_RANDROUND, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_NAIVE, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_RINS, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_DINS, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_RENS, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_LOCALTREE, numberParameters, parameters)].setCurrentOption("off"); parameters[whichParam(CBC_PARAM_STR_COSTSTRATEGY, numberParameters, parameters)].setCurrentOption("off"); } /* Routines to print statistics. */ static void breakdown(const char * name, int numberLook, const double * region) { double range[] = { -COIN_DBL_MAX, -1.0e15, -1.0e11, -1.0e8, -1.0e5, -1.0e4, -1.0e3, -1.0e2, -1.0e1, -1.0, -1.0e-1, -1.0e-2, -1.0e-3, -1.0e-4, -1.0e-5, -1.0e-8, -1.0e-11, -1.0e-15, 0.0, 1.0e-15, 1.0e-11, 1.0e-8, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1, 1.0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e8, 1.0e11, 1.0e15, COIN_DBL_MAX }; int nRanges = static_cast (sizeof(range) / sizeof(double)); int * number = new int[nRanges]; memset(number, 0, nRanges*sizeof(int)); int * numberExact = new int[nRanges]; memset(numberExact, 0, nRanges*sizeof(int)); int i; for ( i = 0; i < numberLook; i++) { double value = region[i]; for (int j = 0; j < nRanges; j++) { if (value == range[j]) { numberExact[j]++; break; } else if (value < range[j]) { number[j]++; break; } } } printf("\n%s has %d entries\n", name, numberLook); for (i = 0; i < nRanges; i++) { if (number[i]) printf("%d between %g and %g", number[i], range[i-1], range[i]); if (numberExact[i]) { if (number[i]) printf(", "); printf("%d exactly at %g", numberExact[i], range[i]); } if (number[i] + numberExact[i]) printf("\n"); } delete [] number; delete [] numberExact; } static void statistics(ClpSimplex * originalModel, ClpSimplex * model) { int numberColumns = originalModel->numberColumns(); const char * integerInformation = originalModel->integerInformation(); const double * columnLower = originalModel->columnLower(); const double * columnUpper = originalModel->columnUpper(); int numberIntegers = 0; int numberBinary = 0; int iRow, iColumn; if (integerInformation) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (integerInformation[iColumn]) { if (columnUpper[iColumn] > columnLower[iColumn]) { numberIntegers++; if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 1) numberBinary++; } } } } numberColumns = model->numberColumns(); int numberRows = model->numberRows(); columnLower = model->columnLower(); columnUpper = model->columnUpper(); const double * rowLower = model->rowLower(); const double * rowUpper = model->rowUpper(); const double * objective = model->objective(); CoinPackedMatrix * matrix = model->matrix(); CoinBigIndex numberElements = matrix->getNumElements(); const int * columnLength = matrix->getVectorLengths(); //const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); int * number = new int[numberRows+1]; memset(number, 0, (numberRows + 1)*sizeof(int)); int numberObjSingletons = 0; /* cType 0 0/inf, 1 0/up, 2 lo/inf, 3 lo/up, 4 free, 5 fix, 6 -inf/0, 7 -inf/up, 8 0/1 */ int cType[9]; std::string cName[] = {"0.0->inf,", "0.0->up,", "lo->inf,", "lo->up,", "free,", "fixed,", "-inf->0.0,", "-inf->up,", "0.0->1.0" }; int nObjective = 0; memset(cType, 0, sizeof(cType)); for (iColumn = 0; iColumn < numberColumns; iColumn++) { int length = columnLength[iColumn]; if (length == 1 && objective[iColumn]) numberObjSingletons++; number[length]++; if (objective[iColumn]) nObjective++; if (columnLower[iColumn] > -1.0e20) { if (columnLower[iColumn] == 0.0) { if (columnUpper[iColumn] > 1.0e20) cType[0]++; else if (columnUpper[iColumn] == 1.0) cType[8]++; else if (columnUpper[iColumn] == 0.0) cType[5]++; else cType[1]++; } else { if (columnUpper[iColumn] > 1.0e20) cType[2]++; else if (columnUpper[iColumn] == columnLower[iColumn]) cType[5]++; else cType[3]++; } } else { if (columnUpper[iColumn] > 1.0e20) cType[4]++; else if (columnUpper[iColumn] == 0.0) cType[6]++; else cType[7]++; } } /* rType 0 E 0, 1 E 1, 2 E -1, 3 E other, 4 G 0, 5 G 1, 6 G other, 7 L 0, 8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free */ int rType[13]; std::string rName[] = {"E 0.0,", "E 1.0,", "E -1.0,", "E other,", "G 0.0,", "G 1.0,", "G other,", "L 0.0,", "L 1.0,", "L other,", "Range 0.0->1.0,", "Range other,", "Free" }; memset(rType, 0, sizeof(rType)); for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] > -1.0e20) { if (rowLower[iRow] == 0.0) { if (rowUpper[iRow] > 1.0e20) rType[4]++; else if (rowUpper[iRow] == 1.0) rType[10]++; else if (rowUpper[iRow] == 0.0) rType[0]++; else rType[11]++; } else if (rowLower[iRow] == 1.0) { if (rowUpper[iRow] > 1.0e20) rType[5]++; else if (rowUpper[iRow] == rowLower[iRow]) rType[1]++; else rType[11]++; } else if (rowLower[iRow] == -1.0) { if (rowUpper[iRow] > 1.0e20) rType[6]++; else if (rowUpper[iRow] == rowLower[iRow]) rType[2]++; else rType[11]++; } else { if (rowUpper[iRow] > 1.0e20) rType[6]++; else if (rowUpper[iRow] == rowLower[iRow]) rType[3]++; else rType[11]++; } } else { if (rowUpper[iRow] > 1.0e20) rType[12]++; else if (rowUpper[iRow] == 0.0) rType[7]++; else if (rowUpper[iRow] == 1.0) rType[8]++; else rType[9]++; } } // Basic statistics printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n", numberRows, numberColumns, nObjective, numberElements); if (number[0] + number[1]) { printf("There are "); if (numberObjSingletons) printf("%d singletons with objective ", numberObjSingletons); int numberNoObj = number[1] - numberObjSingletons; if (numberNoObj) printf("%d singletons with no objective ", numberNoObj); if (number[0]) printf("** %d columns have no entries", number[0]); printf("\n"); } printf("Column breakdown:\n"); int k; for (k = 0; k < static_cast (sizeof(cType) / sizeof(int)); k++) { printf("%d of type %s ", cType[k], cName[k].c_str()); if (((k + 1) % 3) == 0) printf("\n"); } if ((k % 3) != 0) printf("\n"); printf("Row breakdown:\n"); for (k = 0; k < static_cast (sizeof(rType) / sizeof(int)); k++) { printf("%d of type %s ", rType[k], rName[k].c_str()); if (((k + 1) % 3) == 0) printf("\n"); } if ((k % 3) != 0) printf("\n"); if (model->logLevel() < 2) return ; int kMax = model->logLevel() > 3 ? 1000000 : 10; k = 0; for (iRow = 1; iRow <= numberRows; iRow++) { if (number[iRow]) { k++; printf("%d columns have %d entries\n", number[iRow], iRow); if (k == kMax) break; } } if (k < numberRows) { int kk = k; k = 0; for (iRow = numberRows; iRow >= 1; iRow--) { if (number[iRow]) { k++; if (k == kMax) break; } } if (k > kk) { printf("\n .........\n\n"); iRow = k; k = 0; for (; iRow < numberRows; iRow++) { if (number[iRow]) { k++; printf("%d columns have %d entries\n", number[iRow], iRow); if (k == kMax) break; } } } } delete [] number; printf("\n\n"); // get row copy CoinPackedMatrix rowCopy = *matrix; rowCopy.reverseOrdering(); //const int * column = rowCopy.getIndices(); const int * rowLength = rowCopy.getVectorLengths(); //const CoinBigIndex * rowStart = rowCopy.getVectorStarts(); //const double * element = rowCopy.getElements(); number = new int[numberColumns+1]; memset(number, 0, (numberColumns + 1)*sizeof(int)); for (iRow = 0; iRow < numberRows; iRow++) { int length = rowLength[iRow]; number[length]++; } if (number[0]) printf("** %d rows have no entries\n", number[0]); k = 0; for (iColumn = 1; iColumn <= numberColumns; iColumn++) { if (number[iColumn]) { k++; printf("%d rows have %d entries\n", number[iColumn], iColumn); if (k == kMax) break; } } if (k < numberColumns) { int kk = k; k = 0; for (iColumn = numberColumns; iColumn >= 1; iColumn--) { if (number[iColumn]) { k++; if (k == kMax) break; } } if (k > kk) { printf("\n .........\n\n"); iColumn = k; k = 0; for (; iColumn < numberColumns; iColumn++) { if (number[iColumn]) { k++; printf("%d rows have %d entries\n", number[iColumn], iColumn); if (k == kMax) break; } } } } delete [] number; // Now do breakdown of ranges breakdown("Elements", numberElements, elementByColumn); breakdown("RowLower", numberRows, rowLower); breakdown("RowUpper", numberRows, rowUpper); breakdown("ColumnLower", numberColumns, columnLower); breakdown("ColumnUpper", numberColumns, columnUpper); breakdown("Objective", numberColumns, objective); } static bool maskMatches(const int * starts, char ** masks, std::string & check) { // back to char as I am old fashioned const char * checkC = check.c_str(); size_t length = strlen(checkC); while (length > 0 && checkC[length-1] == ' ') length--; for (int i = starts[length]; i < starts[length+1]; i++) { char * thisMask = masks[i]; size_t k; for ( k = 0; k < length; k++) { if (thisMask[k] != '?' && thisMask[k] != checkC[k]) break; } if (k == length) return true; } return false; } static void clean(char * temp) { char * put = temp; while (*put >= ' ') put++; *put = '\0'; } static void generateCode(CbcModel * /*model*/, const char * fileName, int type, int preProcess) { // options on code generation bool sizecode = (type & 4) != 0; type &= 3; FILE * fp = fopen(fileName, "r"); assert (fp); int numberLines = 0; #define MAXLINES 5000 #define MAXONELINE 200 char line[MAXLINES][MAXONELINE]; strcpy(line[numberLines++], "0#if defined(_MSC_VER)"); strcpy(line[numberLines++], "0// Turn off compiler warning about long names"); strcpy(line[numberLines++], "0# pragma warning(disable:4786)"); strcpy(line[numberLines++], "0#endif\n"); strcpy(line[numberLines++], "0#include "); strcpy(line[numberLines++], "0#include "); strcpy(line[numberLines++], "0#include \"OsiClpSolverInterface.hpp\""); strcpy(line[numberLines++], "0#include \"CbcModel.hpp\""); strcpy(line[numberLines++], "0#include \"CbcCutGenerator.hpp\""); strcpy(line[numberLines++], "0#include \"CbcStrategy.hpp\""); strcpy(line[numberLines++], "0#include \"CglPreProcess.hpp\""); strcpy(line[numberLines++], "0#include \"CoinTime.hpp\""); if (preProcess > 0) strcpy(line[numberLines++], "0#include \"CglProbing.hpp\""); // possibly redundant // To allow generated 5's to be just before branchAndBound - do rest here strcpy(line[numberLines++], "5 cbcModel->initialSolve();"); strcpy(line[numberLines++], "5 if (clpModel->tightenPrimalBounds()!=0) {"); strcpy(line[numberLines++], "5 std::cout<<\"Problem is infeasible - tightenPrimalBounds!\"<dual(); // clean up"); if (sizecode) { // override some settings strcpy(line[numberLines++], "5 // compute some things using problem size"); strcpy(line[numberLines++], "5 cbcModel->setMinimumDrop(CoinMin(5.0e-2,"); strcpy(line[numberLines++], "5 fabs(cbcModel->getMinimizationObjValue())*1.0e-3+1.0e-4));"); strcpy(line[numberLines++], "5 if (cbcModel->getNumCols()<500)"); strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible"); strcpy(line[numberLines++], "5 else if (cbcModel->getNumCols()<5000)"); strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop"); strcpy(line[numberLines++], "5 else"); strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPassesAtRoot(20);"); strcpy(line[numberLines++], "5 cbcModel->setMaximumCutPasses(1);"); } if (preProcess <= 0) { // no preprocessing or strategy if (preProcess) { strcpy(line[numberLines++], "5 // Preprocessing using CbcStrategy"); strcpy(line[numberLines++], "5 CbcStrategyDefault strategy(1,5,5);"); strcpy(line[numberLines++], "5 strategy.setupPreProcessing(1);"); strcpy(line[numberLines++], "5 cbcModel->setStrategy(strategy);"); } } else { int translate[] = {9999, 0, 0, -1, 2, 3, -2}; strcpy(line[numberLines++], "5 // Hand coded preprocessing"); strcpy(line[numberLines++], "5 CglPreProcess process;"); strcpy(line[numberLines++], "5 OsiSolverInterface * saveSolver=cbcModel->solver()->clone();"); strcpy(line[numberLines++], "5 // Tell solver we are in Branch and Cut"); strcpy(line[numberLines++], "5 saveSolver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;"); strcpy(line[numberLines++], "5 // Default set of cut generators"); strcpy(line[numberLines++], "5 CglProbing generator1;"); strcpy(line[numberLines++], "5 generator1.setUsingObjective(1);"); strcpy(line[numberLines++], "5 generator1.setMaxPass(3);"); strcpy(line[numberLines++], "5 generator1.setMaxProbeRoot(saveSolver->getNumCols());"); strcpy(line[numberLines++], "5 generator1.setMaxElements(100);"); strcpy(line[numberLines++], "5 generator1.setMaxLookRoot(50);"); strcpy(line[numberLines++], "5 generator1.setRowCuts(3);"); strcpy(line[numberLines++], "5 // Add in generators"); strcpy(line[numberLines++], "5 process.addCutGenerator(&generator1);"); strcpy(line[numberLines++], "5 process.messageHandler()->setLogLevel(cbcModel->logLevel());"); strcpy(line[numberLines++], "5 OsiSolverInterface * solver2 = "); sprintf(line[numberLines++], "5 process.preProcessNonDefault(*saveSolver,%d,10);", translate[preProcess]); strcpy(line[numberLines++], "5 // Tell solver we are not in Branch and Cut"); strcpy(line[numberLines++], "5 saveSolver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;"); strcpy(line[numberLines++], "5 if (solver2)"); strcpy(line[numberLines++], "5 solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;"); strcpy(line[numberLines++], "5 if (!solver2) {"); strcpy(line[numberLines++], "5 std::cout<<\"Pre-processing says infeasible!\"<getNumRows()"); strcpy(line[numberLines++], "5 <<\" rows, \"<getNumCols()"); strcpy(line[numberLines++], "5 <<\" columns and \"<getNumElements()"); strcpy(line[numberLines++], "5 <<\" elements\"<getNumElements()<clone();"); strcpy(line[numberLines++], "5 cbcModel->assignSolver(solver2);"); strcpy(line[numberLines++], "5 cbcModel->initialSolve();"); } while (fgets(line[numberLines], MAXONELINE, fp)) { assert (numberLines < MAXLINES); clean(line[numberLines]); numberLines++; } fclose(fp); strcpy(line[numberLines++], "0\nint main (int argc, const char *argv[])\n{"); strcpy(line[numberLines++], "0 OsiClpSolverInterface solver1;"); strcpy(line[numberLines++], "0 int status=1;"); strcpy(line[numberLines++], "0 if (argc<2)"); strcpy(line[numberLines++], "0 std::cout<<\"Please give file name\"< (osiModel);"); strcpy(line[numberLines++], "0 ClpSimplex * clpModel = osiclpModel->getModelPtr();"); // add in comments about messages strcpy(line[numberLines++], "3 // You can save some time by switching off message building"); strcpy(line[numberLines++], "3 // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);"); // add in actual solve strcpy(line[numberLines++], "5 cbcModel->branchAndBound();"); strcpy(line[numberLines++], "8 std::cout<getNodeCount()<<\" nodes with objective \""); strcpy(line[numberLines++], "8 <getObjValue()"); strcpy(line[numberLines++], "8 <<(!cbcModel->status() ? \" Finished\" : \" Not finished\")"); strcpy(line[numberLines++], "8 <getMinimizationObjValue()<1.0e50) {"); if (preProcess > 0) { strcpy(line[numberLines++], "5 // post process"); strcpy(line[numberLines++], "5 process.postProcess(*cbcModel->solver());"); strcpy(line[numberLines++], "5 // Solution now back in saveSolver"); strcpy(line[numberLines++], "5 cbcModel->assignSolver(saveSolver);"); strcpy(line[numberLines++], "5 memcpy(cbcModel->bestSolution(),cbcModel->solver()->getColSolution(),"); strcpy(line[numberLines++], "5 numberColumns*sizeof(double));"); } strcpy(line[numberLines++], "5 // put back in original solver"); strcpy(line[numberLines++], "5 solver1.setColSolution(cbcModel->bestSolution());"); strcpy(line[numberLines++], "5 const double * solution = solver1.getColSolution();"); strcpy(line[numberLines++], "8 \n // Now you would use solution etc etc\n"); strcpy(line[numberLines++], "5"); strcpy(line[numberLines++], "5 // Get names from solver1 (as OsiSolverInterface may lose)"); strcpy(line[numberLines++], "5 std::vector columnNames = *solver1.getModelPtr()->columnNames();"); strcpy(line[numberLines++], "5 "); strcpy(line[numberLines++], "5 int iColumn;"); strcpy(line[numberLines++], "5 std::cout<1.0e-7&&solver1.isInteger(iColumn)) "); strcpy(line[numberLines++], "5 std::cout< 0) wanted[1] = wanted[6] = 1; if (type > 1) wanted[2] = wanted[4] = wanted[7] = 1; std::string header[9] = { "", "Save values", "Redundant save of default values", "Set changed values", "Redundant set default values", "Solve", "Restore values", "Redundant restore values", "Finish up" }; for (int iType = 0; iType < 9; iType++) { if (!wanted[iType]) continue; int n = 0; int iLine; for (iLine = 0; iLine < numberLines; iLine++) { if (line[iLine][0] == '0' + iType) { if (!n && header[iType] != "") fprintf(fp, "\n // %s\n\n", header[iType].c_str()); n++; // skip save and clp as cloned if (!strstr(line[iLine], "save") || (!strstr(line[iLine], "clpMo") && !strstr(line[iLine], "_Osi"))) fprintf(fp, "%s\n", line[iLine] + 1); } } } fclose(fp); printf("C++ file written to %s\n", fileName); } /* Version 1.00.00 November 16 2005. This is to stop me (JJF) messing about too much. Tuning changes should be noted here. The testing next version may be activated by CBC_NEXT_VERSION This applies to OsiClp, Clp etc Version 1.00.01 November 24 2005 Added several classes for advanced users. This can't affect code (if you don't use it) Made some tiny changes (for N way branching) which should not change anything. CbcNWay object class - for N way branching this also allows use of CbcConsequence class. CbcBranchAllDifferent object class - for branching on general integer variables to stop them having same value so branches are x >= y+1 and x <= y-1. Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly) and CglStored which just has a list of cuts which can be activated. Modified preprocess option to SOS Version 1.00.02 December 9 2005 Added use of CbcStrategy to do clean preprocessing Added use of referenceSolver for cleaner repetition of Cbc Version 1.01.00 February 2 2006 Added first try at Ampl interface Version 1.04 June 2007 Goes parallel Version 2.00 September 2007 Improvements to feaspump Source code changes so up to 2.0 */ Cbc-2.8.12/src/CbcGenSolvers.cpp0000644000076600007660000001565112131315050014742 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenSolvers.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ /* This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers. */ #include "CbcConfig.h" #include "CoinPragma.hpp" #include "OsiSolverInterface.hpp" /* Include class definitions for the solvers that are available. If CBC_DEFAULT_SOLVER is not defined in CbcConfig.h, set it to the first available solver. NOTE: Processing of keyword parameters is made case-independent by forcing lower case comparison. Maps, on the other hand, are case-sensitive. The solver names given here must contain only lower case letters and must match the keywords used when defining the keywords for the solver parameter. */ #ifdef COIN_HAS_CLP # include "OsiClpSolverInterface.hpp" # ifndef CBC_DEFAULT_SOLVER # define CBC_DEFAULT_SOLVER "clp" # endif #endif #ifdef COIN_HAS_CPX # include "OsiCpxSolverInterface.hpp" # ifndef CBC_DEFAULT_SOLVER # define CBC_DEFAULT_SOLVER "cpx" # endif #endif #ifdef COIN_HAS_DYLP # include "OsiDylpSolverInterface.hpp" # ifndef CBC_DEFAULT_SOLVER # define CBC_DEFAULT_SOLVER "dylp" # endif #endif #ifdef COIN_HAS_GLPK # include "OsiGlpkSolverInterface.hpp" # ifndef CBC_DEFAULT_SOLVER # define CBC_DEFAULT_SOLVER "glpk" # endif #endif #ifdef COIN_HAS_MSK # include "OsiMskSolverInterface.hpp" # ifndef CBC_DEFAULT_SOLVER # define CBC_DEFAULT_SOLVER "msk" # endif #endif #ifdef COIN_HAS_SPX # include "OsiSpxSolverInterface.hpp" # ifndef CBC_DEFAULT_SOLVER # define CBC_DEFAULT_SOLVER "spx" # endif #endif #include "CoinParam.hpp" #include "CbcModel.hpp" #include "CbcGenCtlBlk.hpp" #include "CbcGenParam.hpp" #include "CbcGenCbcParam.hpp" #include "CbcGenOsiParam.hpp" namespace { char svnid[] = "$Id: CbcGenSolvers.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } /* Unnamed local namespace to hide the data structures used to maintain the vector of OsiSolverInterface objects. */ namespace { /* Data types for a vector of OsiSolverInterface objects. */ typedef std::map solverMap_t ; typedef solverMap_t::const_iterator solverMapIter_t ; /* The solver map. */ solverMap_t solvers ; } // end unnamed local namespace namespace CbcGenSolvers { /* Create a vector of solver prototypes and establish a default solver. Creating multiple solvers is moderately expensive; if you're not interested in experimenting with solvers other than clp, you're likely better off just working with the cbc main program (CoinSolve.cpp). The businesss with CBC_DEFAULT_SOLVER will select the first available solver as the default, unless overridden at compile time. */ OsiSolverInterface *setupSolvers () { /* Populate the vector of OsiSolverInterface objects. */ # ifdef COIN_HAS_CLP solvers["clp"] = new OsiClpSolverInterface ; # endif # ifdef COIN_HAS_CPX solvers["cpx"] = new OsiCpxSolverInterface ; # endif # ifdef COIN_HAS_DYLP solvers["dylp"] = new OsiDylpSolverInterface ; # endif # ifdef COIN_HAS_GLPK solvers["glpk"] = new OsiGlpkSolverInterface ; # endif # ifdef COIN_HAS_MSK solvers["msk"] = new OsiMskSolverInterface ; # endif # ifdef COIN_HAS_SPX solvers["spx"] = new OsiSpxSolverInterface ; # endif /* Set the standard default values in each solver. */ for (solverMapIter_t solverIter = solvers.begin() ; solverIter != solvers.end() ; solverIter++) { OsiSolverInterface *osi = solverIter->second ; osi->messageHandler()->setLogLevel(0) ; CbcOsiParamUtils::setOsiSolverInterfaceDefaults(osi) ; } /* If we don't have a default solver, we're deeply confused. */ OsiSolverInterface *dflt_solver = solvers[CBC_DEFAULT_SOLVER] ; if (dflt_solver) { std::cout << "Default solver is " << CBC_DEFAULT_SOLVER << std::endl ; } else { std::cerr << "No solvers!" << std::endl ; } return (dflt_solver) ; } /* Cleanup routine to delete the vector of OsiSolverInterface objects. */ void deleteSolvers () { for (solverMapIter_t solverIter = solvers.begin() ; solverIter != solvers.end() ; solverIter++) { if (solverIter->second) delete solverIter->second ; } } /* The `push' routine for the solver parameter. The basic operation is to clone the requested solver and assign it to the current CbcModel object. */ int changeCbcSolver (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; CoinMessageHandler *msghandler = ctlBlk->messageHandler() ; /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* Try to locate the solver specified by the user. */ const std::string solverName = genParam->kwdVal() ; OsiSolverInterface *protoOsi = solvers[solverName] ; if (protoOsi == 0) { std::cerr << "Can't find solver \"" << solverName << "\" in the solvers vector." << std::endl ; return (retval) ; } ctlBlk->dfltSolver_ = protoOsi ; /* We have a solver. */ ctlBlk->message(CBCGEN_NEW_SOLVER) << solverName << CoinMessageEol ; CbcModel *model = ctlBlk->model_ ; assert (model != 0) ; OsiSolverInterface *newOsi = protoOsi->clone() ; model->assignSolver(newOsi) ; return (0) ; } /* This routine sets up a solver parameter object. It doesn't initialise the object being acted upon (a CbcGenCtlBlk); that's done back in the calling routine where we're setting up the cbc-generic parameter vector. */ void setupSolverParam (CbcGenParam &solverParam) { /* Basic setup: parameter type, name, parameter code. */ solverParam.setType(CoinParam::coinParamKwd) ; solverParam.setName("solver") ; solverParam.setParamCode(CbcGenParam::SOLVER) ; /* Add the solvers and set the default value. */ for (solverMapIter_t solverIter = solvers.begin() ; solverIter != solvers.end() ; solverIter++) { solverParam.appendKwd(solverIter->first) ; } solverParam.setKwdVal(CBC_DEFAULT_SOLVER) ; solverParam.setDisplay(true) ; solverParam.setPushFunc(changeCbcSolver) ; /* And add the help strings. */ solverParam.setShortHelp("Specify underlying LP solver") ; solverParam.setLongHelp( "Select the underlying LP solver that will be used to solve the continuous relaxations of subproblems." ) ; } } // end namespace CbcGenSolvers Cbc-2.8.12/src/CbcBranchingObject.hpp0000644000076600007660000001751312131315050015701 0ustar coincoin// $Id: CbcBranchingObject.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/12/2009 carved from CbcBranchBase #ifndef CbcBranchingObject_H #define CbcBranchingObject_H #include #include #include "CbcBranchBase.hpp" #include "OsiBranchingObject.hpp" // The types of objects that will be derived from this class. enum CbcBranchObjType { SimpleIntegerBranchObj = 100, SimpleIntegerDynamicPseudoCostBranchObj = 101, CliqueBranchObj = 102, LongCliqueBranchObj = 103, SoSBranchObj = 104, NWayBranchObj = 105, FollowOnBranchObj = 106, DummyBranchObj = 107, GeneralDepthBranchObj = 108, OneGeneralBranchingObj = 110, CutBranchingObj = 200, LotsizeBranchObj = 300, DynamicPseudoCostBranchObj = 400 }; /** \brief Abstract branching object base class Now just difference with OsiBranchingObject In the abstract, an CbcBranchingObject contains instructions for how to branch. We want an abstract class so that we can describe how to branch on simple objects (e.g., integers) and more exotic objects (e.g., cliques or hyperplanes). The #branch() method is the crucial routine: it is expected to be able to step through a set of branch arms, executing the actions required to create each subproblem in turn. The base class is primarily virtual to allow for a wide range of problem modifications. See CbcObject for an overview of the three classes (CbcObject, CbcBranchingObject, and CbcBranchDecision) which make up cbc's branching model. */ class CbcBranchingObject : public OsiBranchingObject { public: /// Default Constructor CbcBranchingObject (); /// Constructor CbcBranchingObject (CbcModel * model, int variable, int way , double value); /// Copy constructor CbcBranchingObject ( const CbcBranchingObject &); /// Assignment operator CbcBranchingObject & operator=( const CbcBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const = 0; /// Destructor virtual ~CbcBranchingObject (); /** Some branchingObjects may claim to be able to skip strong branching. If so they have to fill in CbcStrongInfo. The object mention in incoming CbcStrongInfo must match. Returns nonzero if skip is wanted */ virtual int fillStrongInfo( CbcStrongInfo & ) { return 0; } /// Reset number of branches left to original inline void resetNumberBranchesLeft() { branchIndex_ = 0; } /// Set number of branches to do inline void setNumberBranches(int value) { branchIndex_ = 0; numberBranches_ = value; } /** \brief Execute the actions required to branch, as specified by the current state of the branching object, and advance the object's state. Mainly for diagnostics, whether it is true branch or strong branching is also passed. Returns change in guessed objective on next branch */ virtual double branch() = 0; /** \brief Execute the actions required to branch, as specified by the current state of the branching object, and advance the object's state. Mainly for diagnostics, whether it is true branch or strong branching is also passed. Returns change in guessed objective on next branch */ virtual double branch(OsiSolverInterface * ) { return branch(); } /** Update bounds in solver as in 'branch' and update given bounds. branchState is -1 for 'down' +1 for 'up' */ virtual void fix(OsiSolverInterface * , double * , double * , int ) const {} /** Change (tighten) bounds in object to reflect bounds in solver. Return true if now fixed */ virtual bool tighten(OsiSolverInterface * ) {return false;} /** Reset every information so that the branching object appears to point to the previous child. This method does not need to modify anything in any solver. */ virtual void previousBranch() { assert(branchIndex_ > 0); branchIndex_--; way_ = -way_; } using OsiBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print() const {} /** \brief Index identifying the associated CbcObject within its class. The name is misleading, and typically the index will not refer directly to a variable. Rather, it identifies an CbcObject within the class of similar CbcObjects E.g., for an CbcSimpleInteger, variable() is the index of the integer variable in the set of integer variables (not the index of the variable in the set of all variables). */ inline int variable() const { return variable_; } /** Get the state of the branching object Returns a code indicating the active arm of the branching object. The precise meaning is defined in the derived class. \sa #way_ */ inline int way() const { return way_; } /** Set the state of the branching object. See #way() */ inline void way(int way) { way_ = way; } /// update model inline void setModel(CbcModel * model) { model_ = model; } /// Return model inline CbcModel * model() const { return model_; } /// Return pointer back to object which created inline CbcObject * object() const { return originalCbcObject_; } /// Set pointer back to object which created inline void setOriginalObject(CbcObject * object) { originalCbcObject_ = object; } // Methods used in heuristics /** Return the type (an integer identifier) of \c this. See definition of CbcBranchObjType above for possibilities */ virtual CbcBranchObjType type() const = 0; /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const { const CbcBranchingObject* br = dynamic_cast(brObj); return variable() - br->variable(); } /** Compare the \c this with \c brObj. \c this and \c brObj must be of the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false) = 0; protected: /// The model that owns this branching object CbcModel * model_; /// Pointer back to object which created CbcObject * originalCbcObject_; /// Branching variable (0 is first integer) int variable_; // was - Way to branch - -1 down (first), 1 up, -2 down (second), 2 up (second) /** The state of the branching object. Specifies the active arm of the branching object. Coded as -1 to take the `down' arm, +1 for the `up' arm. `Down' and `up' are defined based on the natural meaning (floor and ceiling, respectively) for a simple integer. The precise meaning is defined in the derived class. */ int way_; }; #endif Cbc-2.8.12/src/CbcFathomDynamicProgramming.cpp0000644000076600007660000010440612130105453017601 0ustar coincoin/* $Id: CbcFathomDynamicProgramming.cpp 1888 2013-04-06 20:52:59Z stefan $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcFathomDynamicProgramming.hpp" #include "CoinHelperFunctions.hpp" #include "CoinPackedMatrix.hpp" #include "CoinSort.hpp" // Default Constructor CbcFathomDynamicProgramming::CbcFathomDynamicProgramming() : CbcFathom(), size_(0), type_(-1), cost_(NULL), back_(NULL), lookup_(NULL), indices_(NULL), numberActive_(0), maximumSizeAllowed_(1000000), startBit_(NULL), numberBits_(NULL), rhs_(NULL), coefficients_(NULL), target_(0), numberNonOne_(0), bitPattern_(0), algorithm_(-1) { } // Constructor from model CbcFathomDynamicProgramming::CbcFathomDynamicProgramming(CbcModel & model) : CbcFathom(model), cost_(NULL), back_(NULL), lookup_(NULL), indices_(NULL), numberActive_(0), maximumSizeAllowed_(1000000), startBit_(NULL), numberBits_(NULL), rhs_(NULL), coefficients_(NULL), target_(0), numberNonOne_(0), bitPattern_(0), algorithm_(-1) { type_ = checkPossible(); } // Destructor CbcFathomDynamicProgramming::~CbcFathomDynamicProgramming () { gutsOfDelete(); } // Does deleteions void CbcFathomDynamicProgramming::gutsOfDelete() { delete [] cost_; delete [] back_; delete [] lookup_; delete [] indices_; delete [] startBit_; delete [] numberBits_; delete [] rhs_; delete [] coefficients_; cost_ = NULL; back_ = NULL; lookup_ = NULL; indices_ = NULL; startBit_ = NULL; numberBits_ = NULL; rhs_ = NULL; coefficients_ = NULL; } // Clone CbcFathom * CbcFathomDynamicProgramming::clone() const { return new CbcFathomDynamicProgramming(*this); } // Copy constructor CbcFathomDynamicProgramming::CbcFathomDynamicProgramming(const CbcFathomDynamicProgramming & rhs) : CbcFathom(rhs), size_(rhs.size_), type_(rhs.type_), cost_(NULL), back_(NULL), lookup_(NULL), indices_(NULL), numberActive_(rhs.numberActive_), maximumSizeAllowed_(rhs.maximumSizeAllowed_), startBit_(NULL), numberBits_(NULL), rhs_(NULL), coefficients_(NULL), target_(rhs.target_), numberNonOne_(rhs.numberNonOne_), bitPattern_(rhs.bitPattern_), algorithm_(rhs.algorithm_) { if (size_) { cost_ = CoinCopyOfArray(rhs.cost_, size_); back_ = CoinCopyOfArray(rhs.back_, size_); int numberRows = model_->getNumRows(); lookup_ = CoinCopyOfArray(rhs.lookup_, numberRows); startBit_ = CoinCopyOfArray(rhs.startBit_, numberActive_); indices_ = CoinCopyOfArray(rhs.indices_, numberActive_); numberBits_ = CoinCopyOfArray(rhs.numberBits_, numberActive_); rhs_ = CoinCopyOfArray(rhs.rhs_, numberActive_); coefficients_ = CoinCopyOfArray(rhs.coefficients_, numberActive_); } } // Returns type int CbcFathomDynamicProgramming::checkPossible(int allowableSize) { algorithm_ = -1; assert(model_->solver()); OsiSolverInterface * solver = model_->solver(); const CoinPackedMatrix * matrix = solver->getMatrixByCol(); int numberIntegers = model_->numberIntegers(); int numberColumns = solver->getNumCols(); size_ = 0; if (numberIntegers != numberColumns) return -1; // can't do dynamic programming const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * rowUpper = solver->getRowUpper(); int numberRows = model_->getNumRows(); int i; // First check columns to see if possible double * rhs = new double [numberRows]; CoinCopyN(rowUpper, numberRows, rhs); // Column copy const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); bool bad = false; /* It is just possible that we could say okay as variables may get fixed but seems unlikely */ for (i = 0; i < numberColumns; i++) { int j; double lowerValue = lower[i]; assert (lowerValue == floor(lowerValue)); for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; double value = element[j]; if (upper[i] > lowerValue && (value <= 0.0 || value != floor(value))) bad = true; if (lowerValue) rhs[iRow] -= lowerValue * value; } } // check possible (at present do not allow covering) int numberActive = 0; bool infeasible = false; bool saveBad = bad; for (i = 0; i < numberRows; i++) { if (rhs[i] < 0) infeasible = true; else if (rhs[i] > 1.0e5 || fabs(rhs[i] - floor(rhs[i] + 0.5)) > 1.0e-7) bad = true; else if (rhs[i] > 0.0) numberActive++; } if (bad || infeasible) { delete [] rhs; if (!saveBad && infeasible) return -2; else return -1; } // check size of array needed double size = 1.0; double check = COIN_INT_MAX; for (i = 0; i < numberRows; i++) { int n = static_cast (floor(rhs[i] + 0.5)); if (n) { n++; // allow for 0,1... n if (numberActive != 1) { // power of 2 int iBit = 0; int k = n; k &= ~1; while (k) { iBit++; k &= ~(1 << iBit); } // See if exact power if (n != (1 << iBit)) { // round up to next power of 2 n = 1 << (iBit + 1); } size *= n; if (size >= check) break; } else { size = n; // just one constraint } } } // set size needed if (size >= check) size_ = COIN_INT_MAX; else size_ = static_cast (size); int n01 = 0; int nbadcoeff = 0; // See if we can tighten bounds for (i = 0; i < numberColumns; i++) { int j; double lowerValue = lower[i]; double gap = upper[i] - lowerValue; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; double value = element[j]; if (value != 1.0) nbadcoeff++; if (gap*value > rhs[iRow] + 1.0e-8) gap = rhs[iRow] / value; } gap = lowerValue + floor(gap + 1.0e-7); if (gap < upper[i]) solver->setColUpper(i, gap); if (gap <= 1.0) n01++; } if (allowableSize && size_ <= allowableSize) { if (n01 == numberColumns && !nbadcoeff) algorithm_ = 0; // easiest else algorithm_ = 1; } if (allowableSize && size_ <= allowableSize) { numberActive_ = numberActive; indices_ = new int [numberActive_]; cost_ = new double [size_]; CoinFillN(cost_, size_, COIN_DBL_MAX); // but do nothing is okay cost_[0] = 0.0; back_ = new int[size_]; CoinFillN(back_, size_, -1); startBit_ = new int[numberActive_]; numberBits_ = new int[numberActive_]; lookup_ = new int [numberRows]; rhs_ = new int [numberActive_]; numberActive = 0; int kBit = 0; for (i = 0; i < numberRows; i++) { int n = static_cast (floor(rhs[i] + 0.5)); if (n) { lookup_[i] = numberActive; rhs_[numberActive] = n; startBit_[numberActive] = kBit; n++; // allow for 0,1... n int iBit = 0; // power of 2 int k = n; k &= ~1; while (k) { iBit++; k &= ~(1 << iBit); } // See if exact power if (n != (1 << iBit)) { // round up to next power of 2 iBit++; } if (numberActive != 1) { n = 1 << iBit; size *= n; if (size >= check) break; } else { size = n; // just one constraint } numberBits_[numberActive++] = iBit; kBit += iBit; } else { lookup_[i] = -1; } } const double * rowLower = solver->getRowLower(); if (algorithm_ == 0) { // rhs 1 and coefficients 1 // Get first possible solution for printing target_ = -1; int needed = 0; int numberActive = 0; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) { if (rowLower[i] == rowUpper[i]) { needed += 1 << numberActive; numberActive++; } } } for (i = 0; i < size_; i++) { if ((i&needed) == needed) { break; } } target_ = i; } else { coefficients_ = new int[numberActive_]; // If not too many general rhs then we can be more efficient numberNonOne_ = 0; for (i = 0; i < numberActive_; i++) { if (rhs_[i] != 1) numberNonOne_++; } if (numberNonOne_*2 < numberActive_) { // put rhs >1 every second int * permute = new int[numberActive_]; int * temp = new int[numberActive_]; // try different ways int k = 0; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0 && rhs_[newRow] > 1) { permute[newRow] = k; k += 2; } } // adjust so k points to last k -= 2; // and now rest int k1 = 1; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0 && rhs_[newRow] == 1) { permute[newRow] = k1; k1++; if (k1 <= k) k1++; } } for (i = 0; i < numberActive_; i++) { int put = permute[i]; temp[put] = rhs_[i]; } memcpy(rhs_, temp, numberActive_*sizeof(int)); for (i = 0; i < numberActive_; i++) { int put = permute[i]; temp[put] = numberBits_[i]; } memcpy(numberBits_, temp, numberActive_*sizeof(int)); k = 0; for (i = 0; i < numberActive_; i++) { startBit_[i] = k; k += numberBits_[i]; } for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) lookup_[i] = permute[newRow]; } delete [] permute; delete [] temp; // mark new method algorithm_ = 2; } // Get first possible solution for printing target_ = -1; int needed = 0; int * lower2 = new int[numberActive_]; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) { int gap = static_cast (rowUpper[i] - CoinMax(0.0, rowLower[i])); lower2[newRow] = rhs_[newRow] - gap; int numberBits = numberBits_[newRow]; int startBit = startBit_[newRow]; if (numberBits == 1 && !gap) { needed |= 1 << startBit; } } } for (i = 0; i < size_; i++) { if ((i&needed) == needed) { // this one may do bool good = true; for (int kk = 0; kk < numberActive_; kk++) { int numberBits = numberBits_[kk]; int startBit = startBit_[kk]; int size = 1 << numberBits; int start = 1 << startBit; int mask = start * (size - 1); int level = (i & mask) >> startBit; if (level < lower2[kk]) { good = false; break; } } if (good) { break; } } } delete [] lower2; target_ = i; } } delete [] rhs; if (allowableSize && size_ > allowableSize) { COIN_DETAIL_PRINT(printf("Too large - need %d entries x 8 bytes\n", size_)); return -1; // too big } else { return algorithm_; } } // Resets stuff if model changes void CbcFathomDynamicProgramming::resetModel(CbcModel * model) { model_ = model; type_ = checkPossible(); } int CbcFathomDynamicProgramming::fathom(double * & betterSolution) { int returnCode = 0; int type = checkPossible(maximumSizeAllowed_); assert (type != -1); if (type == -2) { // infeasible (so complete search done) return 1; } if (algorithm_ >= 0) { OsiSolverInterface * solver = model_->solver(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * objective = solver->getObjCoefficients(); double direction = solver->getObjSense(); const CoinPackedMatrix * matrix = solver->getMatrixByCol(); // Column copy const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = model_->getNumRows(); int numberColumns = solver->getNumCols(); double offset; solver->getDblParam(OsiObjOffset, offset); double fixedObj = -offset; int i; // may be possible double bestAtTarget = COIN_DBL_MAX; for (i = 0; i < numberColumns; i++) { if (size_ > 10000000 && (i % 100) == 0) COIN_DETAIL_PRINT(printf("column %d\n", i)); double lowerValue = lower[i]; assert (lowerValue == floor(lowerValue)); double cost = direction * objective[i]; fixedObj += lowerValue * cost; int gap = static_cast (upper[i] - lowerValue); CoinBigIndex start = columnStart[i]; tryColumn(columnLength[i], row + start, element + start, cost, gap); if (cost_[target_] < bestAtTarget) { if (model_->messageHandler()->logLevel() > 1) printf("At column %d new best objective of %g\n", i, cost_[target_]); bestAtTarget = cost_[target_]; } } returnCode = 1; int needed = 0; double bestValue = COIN_DBL_MAX; int iBest = -1; if (algorithm_ == 0) { int numberActive = 0; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) { if (rowLower[i] == rowUpper[i]) { needed += 1 << numberActive; numberActive++; } } } for (i = 0; i < size_; i++) { if ((i&needed) == needed) { // this one will do if (cost_[i] < bestValue) { bestValue = cost_[i]; iBest = i; } } } } else { int * lower = new int[numberActive_]; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) { int gap = static_cast (rowUpper[i] - CoinMax(0.0, rowLower[i])); lower[newRow] = rhs_[newRow] - gap; int numberBits = numberBits_[newRow]; int startBit = startBit_[newRow]; if (numberBits == 1 && !gap) { needed |= 1 << startBit; } } } for (i = 0; i < size_; i++) { if ((i&needed) == needed) { // this one may do bool good = true; for (int kk = 0; kk < numberActive_; kk++) { int numberBits = numberBits_[kk]; int startBit = startBit_[kk]; int size = 1 << numberBits; int start = 1 << startBit; int mask = start * (size - 1); int level = (i & mask) >> startBit; if (level < lower[kk]) { good = false; break; } } if (good && cost_[i] < bestValue) { bestValue = cost_[i]; iBest = i; } } } delete [] lower; } if (bestValue < COIN_DBL_MAX) { bestValue += fixedObj; if (model_->messageHandler()->logLevel() > 1) printf("Can get solution of %g\n", bestValue); if (bestValue < model_->getMinimizationObjValue()) { // set up solution betterSolution = new double[numberColumns]; memcpy(betterSolution, lower, numberColumns*sizeof(double)); while (iBest > 0) { int n = decodeBitPattern(iBest - back_[iBest], indices_, numberRows); // Search for cheapest double bestCost = COIN_DBL_MAX; int iColumn = -1; for (i = 0; i < numberColumns; i++) { if (n == columnLength[i]) { bool good = true; for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; double value = element[j]; int iValue = static_cast (value); if (iValue != indices_[iRow]) { good = false; break; } } if (good && objective[i] < bestCost && betterSolution[i] < upper[i]) { bestCost = objective[i]; iColumn = i; } } } assert (iColumn >= 0); betterSolution[iColumn]++; assert (betterSolution[iColumn] <= upper[iColumn]); iBest = back_[iBest]; } } // paranoid check double * rowActivity = new double [numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); for (i = 0; i < numberColumns; i++) { int j; double value = betterSolution[i]; if (value) { for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } // check was feasible bool feasible = true; for (i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i]) { if (rowActivity[i] < rowLower[i] - 1.0e-8) feasible = false; } else if (rowActivity[i] > rowUpper[i]) { if (rowActivity[i] > rowUpper[i] + 1.0e-8) feasible = false; } } if (feasible) { if (model_->messageHandler()->logLevel() > 0) printf("** good solution of %g by dynamic programming\n", bestValue); } delete [] rowActivity; } gutsOfDelete(); } return returnCode; } /* Tries a column returns true if was used in making any changes. */ bool CbcFathomDynamicProgramming::tryColumn(int numberElements, const int * rows, const double * coefficients, double cost, int upper) { bool touched = false; int n = 0; if (algorithm_ == 0) { for (int j = 0; j < numberElements; j++) { int iRow = rows[j]; double value = coefficients[j]; int newRow = lookup_[iRow]; if (newRow < 0 || value > rhs_[newRow]) { n = 0; break; //can't use } else { indices_[n++] = newRow; } } if (n && upper) { touched = addOneColumn0(n, indices_, cost); } } else { for (int j = 0; j < numberElements; j++) { int iRow = rows[j]; double value = coefficients[j]; int iValue = static_cast (value); int newRow = lookup_[iRow]; if (newRow < 0 || iValue > rhs_[newRow]) { n = 0; break; //can't use } else { coefficients_[n] = iValue; indices_[n++] = newRow; if (upper*iValue > rhs_[newRow]) { upper = rhs_[newRow] / iValue; } } } if (n) { if (algorithm_ == 1) { for (int k = 1; k <= upper; k++) { bool t = addOneColumn1(n, indices_, coefficients_, cost); if (t) touched = true; } } else { CoinSort_2(indices_, indices_ + n, coefficients_); for (int k = 1; k <= upper; k++) { bool t = addOneColumn1A(n, indices_, coefficients_, cost); if (t) touched = true; } } } } return touched; } /* Adds one column if type 0, returns true if was used in making any changes */ bool CbcFathomDynamicProgramming::addOneColumn0(int numberElements, const int * rows, double cost) { // build up mask int mask = 0; int i; for (i = 0; i < numberElements; i++) { int iRow = rows[i]; mask |= 1 << iRow; } bitPattern_ = mask; i = size_ - 1 - mask; bool touched = false; while (i >= 0) { int kMask = i & mask; if (kMask == 0) { double thisCost = cost_[i]; if (thisCost != COIN_DBL_MAX) { // possible double newCost = thisCost + cost; int next = i + mask; if (cost_[next] > newCost) { cost_[next] = newCost; back_[next] = i; touched = true; } } i--; } else { // we can skip some int k = (i&~mask); #ifdef CBC_DEBUG for (int j = i - 1; j > k; j--) { int jMask = j & mask; assert (jMask != 0); } #endif i = k; } } return touched; } /* Adds one attempt of one column of type 1, returns true if was used in making any changes. At present the user has to call it once for each possible value */ bool CbcFathomDynamicProgramming::addOneColumn1(int numberElements, const int * rows, const int * coefficients, double cost) { /* build up masks. a) mask for 1 rhs b) mask for addition c) mask so adding will overflow d) individual masks */ int mask1 = 0; int maskAdd = 0; int mask2 = 0; int i; int n2 = 0; int mask[40]; int adjust[40]; assert (numberElements <= 40); for (i = 0; i < numberElements; i++) { int iRow = rows[i]; int numberBits = numberBits_[iRow]; int startBit = startBit_[iRow]; if (numberBits == 1) { mask1 |= 1 << startBit; maskAdd |= 1 << startBit; mask2 |= 1 << startBit; } else { int value = coefficients[i]; int size = 1 << numberBits; int start = 1 << startBit; assert (value < size); maskAdd |= start * value; int gap = size - rhs_[iRow] - 1; assert (gap >= 0); int hi2 = rhs_[iRow] - value; if (hi2 < size - 1) hi2++; adjust[n2] = start * hi2; mask2 += start * gap; mask[n2++] = start * (size - 1); } } bitPattern_ = maskAdd; i = size_ - 1 - maskAdd; bool touched = false; while (i >= 0) { int kMask = i & mask1; if (kMask == 0) { bool good = true; for (int kk = n2 - 1; kk >= 0; kk--) { int iMask = mask[kk]; int jMask = iMask & mask2; int kkMask = iMask & i; kkMask += jMask; if (kkMask > iMask) { // we can skip some int k = (i&~iMask); k |= adjust[kk]; #ifdef CBC_DEBUG for (int j = i - 1; j > k; j--) { int jMask = j & mask1; if (jMask == 0) { bool good = true; for (int kk = n2 - 1; kk >= 0; kk--) { int iMask = mask[kk]; int jMask = iMask & mask2; int kkMask = iMask & i; kkMask += jMask; if (kkMask > iMask) { good = false; break; } } assert (!good); } } #endif i = k; good = false; break; } } if (good) { double thisCost = cost_[i]; if (thisCost != COIN_DBL_MAX) { // possible double newCost = thisCost + cost; int next = i + maskAdd; if (cost_[next] > newCost) { cost_[next] = newCost; back_[next] = i; touched = true; } } } i--; } else { // we can skip some // we can skip some int k = (i&~mask1); #ifdef CBC_DEBUG for (int j = i - 1; j > k; j--) { int jMask = j & mask1; assert (jMask != 0); } #endif i = k; } } return touched; } /* Adds one attempt of one column of type 1, returns true if was used in making any changes. At present the user has to call it once for each possible value This version is when there are enough 1 rhs to do faster */ bool CbcFathomDynamicProgramming::addOneColumn1A(int numberElements, const int * rows, const int * coefficients, double cost) { /* build up masks. a) mask for 1 rhs b) mask for addition c) mask so adding will overflow d) mask for non 1 rhs */ int maskA = 0; int maskAdd = 0; int maskC = 0; int maskD = 0; int i; for (i = 0; i < numberElements; i++) { int iRow = rows[i]; int numberBits = numberBits_[iRow]; int startBit = startBit_[iRow]; if (numberBits == 1) { maskA |= 1 << startBit; maskAdd |= 1 << startBit; } else { int value = coefficients[i]; int size = 1 << numberBits; int start = 1 << startBit; assert (value < size); maskAdd |= start * value; int gap = size - rhs_[iRow] + value - 1; assert (gap > 0 && gap <= size - 1); maskC |= start * gap; maskD |= start * (size - 1); } } bitPattern_ = maskAdd; int maskDiff = maskD - maskC; i = size_ - 1 - maskAdd; bool touched = false; if (!maskD) { // Just ones while (i >= 0) { int kMask = i & maskA; if (kMask == 0) { double thisCost = cost_[i]; if (thisCost != COIN_DBL_MAX) { // possible double newCost = thisCost + cost; int next = i + maskAdd; if (cost_[next] > newCost) { cost_[next] = newCost; back_[next] = i; touched = true; } } i--; } else { // we can skip some int k = (i&~maskA); i = k; } } } else { // More general while (i >= 0) { int kMask = i & maskA; if (kMask == 0) { int added = i & maskD; // just bits belonging to non 1 rhs added += maskC; // will overflow mask if bad added &= (~maskD); if (added == 0) { double thisCost = cost_[i]; if (thisCost != COIN_DBL_MAX) { // possible double newCost = thisCost + cost; int next = i + maskAdd; if (cost_[next] > newCost) { cost_[next] = newCost; back_[next] = i; touched = true; } } i--; } else { // we can skip some int k = i & ~ maskD; // clear all // Put back enough - but only below where we are int kk = (numberNonOne_ << 1) - 2; assert (rhs_[kk] > 1); int iMask = 0; for (; kk >= 0; kk -= 2) { iMask = 1 << startBit_[kk+1]; if ((added&iMask) != 0) { iMask--; break; } } assert (kk >= 0); iMask &= maskDiff; k |= iMask; assert (k < i); i = k; } } else { // we can skip some int k = (i&~maskA); i = k; } } } return touched; } // update model void CbcFathomDynamicProgramming::setModel(CbcModel * model) { model_ = model; type_ = checkPossible(); } // Gets bit pattern from original column int CbcFathomDynamicProgramming::bitPattern(int numberElements, const int * rows, const int * coefficients) { int i; int mask = 0; switch (algorithm_) { // just ones case 0: for (i = 0; i < numberElements; i++) { int iRow = rows[i]; iRow = lookup_[iRow]; if (iRow >= 0) mask |= 1 << iRow; } break; // case 1: case 2: for (i = 0; i < numberElements; i++) { int iRow = rows[i]; iRow = lookup_[iRow]; if (iRow >= 0) { int startBit = startBit_[iRow]; int value = coefficients[i]; int start = 1 << startBit; mask |= start * value; } } break; } return mask; } // Fills in original column (dense) from bit pattern int CbcFathomDynamicProgramming::decodeBitPattern(int bitPattern, int * values, int numberRows) { int i; int n = 0; switch (algorithm_) { // just ones case 0: for (i = 0; i < numberRows; i++) { values[i] = 0; int iRow = lookup_[i]; if (iRow >= 0) { if ((bitPattern&(1 << iRow)) != 0) { values[i] = 1; n++; } } } break; // case 1: case 2: for (i = 0; i < numberRows; i++) { values[i] = 0; int iRow = lookup_[i]; if (iRow >= 0) { int startBit = startBit_[iRow]; int numberBits = numberBits_[iRow]; int iValue = bitPattern >> startBit; iValue &= ((1 << numberBits) - 1); if (iValue) { values[i] = iValue; n++; } } } break; } return n; } Cbc-2.8.12/src/CbcBranchToFixLots.hpp0000644000076600007660000000606612131315050015671 0ustar coincoin// $Id: CbcBranchToFixLots.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/13/2009-- carved out of CbcBranchCut #ifndef CbcBranchToFixLots_H #define CbcBranchToFixLots_H #include "CbcBranchCut.hpp" #include "CbcBranchBase.hpp" #include "OsiRowCut.hpp" #include "CoinPackedMatrix.hpp" /** Define a branch class that branches so that one way variables are fixed while the other way cuts off that solution. a) On reduced cost b) When enough ==1 or <=1 rows have been satisfied (not fixed - satisfied) */ class CbcBranchToFixLots : public CbcBranchCut { public: // Default Constructor CbcBranchToFixLots (); /** Useful constructor - passed reduced cost tolerance and fraction we would like fixed. Also depth level to do at. Also passed number of 1 rows which when clean triggers fix Always does if all 1 rows cleaned up and number>0 or if fraction columns reached Also whether to create branch if can't reach fraction. */ CbcBranchToFixLots (CbcModel * model, double djTolerance, double fractionFixed, int depth, int numberClean = 0, const char * mark = NULL, bool alwaysCreate = false); // Copy constructor CbcBranchToFixLots ( const CbcBranchToFixLots &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcBranchToFixLots & operator=( const CbcBranchToFixLots& rhs); // Destructor ~CbcBranchToFixLots (); /** Does a lot of the work, Returns 0 if no good, 1 if dj, 2 if clean, 3 if both FIXME: should use enum or equivalent to make these numbers clearer. */ int shallWe() const; /// Infeasibility for an integer variable - large is 0.5, but also can be infinity when known infeasible. virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; /** \brief Return true if object can take part in normal heuristics */ virtual bool canDoHeuristics() const { return true; } /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Redoes data when sequence numbers change virtual void redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns); protected: /// data /// Reduced cost tolerance i.e. dj has to be >= this before fixed double djTolerance_; /// We only need to make sure this fraction fixed double fractionFixed_; /// Never fix ones marked here char * mark_; /// Matrix by row CoinPackedMatrix matrixByRow_; /// Do if depth multiple of this int depth_; /// number of ==1 rows which need to be clean int numberClean_; /// If true then always create branch bool alwaysCreate_; }; #endif Cbc-2.8.12/src/CbcHeuristicFPump.hpp0000644000076600007660000002657311510742604015605 0ustar coincoin/* $Id: CbcHeuristicFPump.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicFeasibilityPump_H #define CbcHeuristicFeasibilityPump_H #include "CbcHeuristic.hpp" #include "OsiClpSolverInterface.hpp" /** Feasibility Pump class */ class CbcHeuristicFPump : public CbcHeuristic { public: // Default Constructor CbcHeuristicFPump (); // Constructor with model - assumed before cuts CbcHeuristicFPump (CbcModel & model, double downValue = 0.5, bool roundExpensive = false); // Copy constructor CbcHeuristicFPump ( const CbcHeuristicFPump &); // Destructor ~CbcHeuristicFPump (); /// Assignment operator CbcHeuristicFPump & operator=(const CbcHeuristicFPump& rhs); /// Clone virtual CbcHeuristic * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution with better objective value than one passed in Sets solution values if good, sets objective value (only if good) This is called after cuts have been added - so can not add cuts. It may make sense for user to call this outside Branch and Cut to get solution. Or normally is just at root node. * new meanings for when_ - on first try then set back to 1 11 - at end fix all integers at same bound throughout 12 - also fix all integers staying at same internal integral value throughout 13 - also fix all continuous variables staying at same bound throughout 14 - also fix all continuous variables staying at same internal value throughout 15 - as 13 but no internal integers And beyond that, it's apparently possible for the range to be between 21 and 25, in which case it's reduced on entry to solution() to be between 11 and 15 and allSlack is set to true. Then, if we're not processing general integers, we'll use an all-slack basis to solve ... what? Don't see that yet. */ virtual int solution(double & objectiveValue, double * newSolution); /// Set maximum Time (default off) - also sets starttime to current void setMaximumTime(double value); /// Get maximum Time (default 0.0 == time limit off) inline double maximumTime() const { return maximumTime_; } /// Set fake cutoff (default COIN_DBL_MAX == off) inline void setFakeCutoff(double value) { fakeCutoff_ = value; } /// Get fake cutoff (default 0.0 == off) inline double fakeCutoff() const { return fakeCutoff_; } /// Set absolute increment (default 0.0 == off) inline void setAbsoluteIncrement(double value) { absoluteIncrement_ = value; } /// Get absolute increment (default 0.0 == off) inline double absoluteIncrement() const { return absoluteIncrement_; } /// Set relative increment (default 0.0 == off) inline void setRelativeIncrement(double value) { relativeIncrement_ = value; } /// Get relative increment (default 0.0 == off) inline double relativeIncrement() const { return relativeIncrement_; } /// Set default rounding (default 0.5) inline void setDefaultRounding(double value) { defaultRounding_ = value; } /// Get default rounding (default 0.5) inline double defaultRounding() const { return defaultRounding_; } /// Set initial weight (default 0.0 == off) inline void setInitialWeight(double value) { initialWeight_ = value; } /// Get initial weight (default 0.0 == off) inline double initialWeight() const { return initialWeight_; } /// Set weight factor (default 0.1) inline void setWeightFactor(double value) { weightFactor_ = value; } /// Get weight factor (default 0.1) inline double weightFactor() const { return weightFactor_; } /// Set threshold cost for using original cost - even on continuous (default infinity) inline void setArtificialCost(double value) { artificialCost_ = value; } /// Get threshold cost for using original cost - even on continuous (default infinity) inline double artificialCost() const { return artificialCost_; } /// Get iteration to size ratio inline double iterationRatio() const { return iterationRatio_; } /// Set iteration to size ratio inline void setIterationRatio(double value) { iterationRatio_ = value; } /// Set maximum passes (default 100) inline void setMaximumPasses(int value) { maximumPasses_ = value; } /// Get maximum passes (default 100) inline int maximumPasses() const { return maximumPasses_; } /// Set maximum retries (default 1) inline void setMaximumRetries(int value) { maximumRetries_ = value; } /// Get maximum retries (default 1) inline int maximumRetries() const { return maximumRetries_; } /** Set use of multiple solutions and solves 0 - do not reuse solves, do not accumulate integer solutions for local search 1 - do not reuse solves, accumulate integer solutions for local search 2 - reuse solves, do not accumulate integer solutions for local search 3 - reuse solves, accumulate integer solutions for local search If we add 4 then use second form of problem (with extra rows and variables for general integers) At some point (date?), I added And then there are a few bit fields: 4 - something about general integers So my (lh) guess for 4 was at least in the ballpark, but I'll have to rethink 8 entirely (and it may well not mean the same thing as it did when I added that comment. 8 - determines whether we process general integers And on 090831, John added If we add 4 then use second form of problem (with extra rows and variables for general integers) If we add 8 then can run after initial cuts (if no solution) */ inline void setAccumulate(int value) { accumulate_ = value; } /// Get accumulation option inline int accumulate() const { return accumulate_; } /** Set whether to fix variables on known solution 0 - do not fix 1 - fix integers on reduced costs 2 - fix integers on reduced costs but only on entry */ inline void setFixOnReducedCosts(int value) { fixOnReducedCosts_ = value; } /// Get reduced cost option inline int fixOnReducedCosts() const { return fixOnReducedCosts_; } /** Set reduced cost multiplier 1.0 as normal <1.0 (x) - pretend gap is x* actual gap - just for fixing */ inline void setReducedCostMultiplier(double value) { reducedCostMultiplier_ = value; } /// Get reduced cost multiplier inline double reducedCostMultiplier() const { return reducedCostMultiplier_; } protected: // Data /// Start time double startTime_; /// Maximum Cpu seconds double maximumTime_; /** Fake cutoff value. If set then better of real cutoff and this used to add a constraint */ double fakeCutoff_; /// If positive carry on after solution expecting gain of at least this double absoluteIncrement_; /// If positive carry on after solution expecting gain of at least this times objective double relativeIncrement_; /// Default is round up if > this double defaultRounding_; /// Initial weight for true objective double initialWeight_; /// Factor for decreasing weight double weightFactor_; /// Threshold cost for using original cost - even on continuous double artificialCost_; /** If iterationRatio >0 use instead of maximumPasses_ test is iterations > ratio*(2*nrow+ncol) */ double iterationRatio_; /** Reduced cost multiplier 1.0 as normal <1.0 (x) - pretend gap is x* actual gap - just for fixing */ double reducedCostMultiplier_; /// Maximum number of passes int maximumPasses_; /** Maximum number of retries if we find a solution. If negative we clean out used array */ int maximumRetries_; /** Set use of multiple solutions and solves 0 - do not reuse solves, do not accumulate integer solutions for local search 1 - do not reuse solves, accumulate integer solutions for local search 2 - reuse solves, do not accumulate integer solutions for local search 3 - reuse solves, accumulate integer solutions for local search If we add 4 then use second form of problem (with extra rows and variables for general integers) If we do not accumulate solutions then no mini branch and bounds will be done reuse - refers to initial solve after adding in new "cut" If we add 8 then can run after initial cuts (if no solution) */ int accumulate_; /** Set whether to fix variables on known solution 0 - do not fix 1 - fix integers on reduced costs 2 - fix integers on reduced costs but only on entry */ int fixOnReducedCosts_; /// If true round to expensive bool roundExpensive_; private: /** Rounds solution - down if < downValue If roundExpensive then always to more expnsive. returns 0 if current is solution */ int rounds(OsiSolverInterface * solver, double * solution, /*const double * objective, */ int numberIntegers, const int * integerVariable, /*char * pumpPrint,*/int passNumber, /*bool roundExpensive=false,*/ double downValue = 0.5, int *flip = 0); /* note for eagle eyed readers. when_ can now be exotic - <=10 normal */ }; # ifdef COIN_HAS_CLP class CbcDisasterHandler : public OsiClpDisasterHandler { public: /**@name Virtual methods that the derived classe should provide. */ //@{ #ifdef JJF_ZERO /// Into simplex virtual void intoSimplex(); /// Checks if disaster virtual bool check() const ; /// saves information for next attempt virtual void saveInfo(); #endif /// Type of disaster 0 can fix, 1 abort virtual int typeOfDisaster(); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ CbcDisasterHandler(CbcModel * model = NULL); /** Destructor */ virtual ~CbcDisasterHandler(); // Copy CbcDisasterHandler(const CbcDisasterHandler&); // Assignment CbcDisasterHandler& operator=(const CbcDisasterHandler&); /// Clone virtual ClpDisasterHandler * clone() const; //@} /**@name Sets/gets */ //@{ /** set model. */ void setCbcModel(CbcModel * model); /// Get model inline CbcModel * cbcModel() const { return cbcModel_; } //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Pointer to model CbcModel * cbcModel_; //@} }; #endif #endif Cbc-2.8.12/src/CbcCompareDefault.hpp0000644000076600007660000000721312131315050015546 0ustar coincoin// $Id: CbcCompareDefault.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCompareActual #ifndef CbcCompareDefault_H #define CbcCompareDefault_H //############################################################################# /* These are alternative strategies for node traversal. They can take data etc for fine tuning At present the node list is stored as a heap and the "test" comparison function returns true if node y is better than node x. */ #include "CbcNode.hpp" #include "CbcCompareBase.hpp" #include "CbcCompare.hpp" class CbcModel; /* This is an example of a more complex rule with data It is default after first solution If weight is 0.0 then it is computed to hit first solution less 5% */ class CbcCompareDefault : public CbcCompareBase { public: /// Default Constructor CbcCompareDefault () ; /// Constructor with weight CbcCompareDefault (double weight); /// Copy constructor CbcCompareDefault ( const CbcCompareDefault &rhs); /// Assignment operator CbcCompareDefault & operator=( const CbcCompareDefault& rhs); /// Clone virtual CbcCompareBase * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp); ~CbcCompareDefault() ; /* This returns true if weighted value of node y is less than weighted value of node x */ virtual bool test (CbcNode * x, CbcNode * y) ; using CbcCompareBase::newSolution ; /// This allows method to change behavior as it is called /// after each solution virtual bool newSolution(CbcModel * model, double objectiveAtContinuous, int numberInfeasibilitiesAtContinuous) ; /// This allows method to change behavior /// Return true if want tree re-sorted virtual bool every1000Nodes(CbcModel * model, int numberNodes); /* if weight == -1.0 then fewest infeasibilities (before solution) if -2.0 then do breadth first just for first 1000 nodes if -3.0 then depth first before solution */ inline double getWeight() const { return weight_; } inline void setWeight(double weight) { weight_ = weight; } /// Cutoff inline double getCutoff() const { return cutoff_; } inline void setCutoff(double cutoff) { cutoff_ = cutoff; } /// Best possible solution inline double getBestPossible() const { return bestPossible_; } inline void setBestPossible(double bestPossible) { bestPossible_ = bestPossible; } /// Depth above which want to explore first inline void setBreadthDepth(int value) { breadthDepth_ = value; } /// Start dive void startDive(CbcModel * model); /// Clean up diving (i.e. switch off or prepare) void cleanDive(); protected: /// Weight for each infeasibility double weight_; /// Weight for each infeasibility - computed from solution double saveWeight_; /// Cutoff double cutoff_; /// Best possible solution double bestPossible_; /// Number of solutions int numberSolutions_; /// Tree size (at last check) int treeSize_; /// Depth above which want to explore first int breadthDepth_; /// Chosen node from estimated (-1 is off) int startNodeNumber_; /// Node number when dive started int afterNodeNumber_; /// Indicates doing setup for diving bool setupForDiving_ ; }; #endif //CbcCompareDefault_H Cbc-2.8.12/src/CbcSimpleIntegerPseudoCost.cpp0000644000076600007660000002123212131315050017423 0ustar coincoin// $Id: CbcSimpleIntegerPseudoCost.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcSimpleIntegerPseudoCost.hpp" #include "CbcSimpleIntegerDynamicPseudoCost.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" //############################################################################## /** Default Constructor Equivalent to an unspecified binary variable. */ CbcSimpleIntegerPseudoCost::CbcSimpleIntegerPseudoCost () : CbcSimpleInteger(), downPseudoCost_(1.0e-5), upPseudoCost_(1.0e-5), upDownSeparator_(-1.0), method_(0) { } /** Useful constructor Loads actual upper & lower bounds for the specified variable. */ CbcSimpleIntegerPseudoCost::CbcSimpleIntegerPseudoCost (CbcModel * model, int iColumn, double breakEven) : CbcSimpleInteger(model, iColumn, breakEven) { const double * cost = model->getObjCoefficients(); double costValue = CoinMax(1.0e-5, fabs(cost[iColumn])); // treat as if will cost what it says up upPseudoCost_ = costValue; // and balance at breakeven downPseudoCost_ = ((1.0 - breakEven_) * upPseudoCost_) / breakEven_; upDownSeparator_ = -1.0; method_ = 0; } /** Useful constructor Loads actual upper & lower bounds for the specified variable. */ CbcSimpleIntegerPseudoCost::CbcSimpleIntegerPseudoCost (CbcModel * model, int iColumn, double downPseudoCost, double upPseudoCost) : CbcSimpleInteger(model, iColumn) { downPseudoCost_ = CoinMax(1.0e-10, downPseudoCost); upPseudoCost_ = CoinMax(1.0e-10, upPseudoCost); breakEven_ = upPseudoCost_ / (upPseudoCost_ + downPseudoCost_); upDownSeparator_ = -1.0; method_ = 0; } // Useful constructor - passed and model index and pseudo costs CbcSimpleIntegerPseudoCost::CbcSimpleIntegerPseudoCost (CbcModel * model, int /*dummy*/, int iColumn, double downPseudoCost, double upPseudoCost) { *this = CbcSimpleIntegerPseudoCost(model, iColumn, downPseudoCost, upPseudoCost); columnNumber_ = iColumn; } // Copy constructor CbcSimpleIntegerPseudoCost::CbcSimpleIntegerPseudoCost ( const CbcSimpleIntegerPseudoCost & rhs) : CbcSimpleInteger(rhs), downPseudoCost_(rhs.downPseudoCost_), upPseudoCost_(rhs.upPseudoCost_), upDownSeparator_(rhs.upDownSeparator_), method_(rhs.method_) { } // Clone CbcObject * CbcSimpleIntegerPseudoCost::clone() const { return new CbcSimpleIntegerPseudoCost(*this); } // Assignment operator CbcSimpleIntegerPseudoCost & CbcSimpleIntegerPseudoCost::operator=( const CbcSimpleIntegerPseudoCost & rhs) { if (this != &rhs) { CbcSimpleInteger::operator=(rhs); downPseudoCost_ = rhs.downPseudoCost_; upPseudoCost_ = rhs.upPseudoCost_; upDownSeparator_ = rhs.upDownSeparator_; method_ = rhs.method_; } return *this; } // Destructor CbcSimpleIntegerPseudoCost::~CbcSimpleIntegerPseudoCost () { } CbcBranchingObject * CbcSimpleIntegerPseudoCost::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int way) { //OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); #ifndef NDEBUG double nearest = floor(value + 0.5); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); assert (upper[columnNumber_] > lower[columnNumber_]); #endif if (!model_->hotstartSolution()) { assert (fabs(value - nearest) > integerTolerance); } else { const double * hotstartSolution = model_->hotstartSolution(); double targetValue = hotstartSolution[columnNumber_]; if (way > 0) value = targetValue - 0.1; else value = targetValue + 0.1; } CbcIntegerPseudoCostBranchingObject * newObject = new CbcIntegerPseudoCostBranchingObject(model_, columnNumber_, way, value); double up = upPseudoCost_ * (ceil(value) - value); double down = downPseudoCost_ * (value - floor(value)); double changeInGuessed = up - down; if (way > 0) changeInGuessed = - changeInGuessed; changeInGuessed = CoinMax(0.0, changeInGuessed); //if (way>0) //changeInGuessed += 1.0e8; // bias to stay up newObject->setChangeInGuessed(changeInGuessed); newObject->setOriginalObject(this); return newObject; } double CbcSimpleIntegerPseudoCost::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); if (upper[columnNumber_] == lower[columnNumber_]) { // fixed preferredWay = 1; return 0.0; } double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); /*printf("%d %g %g %g %g\n",columnNumber_,value,lower[columnNumber_], solution[columnNumber_],upper[columnNumber_]);*/ double nearest = floor(value + 0.5); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double below = floor(value + integerTolerance); double above = below + 1.0; if (above > upper[columnNumber_]) { above = below; below = above - 1; } double downCost = CoinMax((value - below) * downPseudoCost_, 0.0); double upCost = CoinMax((above - value) * upPseudoCost_, 0.0); if (downCost >= upCost) preferredWay = 1; else preferredWay = -1; // See if up down choice set if (upDownSeparator_ > 0.0) { preferredWay = (value - below >= upDownSeparator_) ? 1 : -1; } if (preferredWay_) preferredWay = preferredWay_; if (fabs(value - nearest) <= integerTolerance) { return 0.0; } else { // can't get at model so 1,2 don't make sense assert(method_ < 1 || method_ > 2); if (!method_) return CoinMin(downCost, upCost); else return CoinMax(downCost, upCost); } } // Return "up" estimate double CbcSimpleIntegerPseudoCost::upEstimate() const { OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); if (upper[columnNumber_] == lower[columnNumber_]) { // fixed return 0.0; } double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double below = floor(value + integerTolerance); double above = below + 1.0; if (above > upper[columnNumber_]) { above = below; below = above - 1; } double upCost = CoinMax((above - value) * upPseudoCost_, 0.0); return upCost; } // Return "down" estimate double CbcSimpleIntegerPseudoCost::downEstimate() const { OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); if (upper[columnNumber_] == lower[columnNumber_]) { // fixed return 0.0; } double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double below = floor(value + integerTolerance); double above = below + 1.0; if (above > upper[columnNumber_]) { above = below; below = above - 1; } double downCost = CoinMax((value - below) * downPseudoCost_, 0.0); return downCost; } Cbc-2.8.12/src/CbcBranchDefaultDecision.hpp0000644000076600007660000000665312131315050017042 0ustar coincoin// $Id: CbcBranchDefaultDecision.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #ifndef CbcBranchDefaultDecision_H #define CbcBranchDefaultDecision_H #include "CbcBranchBase.hpp" /** Branching decision default class This class implements a simple default algorithm (betterBranch()) for choosing a branching variable. */ class CbcBranchDefaultDecision : public CbcBranchDecision { public: // Default Constructor CbcBranchDefaultDecision (); // Copy constructor CbcBranchDefaultDecision ( const CbcBranchDefaultDecision &); virtual ~CbcBranchDefaultDecision(); /// Clone virtual CbcBranchDecision * clone() const; /// Initialize, e.g. before the start of branch selection at a node virtual void initialize(CbcModel * model); /** \brief Compare two branching objects. Return nonzero if \p thisOne is better than \p bestSoFar. The routine compares branches using the values supplied in \p numInfUp and \p numInfDn until a solution is found by search, after which it uses the values supplied in \p changeUp and \p changeDn. The best branching object seen so far and the associated parameter values are remembered in the \c CbcBranchDefaultDecision object. The nonzero return value is +1 if the up branch is preferred, -1 if the down branch is preferred. As the names imply, the assumption is that the values supplied for \p numInfUp and \p numInfDn will be the number of infeasibilities reported by the branching object, and \p changeUp and \p changeDn will be the estimated change in objective. Other measures can be used if desired. Because an \c CbcBranchDefaultDecision object remembers the current best branching candidate (#bestObject_) as well as the values used in the comparison, the parameter \p bestSoFar is redundant, hence unused. */ virtual int betterBranch(CbcBranchingObject * thisOne, CbcBranchingObject * bestSoFar, double changeUp, int numInfUp, double changeDn, int numInfDn); /** Sets or gets best criterion so far */ virtual void setBestCriterion(double value); virtual double getBestCriterion() const; /** \brief Compare N branching objects. Return index of best and sets way of branching in chosen object. This routine is used only after strong branching. */ virtual int bestBranch (CbcBranchingObject ** objects, int numberObjects, int numberUnsatisfied, double * changeUp, int * numberInfeasibilitiesUp, double * changeDown, int * numberInfeasibilitiesDown, double objectiveValue) ; private: /// Illegal Assignment operator CbcBranchDefaultDecision & operator=(const CbcBranchDefaultDecision& rhs); /// data /// "best" so far double bestCriterion_; /// Change up for best double bestChangeUp_; /// Number of infeasibilities for up int bestNumberUp_; /// Change down for best double bestChangeDown_; /// Pointer to best branching object CbcBranchingObject * bestObject_; /// Number of infeasibilities for down int bestNumberDown_; }; #endif Cbc-2.8.12/src/CbcNode.hpp0000644000076600007660000002665611510742604013565 0ustar coincoin/* $Id: CbcNode.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcNode_H #define CbcNode_H #include #include #include "CoinWarmStartBasis.hpp" #include "CoinSearchTree.hpp" #include "CbcBranchBase.hpp" #include "CbcNodeInfo.hpp" #include "CbcFullNodeInfo.hpp" #include "CbcPartialNodeInfo.hpp" class OsiSolverInterface; class OsiSolverBranch; class OsiCuts; class OsiRowCut; class OsiRowCutDebugger; class CoinWarmStartBasis; class CbcCountRowCut; class CbcModel; class CbcNode; class CbcSubProblem; class CbcGeneralBranchingObject; /** Information required while the node is live When a subproblem is initially created, it is represented by an CbcNode object and an attached CbcNodeInfo object. The CbcNode contains information (depth, branching instructions), that's needed while the subproblem remains `live', i.e., while the subproblem is not fathomed and there are branch arms still be be evaluated. The CbcNode is deleted when the last branch arm has been evaluated. The CbcNodeInfo object contains the information needed to maintain the search tree and recreate the subproblem for the node. It remains in existence until there are no nodes remaining in the subtree rooted at this node. */ class CbcNode : public CoinTreeNode { public: /// Default Constructor CbcNode (); /// Construct and increment parent reference count CbcNode (CbcModel * model, CbcNode * lastNode); /// Copy constructor CbcNode (const CbcNode &); /// Assignment operator CbcNode & operator= (const CbcNode& rhs); /// Destructor ~CbcNode (); /** Create a description of the subproblem at this node The CbcNodeInfo structure holds the information (basis & variable bounds) required to recreate the subproblem for this node. It also links the node to its parent (via the parent's CbcNodeInfo object). If lastNode == NULL, a CbcFullNodeInfo object will be created. All parameters except \p model are unused. If lastNode != NULL, a CbcPartialNodeInfo object will be created. Basis and bounds information will be stored in the form of differences between the parent subproblem and this subproblem. (More precisely, \p lastws, \p lastUpper, \p lastLower, \p numberOldActiveCuts, and \p numberNewCuts are used.) */ void createInfo(CbcModel * model, CbcNode * lastNode, const CoinWarmStartBasis *lastws, const double * lastLower, const double * lastUpper, int numberOldActiveCuts, int numberNewCuts); /** Create a branching object for the node The routine scans the object list of the model and selects a set of unsatisfied objects as candidates for branching. The candidates are evaluated, and an appropriate branch object is installed. The numberPassesLeft is decremented to stop fixing one variable each time and going on and on (e.g. for stock cutting, air crew scheduling) If evaluation determines that an object is monotone or infeasible, the routine returns immediately. In the case of a monotone object, the branch object has already been called to modify the model. Return value:
  • 0: A branching object has been installed
  • -1: A monotone object was discovered
  • -2: An infeasible object was discovered
*/ int chooseBranch (CbcModel * model, CbcNode * lastNode, int numberPassesLeft); /** Create a branching object for the node - when dynamic pseudo costs The routine scans the object list of the model and selects a set of unsatisfied objects as candidates for branching. The candidates are evaluated, and an appropriate branch object is installed. This version gives preference in evaluation to variables which have not been evaluated many times. It also uses numberStrong to say give up if last few tries have not changed incumbent. See Achterberg, Koch and Martin. The numberPassesLeft is decremented to stop fixing one variable each time and going on and on (e.g. for stock cutting, air crew scheduling) If evaluation determines that an object is monotone or infeasible, the routine returns immediately. In the case of a monotone object, the branch object has already been called to modify the model. Return value:
  • 0: A branching object has been installed
  • -1: A monotone object was discovered
  • -2: An infeasible object was discovered
  • >0: Number of quich branching objects (and branches will be non NULL)
*/ int chooseDynamicBranch (CbcModel * model, CbcNode * lastNode, OsiSolverBranch * & branches, int numberPassesLeft); /** Create a branching object for the node The routine scans the object list of the model and selects a set of unsatisfied objects as candidates for branching. The candidates are evaluated, and an appropriate branch object is installed. The numberPassesLeft is decremented to stop fixing one variable each time and going on and on (e.g. for stock cutting, air crew scheduling) If evaluation determines that an object is monotone or infeasible, the routine returns immediately. In the case of a monotone object, the branch object has already been called to modify the model. Return value:
  • 0: A branching object has been installed
  • -1: A monotone object was discovered
  • -2: An infeasible object was discovered
Branch state:
  • -1: start
  • -1: A monotone object was discovered
  • -2: An infeasible object was discovered
*/ int chooseOsiBranch (CbcModel * model, CbcNode * lastNode, OsiBranchingInformation * usefulInfo, int branchState); /** Create a branching object for the node The routine scans the object list of the model and selects a set of unsatisfied objects as candidates for branching. It then solves a series of problems and a CbcGeneral branch object is installed. If evaluation determines that an object is infeasible, the routine returns immediately. Return value:
  • 0: A branching object has been installed
  • -2: An infeasible object was discovered
*/ int chooseClpBranch (CbcModel * model, CbcNode * lastNode); int analyze(CbcModel * model, double * results); /// Decrement active cut counts void decrementCuts(int change = 1); /// Decrement all active cut counts in chain starting at parent void decrementParentCuts(CbcModel * model, int change = 1); /// Nulls out node info void nullNodeInfo(); /** Initialize reference counts in attached CbcNodeInfo This is a convenience routine, which will initialize the reference counts in the attached CbcNodeInfo object based on the attached OsiBranchingObject. \sa CbcNodeInfo::initializeInfo(int). */ void initializeInfo(); /// Does next branch and updates state int branch(OsiSolverInterface * solver); /** Double checks in case node can change its mind! Returns objective value Can change objective etc */ double checkIsCutoff(double cutoff); // Information to make basis and bounds inline CbcNodeInfo * nodeInfo() const { return nodeInfo_; } // Objective value inline double objectiveValue() const { return objectiveValue_; } inline void setObjectiveValue(double value) { objectiveValue_ = value; } /// Number of arms defined for the attached OsiBranchingObject. inline int numberBranches() const { if (branch_) return (branch_->numberBranches()) ; else return (-1) ; } /* Active arm of the attached OsiBranchingObject. In the simplest instance, coded -1 for the down arm of the branch, +1 for the up arm. But see OsiBranchingObject::way() Use nodeInfo--.numberBranchesLeft_ to see how active */ int way() const; /// Depth in branch-and-cut search tree inline int depth() const { return depth_; } /// Set depth in branch-and-cut search tree inline void setDepth(int value) { depth_ = value; } /// Get the number of objects unsatisfied at this node. inline int numberUnsatisfied() const { return numberUnsatisfied_; } /// Set the number of objects unsatisfied at this node. inline void setNumberUnsatisfied(int value) { numberUnsatisfied_ = value; } /// Get sum of "infeasibilities" reported by each object inline double sumInfeasibilities() const { return sumInfeasibilities_; } /// Set sum of "infeasibilities" reported by each object inline void setSumInfeasibilities(double value) { sumInfeasibilities_ = value; } // Guessed objective value (for solution) inline double guessedObjectiveValue() const { return guessedObjectiveValue_; } inline void setGuessedObjectiveValue(double value) { guessedObjectiveValue_ = value; } /// Branching object for this node inline const OsiBranchingObject * branchingObject() const { return branch_; } /// Modifiable branching object for this node inline OsiBranchingObject * modifiableBranchingObject() const { return branch_; } /// Set branching object for this node (takes ownership) inline void setBranchingObject(OsiBranchingObject * branchingObject) { branch_ = branchingObject; } /// The node number inline int nodeNumber() const { return nodeNumber_; } inline void setNodeNumber(int node) { nodeNumber_ = node; } /// Returns true if on tree inline bool onTree() const { return (state_&1) != 0; } /// Sets true if on tree inline void setOnTree(bool yesNo) { if (yesNo) state_ |= 1; else state_ &= ~1; } /// Returns true if active inline bool active() const { return (state_&2) != 0; } /// Sets true if active inline void setActive(bool yesNo) { if (yesNo) state_ |= 2; else state_ &= ~2; } /// Print void print() const; /// Debug inline void checkInfo() const { assert (nodeInfo_->numberBranchesLeft() == branch_->numberBranchesLeft()); } private: // Data /// Information to make basis and bounds CbcNodeInfo * nodeInfo_; /// Objective value double objectiveValue_; /// Guessed satisfied Objective value double guessedObjectiveValue_; /// Sum of "infeasibilities" reported by each object double sumInfeasibilities_; /// Branching object for this node OsiBranchingObject * branch_; /// Depth of the node in the search tree int depth_; /// The number of objects unsatisfied at this node. int numberUnsatisfied_; /// The node number int nodeNumber_; /** State 1 - on tree 2 - active */ int state_; }; #endif Cbc-2.8.12/src/CbcHeuristicDiveLineSearch.cpp0000644000076600007660000000743712131315050017363 0ustar coincoin/* $Id: CbcHeuristicDiveLineSearch.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcHeuristicDiveLineSearch.hpp" #include "CbcStrategy.hpp" // Default Constructor CbcHeuristicDiveLineSearch::CbcHeuristicDiveLineSearch() : CbcHeuristicDive() { } // Constructor from model CbcHeuristicDiveLineSearch::CbcHeuristicDiveLineSearch(CbcModel & model) : CbcHeuristicDive(model) { } // Destructor CbcHeuristicDiveLineSearch::~CbcHeuristicDiveLineSearch () { } // Clone CbcHeuristicDiveLineSearch * CbcHeuristicDiveLineSearch::clone() const { return new CbcHeuristicDiveLineSearch(*this); } // Create C++ lines to get to current state void CbcHeuristicDiveLineSearch::generateCpp( FILE * fp) { CbcHeuristicDiveLineSearch other; fprintf(fp, "0#include \"CbcHeuristicDiveLineSearch.hpp\"\n"); fprintf(fp, "3 CbcHeuristicDiveLineSearch heuristicDiveLineSearch(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicDiveLineSearch"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicDiveLineSearch);\n"); } // Copy constructor CbcHeuristicDiveLineSearch::CbcHeuristicDiveLineSearch(const CbcHeuristicDiveLineSearch & rhs) : CbcHeuristicDive(rhs) { } // Assignment operator CbcHeuristicDiveLineSearch & CbcHeuristicDiveLineSearch::operator=( const CbcHeuristicDiveLineSearch & rhs) { if (this != &rhs) { CbcHeuristicDive::operator=(rhs); } return *this; } bool CbcHeuristicDiveLineSearch::selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound) { int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); // get the LP relaxation solution at the root node double * rootNodeLPSol = model_->continuousSolution(); bestColumn = -1; bestRound = -1; // -1 rounds down, +1 rounds up double bestRelDistance = COIN_DBL_MAX; bool allTriviallyRoundableSoFar = true; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double rootValue = rootNodeLPSol[iColumn]; double value = newSolution[iColumn]; double fraction = value - floor(value); int round = 0; if (fabs(floor(value + 0.5) - value) > integerTolerance) { if (allTriviallyRoundableSoFar || (downLocks_[i] > 0 && upLocks_[i] > 0)) { if (allTriviallyRoundableSoFar && downLocks_[i] > 0 && upLocks_[i] > 0) { allTriviallyRoundableSoFar = false; bestRelDistance = COIN_DBL_MAX; } double relDistance; if (value < rootValue) { round = -1; relDistance = fraction / (rootValue - value); } else if (value > rootValue) { round = 1; relDistance = (1.0 - fraction) / (value - rootValue); } else { round = -1; relDistance = COIN_DBL_MAX; } // if variable is not binary, penalize it if (!solver->isBinary(iColumn)) relDistance *= 1000.0; if (relDistance < bestRelDistance) { bestColumn = iColumn; bestRelDistance = relDistance; bestRound = round; } } } } return allTriviallyRoundableSoFar; } Cbc-2.8.12/src/CbcGenCbcParam.cpp0000644000076600007660000000660512131315050014754 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenCbcParam.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include "CoinParam.hpp" #include "CbcModel.hpp" #include "CbcGenCtlBlk.hpp" #include "CbcGenParam.hpp" #include "CbcGenCbcParam.hpp" namespace { char svnid[] = "$Id: CbcGenCbcParam.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } /* Constructors and destructors There's a generic constructor and one for integer, double, keyword, string, and action parameters. */ /* Default constructor. */ CbcCbcParam::CbcCbcParam () : CoinParam(), paramCode_(CbcCbcParamCode(0)), obj_(0) { /* Nothing to be done here */ } /* Constructor for double parameter */ CbcCbcParam::CbcCbcParam (CbcCbcParamCode code, std::string name, std::string help, double lower, double upper, double dflt, bool display) : CoinParam(name, help, lower, upper, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for integer parameter */ CbcCbcParam::CbcCbcParam (CbcCbcParamCode code, std::string name, std::string help, int lower, int upper, int dflt, bool display) : CoinParam(name, help, lower, upper, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for keyword parameter. */ CbcCbcParam::CbcCbcParam (CbcCbcParamCode code, std::string name, std::string help, std::string firstValue, int dflt, bool display) : CoinParam(name, help, firstValue, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for string parameter. */ CbcCbcParam::CbcCbcParam (CbcCbcParamCode code, std::string name, std::string help, std::string dflt, bool display) : CoinParam(name, help, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for action parameter. */ CbcCbcParam::CbcCbcParam (CbcCbcParamCode code, std::string name, std::string help, bool display) : CoinParam(name, help, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Copy constructor. */ CbcCbcParam::CbcCbcParam (const CbcCbcParam &orig) : CoinParam(orig), paramCode_(orig.paramCode_), obj_(orig.obj_) { /* Nothing to be done here */ } /* Clone */ CbcCbcParam *CbcCbcParam::clone () { return (new CbcCbcParam(*this)) ; } CbcCbcParam &CbcCbcParam::operator= (const CbcCbcParam & rhs) { if (this != &rhs) { CoinParam::operator=(rhs) ; paramCode_ = rhs.paramCode_ ; obj_ = rhs.obj_ ; } return *this ; } /* Destructor */ CbcCbcParam::~CbcCbcParam () { /* Nothing more to do */ } Cbc-2.8.12/src/CbcGenParam.hpp0000644000076600007660000001442112131315050014344 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenParam.hpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #ifndef CbcGenParam_H #define CbcGenParam_H /* \file CbcGenParam.hpp \brief Declarations for parameters that control the cbc-generic main program. */ /* $Id: CbcGenParam.hpp 1902 2013-04-10 16:58:16Z stefan $ */ class CbcGenCtlBlk ; /*! \class CbcGenParam \brief Class for cbc-generic control parameters Adds parameter type codes and push/pull functions to the generic parameter object. */ class CbcGenParam : public CoinParam { public: /*! \name Subtypes */ //@{ /*! \enum CbcGenParamCode \brief Enumeration for cbc-generic parameters These are parameters that control the operation of the cbc-generic main program by operating on a CbcGenCtlBlk object. CBCGEN_FIRSTPARAM and CBCGEN_LASTPARM are markers to allow convenient separation of parameter groups. */ typedef enum { CBCGEN_FIRSTPARAM = 0, GENERALQUERY, FULLGENERALQUERY, HELP, BAB, CLEARCUTS, CLIQUECUTS, COMBINE, COSTSTRATEGY, CPP, CUTDEPTH, CUTSTRATEGY, DEBUG, DIRECTORY, DJFIX, DUMMY, ERRORSALLOWED, EXIT, EXPORT, FLOWCUTS, FPUMP, FPUMPITS, GOMORYCUTS, GREEDY, HEURISTICSTRATEGY, IMPORT, INTPRINT, KNAPSACKCUTS, LOCALTREE, LOGLEVEL, MESSAGES, MIPLIB, MIXEDCUTS, ODDHOLECUTS, OUTDUPROWS, OUTPUTFORMAT, PREPROCESS, PRINTMASK, PRINTOPTIONS, PRINTVERSION, PRIORITYIN, PROBINGCUTS, REDSPLITCUTS, ROUNDING, SOLUTION, SOLVECONTINUOUS, SOLVER, SOS, STDIN, STRENGTHEN, TIGHTENFACTOR, TWOMIRCUTS, UNITTEST, USERCBC, USESOLUTION, VERBOSE, SHOWUNIMP, CBCGEN_LASTPARAM } CbcGenParamCode ; //@} /*! \name Constructors and Destructors Be careful how you specify parameters for the constructors! There's great potential for confusion. */ //@{ /*! \brief Default constructor */ CbcGenParam() ; /*! \brief Constructor for a parameter with a double value The default value is 0.0. Be careful to clearly indicate that \p lower and \p upper are real (double) values to distinguish this constructor from the constructor for an integer parameter. */ CbcGenParam(CbcGenParamCode code, std::string name, std::string help, double lower, double upper, double dflt = 0.0, bool display = true) ; /*! \brief Constructor for a parameter with an integer value The default value is 0. */ CbcGenParam(CbcGenParamCode code, std::string name, std::string help, int lower, int upper, int dflt = 0, bool display = true) ; /*! \brief Constructor for a parameter with keyword values The string supplied as \p firstValue becomes the first keyword. Additional keywords can be added using appendKwd(). Keywords are numbered from zero. It's necessary to specify both the first keyword (\p firstValue) and the default keyword index (\p dflt) in order to distinguish this constructor from the string and action parameter constructors. */ CbcGenParam(CbcGenParamCode code, std::string name, std::string help, std::string firstValue, int dflt, bool display = true) ; /*! \brief Constructor for a string parameter The default string value must be specified explicitly to distinguish a string constructor from an action parameter constructor. */ CbcGenParam(CbcGenParamCode code, std::string name, std::string help, std::string dflt, bool display = true) ; /*! \brief Constructor for an action parameter */ CbcGenParam(CbcGenParamCode code, std::string name, std::string help, bool display = true) ; /*! \brief Copy constructor */ CbcGenParam(const CbcGenParam &orig) ; /*! \brief Clone */ CbcGenParam *clone() ; /*! \brief Assignment */ CbcGenParam &operator=(const CbcGenParam &rhs) ; /*! \brief Destructor */ ~CbcGenParam() ; //@} /*! \name Methods to query and manipulate a parameter object */ //@{ /*! \brief Get the parameter code */ inline CbcGenParamCode paramCode() const { return (paramCode_) ; } /*! \brief Set the parameter code */ inline void setParamCode(CbcGenParamCode code) { paramCode_ = code ; } /*! \brief Get the underlying cbc-generic control object */ inline CbcGenCtlBlk *obj() const { return (obj_) ; } /*! \brief Set the underlying cbc-generic control object */ inline void setObj(CbcGenCtlBlk *obj) { obj_ = obj ; } //@} private: /*! \name Data */ //@{ /// Parameter code CbcGenParamCode paramCode_ ; /// cbc-generic control object CbcGenCtlBlk *obj_ ; //@} } ; /* Declare the utility functions. */ namespace CbcGenParamUtils { void addCbcGenParams(int &numParams, CoinParamVec ¶mVec, CbcGenCtlBlk *ctlBlk) ; void loadGenParamObj(const CoinParamVec paramVec, int first, int last, CbcGenCtlBlk *ctlBlk) ; void saveSolution(const OsiSolverInterface *osi, std::string fileName) ; bool readSolution(std::string fileName, int &numRows, int &numCols, double &objVal, double **rowActivity, double **dualVars, double **primalVars, double **reducedCosts) ; int doBaCParam(CoinParam *param) ; int doDebugParam(CoinParam *param) ; int doExitParam(CoinParam *param) ; int doHelpParam(CoinParam *param) ; int doImportParam(CoinParam *param) ; int doPrintMaskParam(CoinParam *param) ; int doNothingParam(CoinParam *param) ; int doSolutionParam(CoinParam *param) ; int doUnimplementedParam(CoinParam *param) ; int doVersionParam(CoinParam *param) ; int pushCbcGenDblParam(CoinParam *param) ; int pushCbcGenIntParam(CoinParam *param) ; int pushCbcGenKwdParam(CoinParam *param) ; int pushCbcGenStrParam(CoinParam *param) ; int pushCbcGenCutParam(CoinParam *param) ; } #endif Cbc-2.8.12/src/CbcPartialNodeInfo.cpp0000644000076600007660000002220712131315050015664 0ustar coincoin// $Id: CbcPartialNodeInfo.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/24/09 carved from CbcNode #include "CbcConfig.h" #include //#define CBC_DEBUG 1 //#define CHECK_CUT_COUNTS //#define CHECK_NODE //#define CBC_CHECK_BASIS #include #include #define CUTS #include "CoinPragma.hpp" #include "OsiSolverInterface.hpp" #include "OsiChooseVariable.hpp" #include "OsiAuxInfo.hpp" #include "OsiSolverBranch.hpp" #include "CoinWarmStartBasis.hpp" #include "CoinTime.hpp" #include "CbcModel.hpp" #include "CbcNode.hpp" #include "CbcStatistics.hpp" #include "CbcStrategy.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchDynamic.hpp" #include "OsiRowCut.hpp" #include "OsiRowCutDebugger.hpp" #include "OsiCuts.hpp" #include "CbcCountRowCut.hpp" #include "CbcFeasibilityBase.hpp" #include "CbcMessage.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #include "ClpSimplexOther.hpp" #endif using namespace std; #include "CglCutGenerator.hpp" // Default constructor CbcPartialNodeInfo::CbcPartialNodeInfo() : CbcNodeInfo(), basisDiff_(NULL), variables_(NULL), newBounds_(NULL), numberChangedBounds_(0) { /* this space intentionally left blank */ } // Constructor from current state CbcPartialNodeInfo::CbcPartialNodeInfo (CbcNodeInfo *parent, CbcNode *owner, int numberChangedBounds, const int *variables, const double *boundChanges, const CoinWarmStartDiff *basisDiff) : CbcNodeInfo(parent, owner) { basisDiff_ = basisDiff->clone() ; #ifdef CBC_CHECK_BASIS std::cout << "Constructor (" << this << ") " << std::endl ; #endif numberChangedBounds_ = numberChangedBounds; size_t size = numberChangedBounds_ * (sizeof(double) + sizeof(int)); char * temp = new char [size]; newBounds_ = reinterpret_cast (temp); variables_ = reinterpret_cast (newBounds_ + numberChangedBounds_); int i ; for (i = 0; i < numberChangedBounds_; i++) { variables_[i] = variables[i]; newBounds_[i] = boundChanges[i]; } } CbcPartialNodeInfo::CbcPartialNodeInfo (const CbcPartialNodeInfo & rhs) : CbcNodeInfo(rhs) { basisDiff_ = rhs.basisDiff_->clone() ; #ifdef CBC_CHECK_BASIS std::cout << "Copy constructor (" << this << ") from " << this << std::endl ; #endif numberChangedBounds_ = rhs.numberChangedBounds_; size_t size = numberChangedBounds_ * (sizeof(double) + sizeof(int)); char * temp = new char [size]; newBounds_ = reinterpret_cast (temp); variables_ = reinterpret_cast (newBounds_ + numberChangedBounds_); int i ; for (i = 0; i < numberChangedBounds_; i++) { variables_[i] = rhs.variables_[i]; newBounds_[i] = rhs.newBounds_[i]; } } CbcNodeInfo * CbcPartialNodeInfo::clone() const { return (new CbcPartialNodeInfo(*this)); } CbcPartialNodeInfo::~CbcPartialNodeInfo () { delete basisDiff_ ; delete [] newBounds_; } /** The basis supplied as a parameter is incrementally modified, and lower and upper bounds on variables in the model are incrementally modified. Any cuts associated with this node are added to the list in addCuts. */ void CbcPartialNodeInfo::applyToModel (CbcModel *model, CoinWarmStartBasis *&basis, CbcCountRowCut **addCuts, int ¤tNumberCuts) const { OsiSolverInterface *solver = model->solver(); if ((active_&4) != 0) { basis->applyDiff(basisDiff_) ; #ifdef CBC_CHECK_BASIS std::cout << "Basis (after applying " << this << ") " << std::endl ; basis->print() ; #endif } // branch - do bounds int i; if ((active_&1) != 0) { for (i = 0; i < numberChangedBounds_; i++) { int variable = variables_[i]; int k = variable & 0x3fffffff; if ((variable&0x80000000) == 0) { // lower bound changing //#define CBC_PRINT2 #ifdef CBC_PRINT2 if (solver->getColLower()[k] != newBounds_[i]) printf("lower change for column %d - from %g to %g\n", k, solver->getColLower()[k], newBounds_[i]); #endif #ifndef NDEBUG if ((variable&0x40000000) == 0 && false) { double oldValue = solver->getColLower()[k]; assert (newBounds_[i] > oldValue - 1.0e-8); if (newBounds_[i] < oldValue + 1.0e-8) printf("bad null lower change for column %d - bound %g\n", k, oldValue); } #endif solver->setColLower(k, newBounds_[i]); } else { // upper bound changing #ifdef CBC_PRINT2 if (solver->getColUpper()[k] != newBounds_[i]) printf("upper change for column %d - from %g to %g\n", k, solver->getColUpper()[k], newBounds_[i]); #endif #ifndef NDEBUG if ((variable&0x40000000) == 0 && false) { double oldValue = solver->getColUpper()[k]; assert (newBounds_[i] < oldValue + 1.0e-8); if (newBounds_[i] > oldValue - 1.0e-8) printf("bad null upper change for column %d - bound %g\n", k, oldValue); } #endif solver->setColUpper(k, newBounds_[i]); } } } if ((active_&2) != 0) { for (i = 0; i < numberCuts_; i++) { addCuts[currentNumberCuts+i] = cuts_[i]; if (cuts_[i] && model->messageHandler()->logLevel() > 4) { cuts_[i]->print(); } } currentNumberCuts += numberCuts_; } return ; } // Just apply bounds to one variable (1=>infeasible) int CbcPartialNodeInfo::applyBounds(int iColumn, double & lower, double & upper, int force) { // branch - do bounds int i; int found = 0; double newLower = -COIN_DBL_MAX; double newUpper = COIN_DBL_MAX; for (i = 0; i < numberChangedBounds_; i++) { int variable = variables_[i]; int k = variable & 0x3fffffff; if (k == iColumn) { if ((variable&0x80000000) == 0) { // lower bound changing found |= 1; newLower = CoinMax(newLower, newBounds_[i]); if ((force&1) == 0) { if (lower > newBounds_[i]) COIN_DETAIL_PRINT(printf("%d odd lower going from %g to %g\n", iColumn, lower, newBounds_[i])); lower = newBounds_[i]; } else { newBounds_[i] = lower; variables_[i] |= 0x40000000; // say can go odd way } } else { // upper bound changing found |= 2; newUpper = CoinMin(newUpper, newBounds_[i]); if ((force&2) == 0) { if (upper < newBounds_[i]) COIN_DETAIL_PRINT(printf("%d odd upper going from %g to %g\n", iColumn, upper, newBounds_[i])); upper = newBounds_[i]; } else { newBounds_[i] = upper; variables_[i] |= 0x40000000; // say can go odd way } } } } newLower = CoinMax(newLower, lower); newUpper = CoinMin(newUpper, upper); int nAdd = 0; if ((force&2) != 0 && (found&2) == 0) { // need to add new upper nAdd++; } if ((force&1) != 0 && (found&1) == 0) { // need to add new lower nAdd++; } if (nAdd) { size_t size = (numberChangedBounds_ + nAdd) * (sizeof(double) + sizeof(int)); char * temp = new char [size]; double * newBounds = reinterpret_cast (temp); int * variables = reinterpret_cast (newBounds + numberChangedBounds_ + nAdd); int i ; for (i = 0; i < numberChangedBounds_; i++) { variables[i] = variables_[i]; newBounds[i] = newBounds_[i]; } delete [] newBounds_; newBounds_ = newBounds; variables_ = variables; if ((force&2) != 0 && (found&2) == 0) { // need to add new upper int variable = iColumn | 0x80000000; variables_[numberChangedBounds_] = variable; newBounds_[numberChangedBounds_++] = newUpper; } if ((force&1) != 0 && (found&1) == 0) { // need to add new lower int variable = iColumn; variables_[numberChangedBounds_] = variable; newBounds_[numberChangedBounds_++] = newLower; } } return (newUpper >= newLower) ? 0 : 1; } /* Builds up row basis backwards (until original model). Returns NULL or previous one to apply . Depends on Free being 0 and impossible for cuts */ CbcNodeInfo * CbcPartialNodeInfo::buildRowBasis(CoinWarmStartBasis & basis ) const { basis.applyDiff(basisDiff_) ; return parent_ ; } Cbc-2.8.12/src/CbcTree.cpp0000644000076600007660000013756312314276652013602 0ustar coincoin/* $Id: CbcTree.cpp 2023 2014-03-25 12:59:22Z forrest $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CbcModel.hpp" #include "CbcNode.hpp" #include "CbcTree.hpp" #include "CbcThread.hpp" #include "CbcCountRowCut.hpp" #include "CbcCompareActual.hpp" #include "CbcBranchActual.hpp" #if CBC_DEBUG_HEAP > 0 namespace { /* The next few methods test that the heap property (parent equal or better than either child) is maintained in the heap. Originally created to sort out why `cbc -unitTest' triggered an `Invalid heap' error in a MSVS debug build. */ /* Predicate test. The parent should be better or equal to the child. Since the predicate comparison_(x,y) returns true if y (child) is strictly better, we want failure on the initial test. Clearly, success for comparison(x,y) and comparison(y,x) is also a failure. Returns true if the predicate passes, false if it fails. */ bool check_pred (CbcCompareBase &pred, CbcNode *parent, CbcNode *child) { if (parent == 0 || child == 0) return (false) ; if (!pred(parent,child)) return (true) ; else if (pred(child,parent)) std::cout << " Heap predicate failure! (x vector mapping assumed here is valid for the MSVS heap implementation. No guarantee it's valid elsewhere. */ void CbcTree::validateHeap () { if (comparison_.test_ == 0) { std::cout << " Invalid heap (no predicate)!" << std::endl ; return ; } std::vector::const_iterator curNode,lastNode ; curNode = nodes_.begin() ; lastNode = nodes_.end() ; int curNdx = 0 ; int parNdx = 0 ; if (curNode == lastNode) return ; if (*curNode == 0) { std::cout << " Invalid heap[" << curNdx << "] (null entry)!" << std::endl ; } std::vector::const_iterator parent ; std::vector::const_iterator &child = curNode ; for (parent = curNode ; ++curNode != lastNode ; ++parent, ++parNdx) { curNdx++ ; if (*parent == 0) { std::cout << " Invalid heap[" << parNdx << "] (parent null entry)!" << std::endl ; curNode++ ; curNdx++ ; continue ; } if (*curNode == 0) { std::cout << " Invalid heap[" << curNdx << "] (left child null entry)!" << std::endl ; } else { if (!check_pred(*comparison_.test_,*parent,*child)) { std::cout << " Invalid heap (left child better)!" << std::endl ; CbcNode *node = *parent ; std::cout << " Parent [" << parNdx << "] (" << std::hex << node << std::dec << ") unsat " << node->numberUnsatisfied() << ", depth " << node->depth() << ", obj " << node->objectiveValue() << "." << std::endl ; node = *child ; std::cout << " Child [" << curNdx << "] (" << std::hex << node << std::dec << ") unsat " << node->numberUnsatisfied() << ", depth " << node->depth() << ", obj " << node->objectiveValue() << "." << std::endl ; } } curNode++ ; curNdx++ ; if (curNode == lastNode) break ; if (*curNode == 0) { std::cout << " Invalid heap[" << curNdx << "] (right child null entry)!" << std::endl ; } else { if (!check_pred(*comparison_.test_,*parent,*child)) { std::cout << " Invalid heap (right child better)!" << std::endl ; CbcNode *node = *parent ; std::cout << " Parent [" << parNdx << "] (" << std::hex << node << std::dec << ") unsat " << node->numberUnsatisfied() << ", depth " << node->depth() << ", obj " << node->objectiveValue() << "." << std::endl ; node = *child ; std::cout << " Child [" << curNdx << "] (" << std::hex << node << std::dec << ") unsat " << node->numberUnsatisfied() << ", depth " << node->depth() << ", obj " << node->objectiveValue() << "." << std::endl ; } } } return ; } #endif // CBC_DEBUG_HEAP CbcTree::CbcTree() { maximumNodeNumber_ = 0; numberBranching_ = 0; maximumBranching_ = 0; branched_ = NULL; newBound_ = NULL; } CbcTree::~CbcTree() { delete [] branched_; delete [] newBound_; } // Copy constructor CbcTree::CbcTree ( const CbcTree & rhs) { nodes_ = rhs.nodes_; maximumNodeNumber_ = rhs.maximumNodeNumber_; numberBranching_ = rhs.numberBranching_; maximumBranching_ = rhs.maximumBranching_; if (maximumBranching_ > 0) { branched_ = CoinCopyOfArray(rhs.branched_, maximumBranching_); newBound_ = CoinCopyOfArray(rhs.newBound_, maximumBranching_); } else { branched_ = NULL; newBound_ = NULL; } } // Assignment operator CbcTree & CbcTree::operator=(const CbcTree & rhs) { if (this != &rhs) { nodes_ = rhs.nodes_; maximumNodeNumber_ = rhs.maximumNodeNumber_; delete [] branched_; delete [] newBound_; numberBranching_ = rhs.numberBranching_; maximumBranching_ = rhs.maximumBranching_; if (maximumBranching_ > 0) { branched_ = CoinCopyOfArray(rhs.branched_, maximumBranching_); newBound_ = CoinCopyOfArray(rhs.newBound_, maximumBranching_); } else { branched_ = NULL; newBound_ = NULL; } } return *this; } /* Rebuild the heap. */ void CbcTree::rebuild () { std::make_heap(nodes_.begin(), nodes_.end(), comparison_); # if CBC_DEBUG_HEAP > 1 std::cout << " HEAP: rebuild complete." << std::endl ; # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif } // Adds branching information to complete state void CbcTree::addBranchingInformation(const CbcModel * model, const CbcNodeInfo * nodeInfo, const double * currentLower, const double * currentUpper) { const OsiBranchingObject * objA = nodeInfo->owner()->branchingObject(); const CbcIntegerBranchingObject * objBranch = dynamic_cast (objA); if (objBranch) { const CbcObject * objB = objBranch->object(); const CbcSimpleInteger * obj = dynamic_cast (objB); assert (obj); int iColumn = obj->columnNumber(); const double * down = objBranch->downBounds(); const double * up = objBranch->upBounds(); assert (currentLower[iColumn] == down[0]); assert (currentUpper[iColumn] == up[1]); if (dynamic_cast (nodeInfo)) { const CbcPartialNodeInfo * info = dynamic_cast (nodeInfo); const double * newBounds = info->newBounds(); const int * variables = info->variables(); int numberChanged = info->numberChangedBounds(); for (int i = 0; i < numberChanged; i++) { int jColumn = variables[i]; int kColumn = jColumn & (~0x80000000); if (iColumn == kColumn) { jColumn |= 0x40000000; #ifndef NDEBUG double value = newBounds[i]; if ((jColumn&0x80000000) == 0) { assert (value == up[0]); } else { assert (value == down[1]); } #endif } if (numberBranching_ == maximumBranching_) increaseSpace(); newBound_[numberBranching_] = static_cast (newBounds[i]); branched_[numberBranching_++] = jColumn; } } else { const CbcFullNodeInfo * info = dynamic_cast (nodeInfo); int numberIntegers = model->numberIntegers(); const int * which = model->integerVariable(); const double * newLower = info->lower(); const double * newUpper = info->upper(); if (numberBranching_ == maximumBranching_) increaseSpace(); assert (newLower[iColumn] == up[0] || newUpper[iColumn] == down[1]); int jColumn = iColumn | 0x40000000; if (newLower[iColumn] == up[0]) { newBound_[numberBranching_] = static_cast (up[0]); } else { newBound_[numberBranching_] = static_cast (down[1]); jColumn |= 0x80000000; } branched_[numberBranching_++] = jColumn; for (int i = 0; i < numberIntegers; i++) { int jColumn = which[i]; assert (currentLower[jColumn] == newLower[jColumn] || currentUpper[jColumn] == newUpper[jColumn]); if (jColumn != iColumn) { bool changed = false; double value; if (newLower[jColumn] > currentLower[jColumn]) { value = newLower[jColumn]; changed = true; } else if (newUpper[jColumn] < currentUpper[jColumn]) { value = newUpper[jColumn]; jColumn |= 0x80000000; changed = true; } if (changed) { if (numberBranching_ == maximumBranching_) increaseSpace(); newBound_[numberBranching_] = static_cast (value); branched_[numberBranching_++] = jColumn; } } } } } else { // switch off delete [] branched_; delete [] newBound_; maximumBranching_ = -1; branched_ = NULL; newBound_ = NULL; } } // Increase space for data void CbcTree::increaseSpace() { assert (numberBranching_ == maximumBranching_); maximumBranching_ = (3 * maximumBranching_ + 10) >> 1; unsigned int * temp1 = CoinCopyOfArrayPartial(branched_, maximumBranching_, numberBranching_); delete [] branched_; branched_ = temp1; int * temp2 = CoinCopyOfArrayPartial(newBound_, maximumBranching_, numberBranching_); delete [] newBound_; newBound_ = temp2; } // Clone CbcTree * CbcTree::clone() const { return new CbcTree(*this); } #ifndef CBC_DUBIOUS_HEAP /* Set comparison predicate and re-sort the heap. Note that common usage is to tweak the incumbent predicate and then call this method to rebuild the heap. Hence we cannot check for heap validity at entry. rebuild() will check on the way out, if CBC_DEBUG_HEAP is set. TODO: remove the call to cleanDive and put it somewhere appropriate. */ void CbcTree::setComparison(CbcCompareBase &compare) { # if CBC_DEBUG_HEAP > 1 std::cout << " HEAP: resetting comparison predicate." << std::endl ; # endif comparison_.test_ = &compare; /* From a software engineering point of view, setComparison has no business knowing anything about the comparison function. Need to look for a better solution. Perhaps a callback comparable to newSolution, executing when the comparison method is set (i.e., in setComparison). -- lh, 100921 -- */ CbcCompareDefault *compareD = dynamic_cast(&compare); if (compareD) { // clean up diving compareD->cleanDive(); } rebuild() ; } // Return the top node of the heap CbcNode * CbcTree::top() const { return nodes_.front(); } // Add a node to the heap void CbcTree::push(CbcNode * x) { x->setNodeNumber(maximumNodeNumber_); maximumNodeNumber_++; # if CBC_DEBUG_HEAP > 2 CbcNodeInfo *info = x->nodeInfo() ; assert(info) ; std::cout << " HEAP: Pushing node " << x->nodeNumber() << "(" << std::hex << x << std::dec << ") obj " << x->objectiveValue() << ", ref " << info->decrement(0) << ", todo " << info->numberBranchesLeft() << ", refd by " << info->numberPointingToThis() << "." << std::endl ; assert(x->objectiveValue() != COIN_DBL_MAX); # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif x->setOnTree(true); nodes_.push_back(x); std::push_heap(nodes_.begin(), nodes_.end(), comparison_); # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif } // Remove the top node from the heap void CbcTree::pop() { # if CBC_DEBUG_HEAP > 2 CbcNode *node = nodes_.front() ; CbcNodeInfo *info = node->nodeInfo() ; assert(info) ; std::cout << " HEAP: Popping node " << node->nodeNumber() << "(" << std::hex << node << std::dec << ") obj " << node->objectiveValue() << ", ref " << info->decrement(0) << ", todo " << info->numberBranchesLeft() << ", refd by " << info->numberPointingToThis() << "." << std::endl ; # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif nodes_.front()->setOnTree(false); std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif } // Test if empty *** note may be overridden bool CbcTree::empty() { return nodes_.empty(); } /* Return the best node from the heap. Note that best is offered a chance (checkIsCutoff) to reevaluate itself and make arbitrary changes. A caller should be prepared to check that the returned node is acceptable. There's quite a bit of suspect code here, much of it disabled in some way. The net effect at present is to return the top node on the heap after offering the node an opportunity to reevaluate itself. Documentation for checkIsCutoff() puts no restrictions on allowable changes. -- lh, 100921 -- */ CbcNode * CbcTree::bestNode(double cutoff) { # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif /* This code is problematic. As of 100921, there's really no loop. If front() == null, an assert will trigger. checkIsCutoff seems to be work in progress; comments assert that it can make pretty much arbitrary changes to best. If best can change its objective, there's a good possibility the heap is invalid. */ CbcNode * best = NULL; while (!best && nodes_.size()) { best = nodes_.front(); if (best) assert(best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()); if (best && best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()) assert (best->nodeInfo()->numberBranchesLeft()); if (best && best->objectiveValue() >= cutoff) { // double check in case node can change its mind! best->checkIsCutoff(cutoff); } if (!best || best->objectiveValue() >= cutoff) { #ifdef JJF_ZERO // take off std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); delete best; best = NULL; #else // let code get rid of it assert (best); #endif } } /* See if the comparison object wants us to do a full scan with the alternative criteria. The net effect is to confirm best by the alternative criteria, or identify a competitor and erase it. This code is problematic. Nulling an arbitrary node will in general break the heap property. Disabled some time ago, as noted in several places. */ if (false && best && comparison_.test_->fullScan()) { CbcNode * saveBest = best; size_t n = nodes_.size(); size_t iBest = -1; for (size_t i = 0; i < n; i++) { // temp assert (nodes_[i]); assert (nodes_[i]->nodeInfo()); if (nodes_[i] && nodes_[i]->objectiveValue() != COIN_DBL_MAX && nodes_[i]->nodeInfo()) assert (nodes_[i]->nodeInfo()->numberBranchesLeft()); if (nodes_[i] && nodes_[i]->objectiveValue() < cutoff && comparison_.alternateTest(best, nodes_[i])) { best = nodes_[i]; iBest = i; } } if (best == saveBest) { // can pop // take off std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); } else { // make impossible nodes_[iBest] = NULL; } } else if (best) { # if CBC_DEBUG_HEAP > 2 CbcNode *node = nodes_.front() ; CbcNodeInfo *info = node->nodeInfo() ; assert(info) ; std::cout << " bestNode: Popping node " << node->nodeNumber() << "(" << std::hex << node << std::dec << ") obj " << node->objectiveValue() << ", ref " << info->decrement(0) << ", todo " << info->numberBranchesLeft() << ", refd by " << info->numberPointingToThis() << "." << std::endl ; # endif // take off std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); } #if CBC_DEBUG_HEAP > 0 validateHeap() ; #endif if (best) best->setOnTree(false); return best; } /*! \brief Prune the tree using an objective function cutoff This routine removes all nodes with objective worse than the specified cutoff value. */ void CbcTree::cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective) { # if CBC_DEBUG_HEAP > 1 std::cout << " cleanTree: beginning clean." << std::endl ; # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif int j; int nNodes = size(); CbcNode ** nodeArray = new CbcNode * [nNodes]; int * depth = new int [nNodes]; int k = 0; int kDelete = nNodes; bestPossibleObjective = 1.0e100 ; /* Destructively scan the heap. Nodes to be retained go into the front of nodeArray, nodes to be deleted into the back. Store the depth in a correlated array for nodes to be deleted. */ for (j = 0; j < nNodes; j++) { CbcNode * node = top(); pop(); double value = node ? node->objectiveValue() : COIN_DBL_MAX; if (node && value >= cutoff) { // double check in case node can change its mind! value = node->checkIsCutoff(cutoff); } if (value >= cutoff || !node->active()) { if (node) { nodeArray[--kDelete] = node; depth[kDelete] = node->depth(); } } else { bestPossibleObjective = CoinMin(bestPossibleObjective, value); nodeArray[k++] = node; } } /* Rebuild the heap using the retained nodes. */ for (j = 0; j < k; j++) { push(nodeArray[j]); } # if CBC_DEBUG_HEAP > 1 std::cout << " cleanTree: finished rebuild." << std::endl ; # endif # if CBC_DEBUG_HEAP > 0 validateHeap() ; # endif /* Sort the list of nodes to be deleted, nondecreasing. */ CoinSort_2(depth + kDelete, depth + nNodes, nodeArray + kDelete); /* Work back from deepest to shallowest. In spite of the name, addCuts1 is just a preparatory step. When it returns, the following will be true: * all cuts are removed from the solver's copy of the constraint system; * lastws will be a basis appropriate for the specified node; * variable bounds will be adjusted to be appropriate for the specified node; * addedCuts_ (returned via addedCuts()) will contain a list of cuts that should be added to the constraint system at this node (but they have not actually been added). Then we scan the cut list for the node. Decrement the reference count for the cut, and if it's gone to 0, really delete it. I don't yet see why the checks for status != basic and addedCuts_[i] != 0 are necessary. When reconstructing a node, these checks are used to skip over loose cuts, excluding them from the reconstituted basis. But here we're just interested in correcting the reference count. Tight/loose should make no difference. Arguably a separate routine should be used in place of addCuts1. It's doing more work than needed, modifying the model to match a subproblem at a node that will be discarded. Then again, we seem to need the basis. */ for (j = nNodes - 1; j >= kDelete; j--) { CbcNode * node = nodeArray[j]; CoinWarmStartBasis *lastws = model->getEmptyBasis() ; model->addCuts1(node, lastws); // Decrement cut counts assert (node); //assert (node->nodeInfo()); int numberLeft = (node->nodeInfo()) ? node->nodeInfo()->numberBranchesLeft() : 0; int i; for (i = 0; i < model->currentNumberCuts(); i++) { // take off node CoinWarmStartBasis::Status status = lastws->getArtifStatus(i + model->numberRowsAtContinuous()); if (status != CoinWarmStartBasis::basic && model->addedCuts()[i]) { if (!model->addedCuts()[i]->decrement(numberLeft)) delete model->addedCuts()[i]; } } // node should not have anything pointing to it if (node->nodeInfo()) node->nodeInfo()->throwAway(); delete node ; delete lastws ; } delete [] nodeArray; delete [] depth; #ifdef CBC_THREAD if (model->parallelMode() > 0 && model->master()) { // need to adjust for ones not on tree CbcBaseModel * master = model->master(); int numberThreads = master->numberThreads(); for (int i=0;ichild(i); if (child->node()) { // adjust double value = child->node()->objectiveValue(); bestPossibleObjective = CoinMin(bestPossibleObjective, value); } } } #endif } // Return the best node of the heap using alternate criterion CbcNode * CbcTree::bestAlternate() { size_t n = nodes_.size(); CbcNode * best = NULL; if (n) { best = nodes_[0]; for (size_t i = 1; i < n; i++) { if (comparison_.alternateTest(best, nodes_[i])) { best = nodes_[i]; } } } return best; } #ifdef JJF_ZERO // not used, reference removed in CbcModel.cpp CbcTreeArray::CbcTreeArray() : CbcTree(), lastNode_(NULL), lastNodePopped_(NULL), switches_(0) { } CbcTreeArray::~CbcTreeArray() { } // Copy constructor CbcTreeArray::CbcTreeArray ( const CbcTreeArray & rhs) : CbcTree(rhs), lastNode_(rhs.lastNode_), lastNodePopped_(rhs.lastNodePopped_), switches_(rhs.switches_) { } // Assignment operator CbcTreeArray & CbcTreeArray::operator=(const CbcTreeArray & rhs) { if (this != &rhs) { CbcTree::operator=(rhs); lastNode_ = rhs.lastNode_; lastNodePopped_ = rhs.lastNodePopped_; switches_ = rhs.switches_; } return *this; } // Clone CbcTree * CbcTreeArray::clone() const { return new CbcTreeArray(*this); } // Set comparison function and resort heap void CbcTreeArray::setComparison(CbcCompareBase &compare) { comparison_.test_ = &compare; rebuild() ; } // Add a node to the heap void CbcTreeArray::push(CbcNode * x) { /*printf("push obj %g, refcount %d, left %d, pointing to %d\n", x->objectiveValue(),x->nodeInfo()->decrement(0), x->nodeInfo()->numberBranchesLeft(),x->nodeInfo()->numberPointingToThis());*/ assert(x->objectiveValue() != COIN_DBL_MAX && x->nodeInfo()); x->setOnTree(true); if (lastNode_) { if (lastNode_->nodeInfo()->parent() == x->nodeInfo()) { // x is parent of lastNode_ so put x on heap //#define CBCTREE_PRINT #ifdef CBCTREE_PRINT printf("pushX x %x (%x at depth %d n %d) is parent of lastNode_ %x (%x at depth %d n %d)\n", x, x->nodeInfo(), x->depth(), x->nodeNumber(), lastNode_, lastNode_->nodeInfo(), lastNode_->depth(), lastNode_->nodeNumber()); #endif nodes_.push_back(x); } else { x->setNodeNumber(maximumNodeNumber_); maximumNodeNumber_++; #ifdef CBCTREE_PRINT printf("pushLast x %x (%x at depth %d n %d) is parent of lastNode_ %x (%x at depth %d n %d)\n", x, x->nodeInfo(), x->depth(), x->nodeNumber(), lastNode_, lastNode_->nodeInfo(), lastNode_->depth(), lastNode_->nodeNumber()); #endif nodes_.push_back(lastNode_); lastNode_ = x; } std::push_heap(nodes_.begin(), nodes_.end(), comparison_); } else { x->setNodeNumber(maximumNodeNumber_); maximumNodeNumber_++; if (x != lastNodePopped_) { lastNode_ = x; #ifdef CBCTREE_PRINT printf("pushNULL x %x (%x at depth %d n %d)\n", x, x->nodeInfo(), x->depth(), x->nodeNumber()); #endif } else { // means other way was infeasible #ifdef CBCTREE_PRINT printf("push_other_infeasible x %x (%x at depth %d n %d)\n", x, x->nodeInfo(), x->depth(), x->nodeNumber()); #endif nodes_.push_back(x); std::push_heap(nodes_.begin(), nodes_.end(), comparison_); } } } // Test if empty *** note may be overridden bool CbcTreeArray::empty() { return nodes_.empty() && (lastNode_ == NULL); } // Gets best node and takes off heap CbcNode * CbcTreeArray::bestNode(double cutoff) { CbcNode * best = NULL; // See if we want last node or best on heap if (lastNode_) { #ifdef CBCTREE_PRINT printf("Best lastNode_ %x (%x at depth %d) - nodeNumber %d obj %g\n", lastNode_, lastNode_->nodeInfo(), lastNode_->depth(), lastNode_->nodeNumber(), lastNode_->objectiveValue()); #endif assert (lastNode_->onTree()); int nodeNumber = lastNode_->nodeNumber(); bool useLastNode = false; if (nodeNumber + 1 == maximumNodeNumber_) { // diving - look further CbcCompareDefault * compareDefault = dynamic_cast (comparison_.test_); assert (compareDefault); double bestPossible = compareDefault->getBestPossible(); double cutoff = compareDefault->getCutoff(); double objValue = lastNode_->objectiveValue(); if (cutoff < 1.0e20) { if (objValue - bestPossible < 0.999*(cutoff - bestPossible)) useLastNode = true; } else { useLastNode = true; } } if (useLastNode) { lastNode_->setOnTree(false); best = lastNode_; lastNode_ = NULL; assert(best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()); if (best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()) assert (best->nodeInfo()->numberBranchesLeft()); if (best->objectiveValue() >= cutoff) { // double check in case node can change its mind! best->checkIsCutoff(cutoff); } lastNodePopped_ = best; return best; } else { // put on tree nodes_.push_back(lastNode_); lastNode_->setNodeNumber(maximumNodeNumber_); maximumNodeNumber_++; lastNode_ = NULL; std::push_heap(nodes_.begin(), nodes_.end(), comparison_); } } while (!best && nodes_.size()) { best = nodes_.front(); if (best) assert(best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()); if (best && best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()) assert (best->nodeInfo()->numberBranchesLeft()); if (best && best->objectiveValue() >= cutoff) { // double check in case node can change its mind! best->checkIsCutoff(cutoff); } if (!best || best->objectiveValue() >= cutoff) { // let code get rid of it assert (best); } } lastNodePopped_ = best; #ifdef CBCTREE_PRINT if (best) printf("Heap returning node %x (%x at depth %d) - nodeNumber %d - obj %g\n", best, best->nodeInfo(), best->depth(), best->nodeNumber(), best->objectiveValue()); else printf("Heap returning Null\n"); #endif if (best) { // take off std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); } #ifdef DEBUG_CBC_HEAP if (best) { int n = nodes_.size(); bool good = true; for (int i = 0; i < n; i++) { // temp assert (nodes_[i]); if (!comparison_.compareNodes(nodes_[i], best)) { good = false; CbcNode * x = nodes_[i]; printf("i=%d x is better nun %d depth %d obj %g, best nun %d depth %d obj %g\n", i, x->numberUnsatisfied(), x->depth(), x->objectiveValue(), best->numberUnsatisfied(), best->depth(), best->objectiveValue()); } } if (!good) { // compare best to all int i; for (i = 0; i < n; i++) { CbcNode * x = nodes_[i]; printf("i=%d x is nun %d depth %d obj %g", i, x->numberUnsatisfied(), x->depth(), x->objectiveValue()); if (!comparison_.compareNodes(x, best)) { printf(" - best is worse!\n"); } else { printf("\n"); } } // Now compare amongst rest for (i = 0; i < n; i++) { CbcNode * x = nodes_[i]; printf("For i=%d ", i); for (int j = i + 1; j < n; j++) { CbcNode * y = nodes_[j]; if (!comparison_.compareNodes(x, y)) { printf(" b %d", j); } else { printf(" w %d", j); } } printf("\n"); } assert(good); } } #endif if (best) best->setOnTree(false); return best; } double CbcTreeArray::getBestPossibleObjective() { double bestPossibleObjective = 1e100; for (int i = 0 ; i < static_cast (nodes_.size()) ; i++) { if (nodes_[i] && nodes_[i]->objectiveValue() < bestPossibleObjective) { bestPossibleObjective = nodes_[i]->objectiveValue(); } } if (lastNode_) { bestPossibleObjective = CoinMin(bestPossibleObjective, lastNode_->objectiveValue()); } #ifdef CBC_THREAD if (model->parallelMode() > 0 && model->master()) { // need to adjust for ones not on tree CbcBaseModel * master = model->master(); int numberThreads = master->numberThreads(); for (int i=0;ichild(i); if (child->node()) { // adjust double value = child->node()->objectiveValue(); bestPossibleObjective = CoinMin(bestPossibleObjective, value); } } } #endif CbcCompareDefault * compareDefault = dynamic_cast (comparison_.test_); assert (compareDefault); compareDefault->setBestPossible(bestPossibleObjective); return bestPossibleObjective; } /*! \brief Prune the tree using an objective function cutoff This routine removes all nodes with objective worst than the specified cutoff value. */ void CbcTreeArray::cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective) { int j; int nNodes = size(); int lastNode = nNodes + 1; CbcNode ** nodeArray = new CbcNode * [lastNode]; int * depth = new int [lastNode]; int k = 0; int kDelete = lastNode; bestPossibleObjective = 1.0e100 ; /* Destructively scan the heap. Nodes to be retained go into the front of nodeArray, nodes to be deleted into the back. Store the depth in a correlated array for nodes to be deleted. */ for (j = 0; j < nNodes; j++) { CbcNode * node = nodes_.front(); nodes_.front()->setOnTree(false); std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); double value = node ? node->objectiveValue() : COIN_DBL_MAX; if (node && value >= cutoff) { // double check in case node can change its mind! value = node->checkIsCutoff(cutoff); } if (value >= cutoff || !node->active()) { if (node) { nodeArray[--kDelete] = node; depth[kDelete] = node->depth(); } } else { bestPossibleObjective = CoinMin(bestPossibleObjective, value); nodeArray[k++] = node; } } #ifdef CBC_THREAD if (model->parallelMode() > 0 && model->master()) { // need to adjust for ones not on tree CbcBaseModel * master = model->master(); int numberThreads = master->numberThreads(); for (int i=0;ichild(i); if (child->node()) { // adjust double value = child->node()->objectiveValue(); bestPossibleObjective = CoinMin(bestPossibleObjective, value); } } } #endif if (lastNode_) { double value = lastNode_->objectiveValue(); bestPossibleObjective = CoinMin(bestPossibleObjective, value); if (value >= cutoff || !lastNode_->active()) { nodeArray[--kDelete] = lastNode_; depth[kDelete] = lastNode_->depth(); lastNode_ = NULL; } } CbcCompareDefault * compareDefault = dynamic_cast (comparison_.test_); assert (compareDefault); compareDefault->setBestPossible(bestPossibleObjective); compareDefault->setCutoff(cutoff); /* Rebuild the heap using the retained nodes. */ for (j = 0; j < k; j++) { CbcNode * node = nodeArray[j]; node->setOnTree(true); nodes_.push_back(node); std::push_heap(nodes_.begin(), nodes_.end(), comparison_); } /* Sort the list of nodes to be deleted, nondecreasing. */ CoinSort_2(depth + kDelete, depth + lastNode, nodeArray + kDelete); /* Work back from deepest to shallowest. In spite of the name, addCuts1 is just a preparatory step. When it returns, the following will be true: * all cuts are removed from the solver's copy of the constraint system; * lastws will be a basis appropriate for the specified node; * variable bounds will be adjusted to be appropriate for the specified node; * addedCuts_ (returned via addedCuts()) will contain a list of cuts that should be added to the constraint system at this node (but they have not actually been added). Then we scan the cut list for the node. Decrement the reference count for the cut, and if it's gone to 0, really delete it. I don't yet see why the checks for status != basic and addedCuts_[i] != 0 are necessary. When reconstructing a node, these checks are used to skip over loose cuts, excluding them from the reconstituted basis. But here we're just interested in correcting the reference count. Tight/loose should make no difference. Arguably a separate routine should be used in place of addCuts1. It's doing more work than needed, modifying the model to match a subproblem at a node that will be discarded. Then again, we seem to need the basis. */ for (j = lastNode - 1; j >= kDelete; j--) { CbcNode * node = nodeArray[j]; CoinWarmStartBasis *lastws = model->getEmptyBasis() ; model->addCuts1(node, lastws); // Decrement cut counts assert (node); //assert (node->nodeInfo()); int numberLeft = (node->nodeInfo()) ? node->nodeInfo()->numberBranchesLeft() : 0; int i; for (i = 0; i < model->currentNumberCuts(); i++) { // take off node CoinWarmStartBasis::Status status = lastws->getArtifStatus(i + model->numberRowsAtContinuous()); if (status != CoinWarmStartBasis::basic && model->addedCuts()[i]) { if (!model->addedCuts()[i]->decrement(numberLeft)) delete model->addedCuts()[i]; } } // node should not have anything pointing to it if (node->nodeInfo()) node->nodeInfo()->throwAway(); delete node ; delete lastws ; } delete [] nodeArray; delete [] depth; } #endif #else // defined(CBC_DUBIOUS_HEAP) /* Unclear whether this code is useful any longer. Likely stale. See note in CbcCompareDefault.hpp re. CBC_DUBIOUS_HEAP. -- lh, 100921 -- */ // Set comparison function and resort heap void CbcTree::setComparison(CbcCompareBase &compare) { comparison_.test_ = &compare; std::vector newNodes = nodes_; nodes_.resize(0); while (newNodes.size() > 0) { push( newNodes.back()); newNodes.pop_back(); } } // Return the top node of the heap CbcNode * CbcTree::top() const { return nodes_.front(); } // Add a node to the heap void CbcTree::push(CbcNode * x) { x->setNodeNumber(maximumNodeNumber_); maximumNodeNumber_++; /*printf("push obj %g, refcount %d, left %d, pointing to %d\n", x->objectiveValue(),x->nodeInfo()->decrement(0), x->nodeInfo()->numberBranchesLeft(),x->nodeInfo()->numberPointingToThis());*/ assert(x->objectiveValue() != COIN_DBL_MAX && x->nodeInfo()); #ifdef JJF_ZERO nodes_.push_back(x); push_heap(nodes_.begin(), nodes_.end(), comparison_); #else realpush(x); #endif } // Remove the top node from the heap void CbcTree::pop() { #ifdef JJF_ZERO std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); #else if (nodes_.size()) { //CbcNode* s = nodes_.front(); realpop(); //delete s; } assert (nodes_.size() >= 0); #endif } // Test if empty *** note may be overridden bool CbcTree::empty() { return nodes_.empty(); } // Gets best node and takes off heap CbcNode * CbcTree::bestNode(double cutoff) { CbcNode * best = NULL; while (!best && nodes_.size()) { best = nodes_.front(); if (best) assert(best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()); if (best && best->objectiveValue() != COIN_DBL_MAX && best->nodeInfo()) assert (best->nodeInfo()->numberBranchesLeft()); if (best && best->objectiveValue() >= cutoff) { // double check in case node can change its mind! best->checkIsCutoff(cutoff); } if (!best || best->objectiveValue() >= cutoff) { #ifdef JJF_ZERO // take off std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); delete best; best = NULL; #else // let code get rid of it assert (best); #endif } } // switched off for now if (best && comparison_.test_->fullScan() && false) { CbcNode * saveBest = best; int n = nodes_.size(); int iBest = -1; for (int i = 0; i < n; i++) { // temp assert (nodes_[i]); assert (nodes_[i]->nodeInfo()); if (nodes_[i] && nodes_[i]->objectiveValue() != COIN_DBL_MAX && nodes_[i]->nodeInfo()) assert (nodes_[i]->nodeInfo()->numberBranchesLeft()); if (nodes_[i] && nodes_[i]->objectiveValue() < cutoff && comparison_.alternateTest(best, nodes_[i])) { best = nodes_[i]; iBest = i; } } if (best == saveBest) { // can pop // take off std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); } else { // make impossible nodes_[iBest] = NULL; } } else if (best) { // take off #ifdef JJF_ZERO std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); #else realpop(); #endif } #ifdef DEBUG_CBC_HEAP if (best) { int n = nodes_.size(); bool good = true; for (int i = 0; i < n; i++) { // temp assert (nodes_[i]); if (!comparison_.compareNodes(nodes_[i], best)) { good = false; CbcNode * x = nodes_[i]; printf("i=%d x is better nun %d depth %d obj %g, best nun %d depth %d obj %g\n", i, x->numberUnsatisfied(), x->depth(), x->objectiveValue(), best->numberUnsatisfied(), best->depth(), best->objectiveValue()); } } if (!good) { // compare best to all int i; for (i = 0; i < n; i++) { CbcNode * x = nodes_[i]; printf("i=%d x is nun %d depth %d obj %g", i, x->numberUnsatisfied(), x->depth(), x->objectiveValue()); if (!comparison_.compareNodes(x, best)) { printf(" - best is worse!\n"); } else { printf("\n"); } } // Now compare amongst rest for (i = 0; i < n; i++) { CbcNode * x = nodes_[i]; printf("For i=%d ", i); for (int j = i + 1; j < n; j++) { CbcNode * y = nodes_[j]; if (!comparison_.compareNodes(x, y)) { printf(" b %d", j); } else { printf(" w %d", j); } } printf("\n"); } assert(good); } } #endif if (best) best->setOnTree(false); return best; } /*! \brief Prune the tree using an objective function cutoff This routine removes all nodes with objective worst than the specified cutoff value. */ void CbcTree::cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective) { int j; int nNodes = nodes_.size(); CbcNode ** nodeArray = new CbcNode * [nNodes]; int * depth = new int [nNodes]; int k = 0; int kDelete = nNodes; bestPossibleObjective = 1.0e100 ; /* Destructively scan the heap. Nodes to be retained go into the front of nodeArray, nodes to be deleted into the back. Store the depth in a correlated array for nodes to be deleted. */ for (j = 0; j < nNodes; j++) { CbcNode * node = top(); pop(); double value = node ? node->objectiveValue() : COIN_DBL_MAX; if (node && value >= cutoff) { // double check in case node can change its mind! value = node->checkIsCutoff(cutoff); } bestPossibleObjective = CoinMin(bestPossibleObjective, value); if (value >= cutoff) { if (node) { nodeArray[--kDelete] = node; depth[kDelete] = node->depth(); } } else { nodeArray[k++] = node; } } #ifdef CBC_THREAD if (model->parallelMode() > 0 && model->master()) { // need to adjust for ones not on tree CbcBaseModel * master = model->master(); int numberThreads = master->numberThreads(); for (int i=0;ichild(i); if (child->node()) { // adjust double value = child->node()->objectiveValue(); bestPossibleObjective = CoinMin(bestPossibleObjective, value); } } } #endif /* Rebuild the heap using the retained nodes. */ for (j = 0; j < k; j++) { push(nodeArray[j]); } /* Sort the list of nodes to be deleted, nondecreasing. */ CoinSort_2(depth + kDelete, depth + nNodes, nodeArray + kDelete); /* Work back from deepest to shallowest. In spite of the name, addCuts1 is just a preparatory step. When it returns, the following will be true: * all cuts are removed from the solver's copy of the constraint system; * lastws will be a basis appropriate for the specified node; * variable bounds will be adjusted to be appropriate for the specified node; * addedCuts_ (returned via addedCuts()) will contain a list of cuts that should be added to the constraint system at this node (but they have not actually been added). Then we scan the cut list for the node. Decrement the reference count for the cut, and if it's gone to 0, really delete it. I don't yet see why the checks for status != basic and addedCuts_[i] != 0 are necessary. When reconstructing a node, these checks are used to skip over loose cuts, excluding them from the reconstituted basis. But here we're just interested in correcting the reference count. Tight/loose should make no difference. Arguably a separate routine should be used in place of addCuts1. It's doing more work than needed, modifying the model to match a subproblem at a node that will be discarded. Then again, we seem to need the basis. */ for (j = nNodes - 1; j >= kDelete; j--) { CbcNode * node = nodeArray[j]; CoinWarmStartBasis *lastws = model->getEmptyBasis() ; model->addCuts1(node, lastws); // Decrement cut counts assert (node); //assert (node->nodeInfo()); int numberLeft = (node->nodeInfo()) ? node->nodeInfo()->numberBranchesLeft() : 0; int i; for (i = 0; i < model->currentNumberCuts(); i++) { // take off node CoinWarmStartBasis::Status status = lastws->getArtifStatus(i + model->numberRowsAtContinuous()); if (status != CoinWarmStartBasis::basic && model->addedCuts()[i]) { if (!model->addedCuts()[i]->decrement(numberLeft)) delete model->addedCuts()[i]; } } // node should not have anything pointing to it if (node->nodeInfo()) node->nodeInfo()->throwAway(); delete node ; delete lastws ; } delete [] nodeArray; delete [] depth; } // Return the best node of the heap using alternate criterion CbcNode * CbcTree::bestAlternate() { int n = nodes_.size(); CbcNode * best = NULL; if (n) { best = nodes_[0]; for (int i = 1; i < n; i++) { if (comparison_.alternateTest(best, nodes_[i])) { best = nodes_[i]; } } } return best; } void CbcTree::realpop() { if (nodes_.size() > 0) { nodes_[0] = nodes_.back(); nodes_.pop_back(); fixTop(); } assert (nodes_.size() >= 0); } /* After changing data in the top node, fix the heap */ void CbcTree::fixTop() { const int size = nodes_.size(); if (size > 1) { CbcNode** candidates = &nodes_[0]; CbcNode* s = candidates[0]; --candidates; int pos = 1; int ch; for (ch = 2; ch < size; pos = ch, ch *= 2) { if (!comparison_.compareNodes(candidates[ch+1], candidates[ch])) ++ch; if (!comparison_.compareNodes(s, candidates[ch])) break; candidates[pos] = candidates[ch]; } if (ch == size) { if (!comparison_.compareNodes(candidates[ch], s)) { candidates[pos] = candidates[ch]; pos = ch; } } candidates[pos] = s; } } void CbcTree::realpush(CbcNode * node) { node->setOnTree(true); nodes_.push_back(node); CbcNode** candidates = &nodes_[0]; --candidates; int pos = nodes_.size(); int ch; for (ch = pos / 2; ch != 0; pos = ch, ch /= 2) { if (!comparison_.compareNodes(candidates[ch], node)) break; candidates[pos] = candidates[ch]; } candidates[pos] = node; } #endif double CbcTree::getBestPossibleObjective() { double r_val = 1e100; for (int i = 0 ; i < static_cast (nodes_.size()) ; i++) { if (nodes_[i] && nodes_[i]->objectiveValue() < r_val) { r_val = nodes_[i]->objectiveValue(); } } return r_val; } Cbc-2.8.12/src/CbcCompareObjective.cpp0000644000076600007660000000354112131315050016067 0ustar coincoin// $Id: CbcCompareObjective.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCompareActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CbcMessage.hpp" #include "CbcModel.hpp" #include "CbcTree.hpp" #include "CbcCompareActual.hpp" #include "CoinError.hpp" #include "CbcCompareObjective.hpp" /** Default Constructor */ CbcCompareObjective::CbcCompareObjective () : CbcCompareBase() { test_ = this; } // Copy constructor CbcCompareObjective::CbcCompareObjective ( const CbcCompareObjective & rhs) : CbcCompareBase(rhs) { } // Clone CbcCompareBase * CbcCompareObjective::clone() const { return new CbcCompareObjective(*this); } // Assignment operator CbcCompareObjective & CbcCompareObjective::operator=( const CbcCompareObjective & rhs) { if (this != &rhs) { CbcCompareBase::operator=(rhs); } return *this; } // Destructor CbcCompareObjective::~CbcCompareObjective () { } // Returns true if y better than x bool CbcCompareObjective::test (CbcNode * x, CbcNode * y) { double testX = x->objectiveValue(); double testY = y->objectiveValue(); if (testX != testY) return testX > testY; else return equalityTest(x, y); // so ties will be broken in consistent manner } // Create C++ lines to get to current state void CbcCompareObjective::generateCpp( FILE * fp) { fprintf(fp, "0#include \"CbcCompareActual.hpp\"\n"); fprintf(fp, "3 CbcCompareObjective compare;\n"); fprintf(fp, "3 cbcModel->setNodeComparison(compare);\n"); } Cbc-2.8.12/src/CbcHeuristicDINS.cpp0000644000076600007660000003724212131315050015270 0ustar coincoin// $Id: CbcHeuristicDINS.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // edwin 12/5/09 carved out of CbcHeuristicRINS #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcHeuristicDINS.hpp" #include "CbcBranchActual.hpp" #include "CbcStrategy.hpp" #include "CglPreProcess.hpp" // Default Constructor CbcHeuristicDINS::CbcHeuristicDINS() : CbcHeuristic() { numberSolutions_ = 0; numberSuccesses_ = 0; numberTries_ = 0; howOften_ = 100; decayFactor_ = 0.5; maximumKeepSolutions_ = 5; numberKeptSolutions_ = 0; numberIntegers_ = -1; localSpace_ = 10; values_ = NULL; } // Constructor with model - assumed before cuts CbcHeuristicDINS::CbcHeuristicDINS(CbcModel & model) : CbcHeuristic(model) { numberSolutions_ = 0; numberSuccesses_ = 0; numberTries_ = 0; howOften_ = 100; decayFactor_ = 0.5; assert(model.solver()); maximumKeepSolutions_ = 5; numberKeptSolutions_ = 0; numberIntegers_ = -1; localSpace_ = 10; values_ = NULL; } // Destructor CbcHeuristicDINS::~CbcHeuristicDINS () { for (int i = 0; i < numberKeptSolutions_; i++) delete [] values_[i]; delete [] values_; } // Clone CbcHeuristic * CbcHeuristicDINS::clone() const { return new CbcHeuristicDINS(*this); } // Assignment operator CbcHeuristicDINS & CbcHeuristicDINS::operator=( const CbcHeuristicDINS & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); numberSolutions_ = rhs.numberSolutions_; howOften_ = rhs.howOften_; numberSuccesses_ = rhs.numberSuccesses_; numberTries_ = rhs.numberTries_; for (int i = 0; i < numberKeptSolutions_; i++) delete [] values_[i]; delete [] values_; maximumKeepSolutions_ = rhs.maximumKeepSolutions_; numberKeptSolutions_ = rhs.numberKeptSolutions_; numberIntegers_ = rhs.numberIntegers_; localSpace_ = rhs.localSpace_; if (model_ && rhs.values_) { assert (numberIntegers_ >= 0); values_ = new int * [maximumKeepSolutions_]; for (int i = 0; i < maximumKeepSolutions_; i++) values_[i] = CoinCopyOfArray(rhs.values_[i], numberIntegers_); } else { values_ = NULL; } } return *this; } // Create C++ lines to get to current state void CbcHeuristicDINS::generateCpp( FILE * fp) { CbcHeuristicDINS other; fprintf(fp, "0#include \"CbcHeuristicDINS.hpp\"\n"); fprintf(fp, "3 CbcHeuristicDINS heuristicDINS(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicDINS"); if (howOften_ != other.howOften_) fprintf(fp, "3 heuristicDINS.setHowOften(%d);\n", howOften_); else fprintf(fp, "4 heuristicDINS.setHowOften(%d);\n", howOften_); if (maximumKeepSolutions_ != other.maximumKeepSolutions_) fprintf(fp, "3 heuristicDINS.setMaximumKeep(%d);\n", maximumKeepSolutions_); else fprintf(fp, "4 heuristicDINS.setMaximumKeep(%d);\n", maximumKeepSolutions_); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicDINS);\n"); } // Copy constructor CbcHeuristicDINS::CbcHeuristicDINS(const CbcHeuristicDINS & rhs) : CbcHeuristic(rhs), numberSolutions_(rhs.numberSolutions_), howOften_(rhs.howOften_), numberSuccesses_(rhs.numberSuccesses_), numberTries_(rhs.numberTries_), maximumKeepSolutions_(rhs.maximumKeepSolutions_), numberKeptSolutions_(rhs.numberKeptSolutions_), numberIntegers_(rhs.numberIntegers_), localSpace_(rhs.localSpace_) { if (model_ && rhs.values_) { assert (numberIntegers_ >= 0); values_ = new int * [maximumKeepSolutions_]; for (int i = 0; i < maximumKeepSolutions_; i++) values_[i] = CoinCopyOfArray(rhs.values_[i], numberIntegers_); } else { values_ = NULL; } } // Resets stuff if model changes void CbcHeuristicDINS::resetModel(CbcModel * ) { //CbcHeuristic::resetModel(model); for (int i = 0; i < numberKeptSolutions_; i++) delete [] values_[i]; delete [] values_; numberKeptSolutions_ = 0; numberIntegers_ = -1; numberSolutions_ = 0; values_ = NULL; } /* First tries setting a variable to better value. If feasible then tries setting others. If not feasible then tries swaps Returns 1 if solution, 0 if not */ int CbcHeuristicDINS::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; int returnCode = 0; const double * bestSolution = model_->bestSolution(); if (!bestSolution) return 0; // No solution found yet if (numberSolutions_ < model_->getSolutionCount()) { // new solution - add info numberSolutions_ = model_->getSolutionCount(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); if (numberIntegers_ < 0) { numberIntegers_ = numberIntegers; assert (!values_); values_ = new int * [maximumKeepSolutions_]; for (int i = 0; i < maximumKeepSolutions_; i++) values_[i] = NULL; } else { assert (numberIntegers == numberIntegers_); } // move solutions (0 will be most recent) { int * temp = values_[maximumKeepSolutions_-1]; for (int i = maximumKeepSolutions_ - 1; i > 0; i--) values_[i] = values_[i-1]; if (!temp) temp = new int [numberIntegers_]; values_[0] = temp; } int i; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = bestSolution[iColumn]; double nearest = floor(value + 0.5); values_[0][i] = static_cast (nearest); } numberKeptSolutions_ = CoinMin(numberKeptSolutions_ + 1, maximumKeepSolutions_); } int finalReturnCode = 0; if (((model_->getNodeCount() % howOften_) == howOften_ / 2 || !model_->getNodeCount()) && (model_->getCurrentPassNumber() == 1 || model_->getCurrentPassNumber() == 999999)) { OsiSolverInterface * solver = model_->solver(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double * currentSolution = solver->getColSolution(); int localSpace = localSpace_; // 0 means finished but no solution, 1 solution, 2 node limit int status = -1; double cutoff = model_->getCutoff(); while (status) { status = 0; OsiSolverInterface * newSolver = cloneBut(3); // was model_->continuousSolver()->clone(); const double * colLower = solver->getColLower(); const double * colUpper = solver->getColUpper(); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); const double * continuousSolution = newSolver->getColSolution(); // Space for added constraint double * element = new double [numberIntegers]; int * column = new int [numberIntegers]; int i; int nFix = 0; int nCouldFix = 0; int nCouldFix2 = 0; int nBound = 0; int nEl = 0; double bias = localSpace; int okSame = numberKeptSolutions_ - 1; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double valueInt = bestSolution[iColumn]; if (valueInt < originalLower) { valueInt = originalLower; } else if (valueInt > originalUpper) { valueInt = originalUpper; } int intValue = static_cast (floor(valueInt + 0.5)); double currentValue = currentSolution[iColumn]; double currentLower = colLower[iColumn]; double currentUpper = colUpper[iColumn]; if (fabs(valueInt - currentValue) >= 0.5) { // Re-bound nBound++; if (intValue >= currentValue) { currentLower = CoinMax(currentLower, ceil(2 * currentValue - intValue)); currentUpper = intValue; } else { currentLower = intValue; currentUpper = CoinMin(currentUpper, floor(2 * currentValue - intValue)); } newSolver->setColLower(iColumn, currentLower); newSolver->setColUpper(iColumn, currentUpper); } else { // See if can fix bool canFix = false; double continuousValue = continuousSolution[iColumn]; if (fabs(currentValue - valueInt) < 10.0*primalTolerance) { if (currentUpper - currentLower > 1.0) { // General integer variable canFix = true; } else if (fabs(continuousValue - valueInt) < 10.0*primalTolerance) { int nSame = 1; //assert (intValue==values_[0][i]); for (int k = 1; k < numberKeptSolutions_; k++) { if (intValue == values_[k][i]) nSame++; } if (nSame >= okSame) { // can fix canFix = true; } else { nCouldFix++; } } else { nCouldFix2++; } } if (canFix) { newSolver->setColLower(iColumn, intValue); newSolver->setColUpper(iColumn, intValue); nFix++; } else { if (currentUpper - currentLower > 1.0) { // General integer variable currentLower = floor(currentValue); if (intValue >= currentLower && intValue <= currentLower + 1) { newSolver->setColLower(iColumn, currentLower); newSolver->setColUpper(iColumn, currentLower + 1.0); } else { // fix double value; if (intValue < currentLower) value = currentLower; else value = currentLower + 1; newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); nFix++; } } else { // 0-1 (ish) column[nEl] = iColumn; if (intValue == currentLower) { bias += currentLower; element[nEl++] = 1.0; } else if (intValue == currentUpper) { bias += currentUpper; element[nEl++] = -1.0; } else { printf("bad DINS logic\n"); abort(); } } } } } char generalPrint[200]; sprintf(generalPrint, "%d fixed, %d same as cont/int, %d same as int - %d bounded %d in cut\n", nFix, nCouldFix, nCouldFix2, nBound, nEl); model_->messageHandler()->message(CBC_FPUMP2, model_->messages()) << generalPrint << CoinMessageEol; if (nFix > numberIntegers / 10) { #ifdef JJF_ZERO newSolver->initialSolve(); printf("obj %g\n", newSolver->getObjValue()); for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; printf("%d new bounds %g %g - solutions %g %g\n", iColumn, newSolver->getColLower()[iColumn], newSolver->getColUpper()[iColumn], bestSolution[iColumn], currentSolution[iColumn]); } #endif if (nEl > 0) newSolver->addRow(nEl, column, element, -COIN_DBL_MAX, bias); //printf("%d integers have same value\n",nFix); returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, cutoff, "CbcHeuristicDINS"); if (returnCode < 0) { returnCode = 0; // returned on size status = 0; } else { numRuns_++; if ((returnCode&2) != 0) { // could add cut as complete search returnCode &= ~2; if ((returnCode&1) != 0) { numberSuccesses_++; status = 1; } else { // no solution status = 0; } } else { if ((returnCode&1) != 0) { numberSuccesses_++; status = 1; } else { // no solution but node limit status = 2; if (nEl) localSpace -= 5; else localSpace = -1; if (localSpace < 0) status = 0; } } if ((returnCode&1) != 0) { cutoff = CoinMin(cutoff, solutionValue - model_->getCutoffIncrement()); finalReturnCode = 1; } } } delete [] element; delete [] column; delete newSolver; } numberTries_++; if ((numberTries_ % 10) == 0 && numberSuccesses_*3 < numberTries_) howOften_ += static_cast (howOften_ * decayFactor_); } return finalReturnCode; } // update model void CbcHeuristicDINS::setModel(CbcModel * model) { model_ = model; // Get a copy of original matrix assert(model_->solver()); for (int i = 0; i < numberKeptSolutions_; i++) delete [] values_[i]; delete [] values_; numberKeptSolutions_ = 0; numberIntegers_ = -1; numberSolutions_ = 0; values_ = NULL; } Cbc-2.8.12/src/CbcFixVariable.hpp0000644000076600007660000000371012131315050015045 0ustar coincoin// $Id: CbcFixVariable.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #ifndef CbcFixVariable_H #define CbcFixVariable_H #include "CbcBranchBase.hpp" /** Class for consequent bounds. When a variable is branched on it normally interacts with other variables by means of equations. There are cases where we want to step outside LP and do something more directly e.g. fix bounds. This class is for that. A state of -9999 means at LB, +9999 means at UB, others mean if fixed to that value. */ class CbcFixVariable : public CbcConsequence { public: // Default Constructor CbcFixVariable (); // One useful Constructor CbcFixVariable (int numberStates, const int * states, const int * numberNewLower, const int ** newLowerValue, const int ** lowerColumn, const int * numberNewUpper, const int ** newUpperValue, const int ** upperColumn); // Copy constructor CbcFixVariable ( const CbcFixVariable & rhs); // Assignment operator CbcFixVariable & operator=( const CbcFixVariable & rhs); /// Clone virtual CbcConsequence * clone() const; /// Destructor virtual ~CbcFixVariable (); /** Apply to an LP solver. Action depends on state */ virtual void applyToSolver(OsiSolverInterface * solver, int state) const; protected: /// Number of states int numberStates_; /// Values of integers for various states int * states_; /// Start of information for each state (setting new lower) int * startLower_; /// Start of information for each state (setting new upper) int * startUpper_; /// For each variable new bounds double * newBound_; /// Variable int * variable_; }; #endif Cbc-2.8.12/src/CbcMessage.cpp0000644000076600007660000001402312136524567014253 0ustar coincoin/* $Id: CbcMessage.cpp 1916 2013-04-26 16:21:11Z tkr $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcMessage.hpp" #include typedef struct { CBC_Message internalNumber; int externalNumber; // or continuation char detail; const char * message; } Cbc_message; static Cbc_message us_english[] = { {CBC_END_GOOD, 1, 1, "Search completed - best objective %.16g, took %d iterations and %d nodes (%.2f seconds)"}, {CBC_MAXNODES, 3, 1, "Exiting on maximum nodes"}, {CBC_SOLUTION, 4, 1, "Integer solution of %g found after %d iterations and %d nodes (%.2f seconds)"}, {CBC_END, 5, 1, "Partial search - best objective %g (best possible %g), took %d iterations and %d nodes (%.2f seconds)"}, {CBC_INFEAS, 6, 1, "The LP relaxation is infeasible or too expensive"}, {CBC_STRONG, 7, 4, "Strong branching on %d (%d), down %g (%d) up %g (%d) value %g"}, {CBC_SOLINDIVIDUAL, 8, 2, "%d has value %g"}, {CBC_INTEGERINCREMENT, 9, 3, "Objective coefficients multiple of %g"}, {CBC_STATUS, 10, 1, "After %d nodes, %d on tree, %g best solution, best possible %g (%.2f seconds)"}, {CBC_GAP, 11, 1, "Exiting as integer gap of %g less than %g or %g%%"}, {CBC_ROUNDING, 12, 1, "Integer solution of %g found by %s after %d iterations and %d nodes (%.2f seconds)"}, {CBC_ROOT, 13, 1, "At root node, %d cuts changed objective from %g to %g in %d passes"}, {CBC_GENERATOR, 14, 1, "Cut generator %d (%s) - %d row cuts average %.1f elements, %d column cuts (%d active) %? in %.3f seconds - new frequency is %d"}, {CBC_BRANCH, 15, 3, "Node %d Obj %g Unsat %d depth %d"}, {CBC_STRONGSOL, 16, 1, "Integer solution of %g found by strong branching after %d iterations and %d nodes (%.2f seconds)"}, {CBC_VUB_PASS, 17, 1, "%d solved, %d variables fixed, %d tightened"}, {CBC_VUB_END, 18, 1, "After tightenVubs, %d variables fixed, %d tightened"}, {CBC_MAXSOLS, 19, 1, "Exiting on maximum solutions"}, {CBC_MAXTIME, 20, 1, "Exiting on maximum time"}, {CBC_NOTFEAS1, 21, 2, "On closer inspection node is infeasible"}, {CBC_NOTFEAS2, 22, 2, "On closer inspection objective value of %g above cutoff of %g"}, {CBC_NOTFEAS3, 23, 2, "Allowing solution, even though largest row infeasibility is %g"}, {CBC_TREE_SOL, 24, 1, "Integer solution of %g found by subtree after %d iterations and %d nodes (%.2f seconds)"}, {CBC_ITERATE_STRONG, 25, 3, "%d cleanup iterations before strong branching"}, {CBC_PRIORITY, 26, 1, "Setting priorities for objects %d to %d inclusive (out of %d)"}, {CBC_EVENT, 27, 1, "Exiting on user event"}, {CBC_START_SUB, 28, 1, "Starting sub-tree for %s - maximum nodes %d"}, {CBC_END_SUB, 29, 1, "Ending sub-tree for %s"}, {CBC_THREAD_STATS, 30, 1, "%s%? %d used %d times, waiting to start %g, %?%g cpu time,%? %g waiting for threads, %? %d locks, %g locked, %g waiting for locks"}, {CBC_CUTS_STATS, 31, 1, "%d added rows had average density of %g"}, {CBC_STRONG_STATS, 32, 1, "Strong branching done %d times (%d iterations), fathomed %d nodes and fixed %d variables"}, {CBC_SOLUTION2, 33, 1, "Integer solution of %g found (by alternate solver) after %d iterations and %d nodes (%.2f seconds)"}, {CBC_UNBOUNDED, 34, 1, "The LP relaxation is unbounded!"}, {CBC_OTHER_STATS, 35, 1, "Maximum depth %d, %g variables fixed on reduced cost"}, {CBC_HEURISTICS_OFF, 36, 1, "Heuristics switched off as %d branching objects are of wrong type"}, {CBC_STATUS2, 37, 1, "%d nodes, %d on tree, best %g - possible %g depth %d unsat %d its %d (%.2f seconds)"}, {CBC_FPUMP1, 38, 1, "%s"}, {CBC_FPUMP2, 39, 2, "%s"}, {CBC_STATUS3, 40, 1, "%d nodes (+%d), %d on tree, best %g - possible %g depth %d unsat %d its %d (+%d) (%.2f seconds)"}, {CBC_OTHER_STATS2, 41, 1, "Maximum depth %d, %g variables fixed on reduced cost (%d nodes in complete fathoming taking %d iterations)"}, {CBC_RELAXED1, 42, 1, "Possible objective of %.18g but variable %d is %g from integer value, integer tolerance %g"}, {CBC_RELAXED2, 43, 2, "Possible objective of %.18g but had to fudge solution with tolerance of %g - check scaling of problem?"}, {CBC_RESTART, 44, 1, "Reduced cost fixing - %d rows, %d columns - restarting search"}, {CBC_GENERAL, 45, 1, "%s"}, {CBC_ROOT_DETAIL, 46, 2, "Root node pass %d, %d rows, %d total tight cuts - objective %g"}, {CBC_CUTOFF_WARNING1, 47, 1, "Cutoff set to %g - equivalent to best solution of %g"}, {CBC_END_SOLUTION, 48, 2, "Final check on integer solution of %g found after %d iterations and %d nodes (%.2f seconds)"}, #ifndef NO_FATHOM_PRINT {CBC_FATHOM_CHANGE, 49, 1, "Complete fathoming at depth >= %d"}, #endif {CBC_MAXITERS, 50, 1, "Exiting on maximum number of iterations"}, {CBC_NOINT, 3007, 1, "No integer variables - nothing to do"}, {CBC_WARNING_STRONG, 3008, 1, "Strong branching is fixing too many variables, too expensively!"}, {CBC_DUMMY_END, 999999, 0, ""} }; /* Constructor */ CbcMessage::CbcMessage(Language language) : CoinMessages(sizeof(us_english) / sizeof(Cbc_message)) { language_ = language; strcpy(source_, "Cbc"); class_ = 0; // branch and bound Cbc_message * message = us_english; while (message->internalNumber != CBC_DUMMY_END) { CoinOneMessage oneMessage(message->externalNumber, message->detail, message->message); addMessage(message->internalNumber, oneMessage); message ++; } // Put into compact form toCompact(); // now override any language ones //switch (language) { //default: message = NULL; // break; //} // replace if any found if (message) { while (message->internalNumber != CBC_DUMMY_END) { replaceMessage(message->internalNumber, message->message); message ++; } } } Cbc-2.8.12/src/CbcHeuristicDive.cpp0000644000076600007660000013726112136455127015443 0ustar coincoin/* $Id: CbcHeuristicDive.cpp 1912 2013-04-26 10:43:35Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcHeuristicDive.hpp" #include "CbcStrategy.hpp" #include "CbcModel.hpp" #include "CbcSubProblem.hpp" #include "OsiAuxInfo.hpp" #include "CoinTime.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #endif //#define DIVE_FIX_BINARY_VARIABLES //#define DIVE_DEBUG // Default Constructor CbcHeuristicDive::CbcHeuristicDive() : CbcHeuristic() { // matrix and row copy will automatically be empty downLocks_ = NULL; upLocks_ = NULL; downArray_ = NULL; upArray_ = NULL; percentageToFix_ = 0.2; maxIterations_ = 100; maxSimplexIterations_ = 10000; maxSimplexIterationsAtRoot_ = 1000000; maxTime_ = 600; whereFrom_ = 255 - 2 - 16 + 256; decayFactor_ = 1.0; } // Constructor from model CbcHeuristicDive::CbcHeuristicDive(CbcModel & model) : CbcHeuristic(model) { downLocks_ = NULL; upLocks_ = NULL; downArray_ = NULL; upArray_ = NULL; // Get a copy of original matrix assert(model.solver()); // model may have empty matrix - wait until setModel const CoinPackedMatrix * matrix = model.solver()->getMatrixByCol(); if (matrix) { matrix_ = *matrix; matrixByRow_ = *model.solver()->getMatrixByRow(); validate(); } percentageToFix_ = 0.2; maxIterations_ = 100; maxSimplexIterations_ = 10000; maxSimplexIterationsAtRoot_ = 1000000; maxTime_ = 600; whereFrom_ = 255 - 2 - 16 + 256; decayFactor_ = 1.0; } // Destructor CbcHeuristicDive::~CbcHeuristicDive () { delete [] downLocks_; delete [] upLocks_; assert (!downArray_); } // Create C++ lines to get to current state void CbcHeuristicDive::generateCpp( FILE * fp, const char * heuristic) { // hard coded as CbcHeuristic virtual CbcHeuristic::generateCpp(fp, heuristic); if (percentageToFix_ != 0.2) fprintf(fp, "3 %s.setPercentageToFix(%.f);\n", heuristic, percentageToFix_); else fprintf(fp, "4 %s.setPercentageToFix(%.f);\n", heuristic, percentageToFix_); if (maxIterations_ != 100) fprintf(fp, "3 %s.setMaxIterations(%d);\n", heuristic, maxIterations_); else fprintf(fp, "4 %s.setMaxIterations(%d);\n", heuristic, maxIterations_); if (maxSimplexIterations_ != 10000) fprintf(fp, "3 %s.setMaxSimplexIterations(%d);\n", heuristic, maxSimplexIterations_); else fprintf(fp, "4 %s.setMaxSimplexIterations(%d);\n", heuristic, maxSimplexIterations_); if (maxTime_ != 600) fprintf(fp, "3 %s.setMaxTime(%.2f);\n", heuristic, maxTime_); else fprintf(fp, "4 %s.setMaxTime(%.2f);\n", heuristic, maxTime_); } // Copy constructor CbcHeuristicDive::CbcHeuristicDive(const CbcHeuristicDive & rhs) : CbcHeuristic(rhs), matrix_(rhs.matrix_), matrixByRow_(rhs.matrixByRow_), percentageToFix_(rhs.percentageToFix_), maxIterations_(rhs.maxIterations_), maxSimplexIterations_(rhs.maxSimplexIterations_), maxSimplexIterationsAtRoot_(rhs.maxSimplexIterationsAtRoot_), maxTime_(rhs.maxTime_) { downArray_ = NULL; upArray_ = NULL; if (rhs.downLocks_) { int numberIntegers = model_->numberIntegers(); downLocks_ = CoinCopyOfArray(rhs.downLocks_, numberIntegers); upLocks_ = CoinCopyOfArray(rhs.upLocks_, numberIntegers); } else { downLocks_ = NULL; upLocks_ = NULL; } } // Assignment operator CbcHeuristicDive & CbcHeuristicDive::operator=( const CbcHeuristicDive & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); matrix_ = rhs.matrix_; matrixByRow_ = rhs.matrixByRow_; percentageToFix_ = rhs.percentageToFix_; maxIterations_ = rhs.maxIterations_; maxSimplexIterations_ = rhs.maxSimplexIterations_; maxSimplexIterationsAtRoot_ = rhs.maxSimplexIterationsAtRoot_; maxTime_ = rhs.maxTime_; delete [] downLocks_; delete [] upLocks_; if (rhs.downLocks_) { int numberIntegers = model_->numberIntegers(); downLocks_ = CoinCopyOfArray(rhs.downLocks_, numberIntegers); upLocks_ = CoinCopyOfArray(rhs.upLocks_, numberIntegers); } else { downLocks_ = NULL; upLocks_ = NULL; } } return *this; } // Resets stuff if model changes void CbcHeuristicDive::resetModel(CbcModel * model) { model_ = model; assert(model_->solver()); // Get a copy of original matrix const CoinPackedMatrix * matrix = model_->solver()->getMatrixByCol(); // model may have empty matrix - wait until setModel if (matrix) { matrix_ = *matrix; matrixByRow_ = *model->solver()->getMatrixByRow(); validate(); } } // update model void CbcHeuristicDive::setModel(CbcModel * model) { model_ = model; assert(model_->solver()); // Get a copy of original matrix const CoinPackedMatrix * matrix = model_->solver()->getMatrixByCol(); if (matrix) { matrix_ = *matrix; matrixByRow_ = *model->solver()->getMatrixByRow(); // make sure model okay for heuristic validate(); } } bool CbcHeuristicDive::canHeuristicRun() { return shouldHeurRun_randomChoice(); } inline bool compareBinaryVars(const PseudoReducedCost obj1, const PseudoReducedCost obj2) { return obj1.pseudoRedCost > obj2.pseudoRedCost; } // inner part of dive int CbcHeuristicDive::solution(double & solutionValue, int & numberNodes, int & numberCuts, OsiRowCut ** cuts, CbcSubProblem ** & nodes, double * newSolution) { #ifdef DIVE_DEBUG int nRoundInfeasible = 0; int nRoundFeasible = 0; #endif int reasonToStop = 0; double time1 = CoinCpuTime(); int numberSimplexIterations = 0; int maxSimplexIterations = (model_->getNodeCount()) ? maxSimplexIterations_ : maxSimplexIterationsAtRoot_; // but can't be exactly coin_int_max maxSimplexIterations = CoinMin(maxSimplexIterations,COIN_INT_MAX>>3); OsiSolverInterface * solver = cloneBut(6); // was model_->solver()->clone(); # ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver); if (clpSolver) { ClpSimplex * clpSimplex = clpSolver->getModelPtr(); int oneSolveIts = clpSimplex->maximumIterations(); oneSolveIts = CoinMin(1000+2*(clpSimplex->numberRows()+clpSimplex->numberColumns()),oneSolveIts); clpSimplex->setMaximumIterations(oneSolveIts); if (!nodes) { // say give up easily clpSimplex->setMoreSpecialOptions(clpSimplex->moreSpecialOptions() | 64); } else { // get ray int specialOptions = clpSimplex->specialOptions(); specialOptions &= ~0x3100000; specialOptions |= 32; clpSimplex->setSpecialOptions(specialOptions); clpSolver->setSpecialOptions(clpSolver->specialOptions() | 1048576); if ((model_->moreSpecialOptions()&16777216)!=0) { // cutoff is constraint clpSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); } } } # endif const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); const double * solution = solver->getColSolution(); const double * objective = solver->getObjCoefficients(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); int numberRows = matrix_.getNumRows(); assert (numberRows <= solver->getNumRows()); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); double direction = solver->getObjSense(); // 1 for min, -1 for max double newSolutionValue = direction * solver->getObjValue(); int returnCode = 0; // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); #ifdef DIVE_FIX_BINARY_VARIABLES // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); #endif // Get solution array for heuristic solution int numberColumns = solver->getNumCols(); memcpy(newSolution, solution, numberColumns*sizeof(double)); // vectors to store the latest variables fixed at their bounds int* columnFixed = new int [numberIntegers]; double* originalBound = new double [numberIntegers+2*numberColumns]; double * lowerBefore = originalBound+numberIntegers; double * upperBefore = lowerBefore+numberColumns; memcpy(lowerBefore,lower,numberColumns*sizeof(double)); memcpy(upperBefore,upper,numberColumns*sizeof(double)); double * lastDjs=newSolution+numberColumns; bool * fixedAtLowerBound = new bool [numberIntegers]; PseudoReducedCost * candidate = new PseudoReducedCost [numberIntegers]; double * random = new double [numberIntegers]; int maxNumberAtBoundToFix = static_cast (floor(percentageToFix_ * numberIntegers)); assert (!maxNumberAtBoundToFix||!nodes); // count how many fractional variables int numberFractionalVariables = 0; for (int i = 0; i < numberIntegers; i++) { random[i] = randomNumberGenerator_.randomDouble() + 0.3; int iColumn = integerVariable[i]; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { numberFractionalVariables++; } } const double* reducedCost = NULL; // See if not NLP if (model_->solverCharacteristics()->reducedCostsAccurate()) reducedCost = solver->getReducedCost(); int iteration = 0; while (numberFractionalVariables) { iteration++; // initialize any data initializeData(); // select a fractional variable to bound int bestColumn = -1; int bestRound; // -1 rounds down, +1 rounds up bool canRound = selectVariableToBranch(solver, newSolution, bestColumn, bestRound); // if the solution is not trivially roundable, we don't try to round; // if the solution is trivially roundable, we try to round. However, // if the rounded solution is worse than the current incumbent, // then we don't round and proceed normally. In this case, the // bestColumn will be a trivially roundable variable if (canRound) { // check if by rounding all fractional variables // we get a solution with an objective value // better than the current best integer solution double delta = 0.0; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { assert(downLocks_[i] == 0 || upLocks_[i] == 0); double obj = objective[iColumn]; if (downLocks_[i] == 0 && upLocks_[i] == 0) { if (direction * obj >= 0.0) delta += (floor(value) - value) * obj; else delta += (ceil(value) - value) * obj; } else if (downLocks_[i] == 0) delta += (floor(value) - value) * obj; else delta += (ceil(value) - value) * obj; } } if (direction*(solver->getObjValue() + delta) < solutionValue) { #ifdef DIVE_DEBUG nRoundFeasible++; #endif if (!nodes||bestColumn<0) { // Round all the fractional variables for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { assert(downLocks_[i] == 0 || upLocks_[i] == 0); if (downLocks_[i] == 0 && upLocks_[i] == 0) { if (direction * objective[iColumn] >= 0.0) newSolution[iColumn] = floor(value); else newSolution[iColumn] = ceil(value); } else if (downLocks_[i] == 0) newSolution[iColumn] = floor(value); else newSolution[iColumn] = ceil(value); } } break; } else { // can't round if going to use in branching int i; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[bestColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { if (iColumn==bestColumn) { assert(downLocks_[i] == 0 || upLocks_[i] == 0); double obj = objective[bestColumn]; if (downLocks_[i] == 0 && upLocks_[i] == 0) { if (direction * obj >= 0.0) bestRound=-1; else bestRound=1; } else if (downLocks_[i] == 0) bestRound=-1; else bestRound=1; break; } } } } } #ifdef DIVE_DEBUG else nRoundInfeasible++; #endif } // do reduced cost fixing #ifdef DIVE_DEBUG int numberFixed = reducedCostFix(solver); std::cout << "numberReducedCostFixed = " << numberFixed << std::endl; #else reducedCostFix(solver); #endif int numberAtBoundFixed = 0; #ifdef DIVE_FIX_BINARY_VARIABLES // fix binary variables based on pseudo reduced cost if (binVarIndex_.size()) { int cnt = 0; int n = static_cast(binVarIndex_.size()); for (int j = 0; j < n; j++) { int iColumn1 = binVarIndex_[j]; double value = newSolution[iColumn1]; if (fabs(value) <= integerTolerance && lower[iColumn1] != upper[iColumn1]) { double maxPseudoReducedCost = 0.0; #ifdef DIVE_DEBUG std::cout << "iColumn1 = " << iColumn1 << ", value = " << value << std::endl; #endif int iRow = vbRowIndex_[j]; double chosenValue = 0.0; for (int k = rowStart[iRow]; k < rowStart[iRow] + rowLength[iRow]; k++) { int iColumn2 = column[k]; #ifdef DIVE_DEBUG std::cout << "iColumn2 = " << iColumn2 << std::endl; #endif if (iColumn1 != iColumn2) { double pseudoReducedCost = fabs(reducedCost[iColumn2] * elementByRow[k]); #ifdef DIVE_DEBUG int k2; for (k2 = rowStart[iRow]; k2 < rowStart[iRow] + rowLength[iRow]; k2++) { if (column[k2] == iColumn1) break; } std::cout << "reducedCost[" << iColumn2 << "] = " << reducedCost[iColumn2] << ", elementByRow[" << iColumn2 << "] = " << elementByRow[k] << ", elementByRow[" << iColumn1 << "] = " << elementByRow[k2] << ", pseudoRedCost = " << pseudoReducedCost << std::endl; #endif if (pseudoReducedCost > maxPseudoReducedCost) maxPseudoReducedCost = pseudoReducedCost; } else { // save value chosenValue = fabs(elementByRow[k]); } } assert (chosenValue); maxPseudoReducedCost /= chosenValue; #ifdef DIVE_DEBUG std::cout << ", maxPseudoRedCost = " << maxPseudoReducedCost << std::endl; #endif candidate[cnt].var = iColumn1; candidate[cnt++].pseudoRedCost = maxPseudoReducedCost; } } #ifdef DIVE_DEBUG std::cout << "candidates for rounding = " << cnt << std::endl; #endif std::sort(candidate, candidate + cnt, compareBinaryVars); for (int i = 0; i < cnt; i++) { int iColumn = candidate[i].var; if (numberAtBoundFixed < maxNumberAtBoundToFix) { columnFixed[numberAtBoundFixed] = iColumn; originalBound[numberAtBoundFixed] = upper[iColumn]; fixedAtLowerBound[numberAtBoundFixed] = true; solver->setColUpper(iColumn, lower[iColumn]); numberAtBoundFixed++; if (numberAtBoundFixed == maxNumberAtBoundToFix) break; } } } #endif // fix other integer variables that are at their bounds int cnt = 0; #ifdef GAP double gap = 1.0e30; #endif if (reducedCost && true) { #ifndef JJF_ONE cnt = fixOtherVariables(solver, solution, candidate, random); #else #ifdef GAP double cutoff = model_->getCutoff() ; if (cutoff < 1.0e20 && false) { double direction = solver->getObjSense() ; gap = cutoff - solver->getObjValue() * direction ; gap *= 0.1; // Fix more if plausible double tolerance; solver->getDblParam(OsiDualTolerance, tolerance) ; if (gap <= 0.0) gap = tolerance; gap += 100.0 * tolerance; } int nOverGap = 0; #endif int numberFree = 0; int numberFixed = 0; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { numberFree++; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) <= integerTolerance) { candidate[cnt].var = iColumn; candidate[cnt++].pseudoRedCost = fabs(reducedCost[iColumn] * random[i]); #ifdef GAP if (fabs(reducedCost[iColumn]) > gap) nOverGap++; #endif } } else { numberFixed++; } } #ifdef GAP int nLeft = maxNumberAtBoundToFix - numberAtBoundFixed; #ifdef CLP_INVESTIGATE4 printf("cutoff %g obj %g nover %d - %d free, %d fixed\n", cutoff, solver->getObjValue(), nOverGap, numberFree, numberFixed); #endif if (nOverGap > nLeft && true) { nOverGap = CoinMin(nOverGap, nLeft + maxNumberAtBoundToFix / 2); maxNumberAtBoundToFix += nOverGap - nLeft; } #else #ifdef CLP_INVESTIGATE4 printf("cutoff %g obj %g - %d free, %d fixed\n", model_->getCutoff(), solver->getObjValue(), numberFree, numberFixed); #endif #endif #endif } else { for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) <= integerTolerance) { candidate[cnt].var = iColumn; candidate[cnt++].pseudoRedCost = numberIntegers - i; } } } } std::sort(candidate, candidate + cnt, compareBinaryVars); for (int i = 0; i < cnt; i++) { int iColumn = candidate[i].var; if (upper[iColumn] > lower[iColumn]) { double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) <= integerTolerance && numberAtBoundFixed < maxNumberAtBoundToFix) { // fix the variable at one of its bounds if (fabs(lower[iColumn] - value) <= integerTolerance) { columnFixed[numberAtBoundFixed] = iColumn; originalBound[numberAtBoundFixed] = upper[iColumn]; fixedAtLowerBound[numberAtBoundFixed] = true; solver->setColUpper(iColumn, lower[iColumn]); numberAtBoundFixed++; } else if (fabs(upper[iColumn] - value) <= integerTolerance) { columnFixed[numberAtBoundFixed] = iColumn; originalBound[numberAtBoundFixed] = lower[iColumn]; fixedAtLowerBound[numberAtBoundFixed] = false; solver->setColLower(iColumn, upper[iColumn]); numberAtBoundFixed++; } if (numberAtBoundFixed == maxNumberAtBoundToFix) break; } } } #ifdef DIVE_DEBUG std::cout << "numberAtBoundFixed = " << numberAtBoundFixed << std::endl; #endif double originalBoundBestColumn; double bestColumnValue; int whichWay; if (bestColumn >= 0) { bestColumnValue = newSolution[bestColumn]; if (bestRound < 0) { originalBoundBestColumn = upper[bestColumn]; solver->setColUpper(bestColumn, floor(bestColumnValue)); whichWay=0; } else { originalBoundBestColumn = lower[bestColumn]; solver->setColLower(bestColumn, ceil(bestColumnValue)); whichWay=1; } } else { break; } int originalBestRound = bestRound; int saveModelOptions = model_->specialOptions(); while (1) { model_->setSpecialOptions(saveModelOptions | 2048); solver->resolve(); model_->setSpecialOptions(saveModelOptions); if (!solver->isAbandoned()&&!solver->isIterationLimitReached()) { numberSimplexIterations += solver->getIterationCount(); } else { numberSimplexIterations = maxSimplexIterations + 1; reasonToStop += 100; break; } if (!solver->isProvenOptimal()) { if (nodes) { if (solver->isProvenPrimalInfeasible()) { if (maxSimplexIterationsAtRoot_!=COIN_INT_MAX) { // stop now printf("stopping on first infeasibility\n"); break; } else if (cuts) { // can do conflict cut printf("could do intermediate conflict cut\n"); bool localCut; OsiRowCut * cut = model_->conflictCut(solver,localCut); if (cut) { if (!localCut) { model_->makePartialCut(cut,solver); cuts[numberCuts++]=cut; } else { delete cut; } } } } else { reasonToStop += 10; break; } } if (numberAtBoundFixed > 0) { // Remove the bound fix for variables that were at bounds for (int i = 0; i < numberAtBoundFixed; i++) { int iColFixed = columnFixed[i]; if (fixedAtLowerBound[i]) solver->setColUpper(iColFixed, originalBound[i]); else solver->setColLower(iColFixed, originalBound[i]); } numberAtBoundFixed = 0; } else if (bestRound == originalBestRound) { bestRound *= (-1); whichWay |=2; if (bestRound < 0) { solver->setColLower(bestColumn, originalBoundBestColumn); solver->setColUpper(bestColumn, floor(bestColumnValue)); } else { solver->setColLower(bestColumn, ceil(bestColumnValue)); solver->setColUpper(bestColumn, originalBoundBestColumn); } } else break; } else break; } if (!solver->isProvenOptimal() || direction*solver->getObjValue() >= solutionValue) { reasonToStop += 1; } else if (iteration > maxIterations_) { reasonToStop += 2; } else if (CoinCpuTime() - time1 > maxTime_) { reasonToStop += 3; } else if (numberSimplexIterations > maxSimplexIterations) { reasonToStop += 4; // also switch off #ifdef CLP_INVESTIGATE printf("switching off diving as too many iterations %d, %d allowed\n", numberSimplexIterations, maxSimplexIterations); #endif when_ = 0; } else if (solver->getIterationCount() > 1000 && iteration > 3 && !nodes) { reasonToStop += 5; // also switch off #ifdef CLP_INVESTIGATE printf("switching off diving one iteration took %d iterations (total %d)\n", solver->getIterationCount(), numberSimplexIterations); #endif when_ = 0; } memcpy(newSolution, solution, numberColumns*sizeof(double)); numberFractionalVariables = 0; double sumFractionalVariables=0.0; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; double away = fabs(floor(value + 0.5) - value); if (away > integerTolerance) { numberFractionalVariables++; sumFractionalVariables += away; } } if (nodes) { // save information //branchValues[numberNodes]=bestColumnValue; //statuses[numberNodes]=whichWay+(bestColumn<<2); //bases[numberNodes]=solver->getWarmStart(); ClpSimplex * simplex = clpSolver->getModelPtr(); CbcSubProblem * sub = new CbcSubProblem(clpSolver,lowerBefore,upperBefore, simplex->statusArray(),numberNodes); nodes[numberNodes]=sub; // other stuff sub->branchValue_=bestColumnValue; sub->problemStatus_=whichWay; sub->branchVariable_=bestColumn; sub->objectiveValue_ = simplex->objectiveValue(); sub->sumInfeasibilities_ = sumFractionalVariables; sub->numberInfeasibilities_ = numberFractionalVariables; printf("DiveNode %d column %d way %d bvalue %g obj %g\n", numberNodes,sub->branchVariable_,sub->problemStatus_, sub->branchValue_,sub->objectiveValue_); numberNodes++; if (solver->isProvenOptimal()) { memcpy(lastDjs,solver->getReducedCost(),numberColumns*sizeof(double)); memcpy(lowerBefore,lower,numberColumns*sizeof(double)); memcpy(upperBefore,upper,numberColumns*sizeof(double)); } } if (!numberFractionalVariables||reasonToStop) break; } if (nodes) { printf("Exiting dive for reason %d\n",reasonToStop); if (reasonToStop>1) { printf("problems in diving\n"); int whichWay=nodes[numberNodes-1]->problemStatus_; CbcSubProblem * sub; if ((whichWay&2)==0) { // leave both ways sub = new CbcSubProblem(*nodes[numberNodes-1]); nodes[numberNodes++]=sub; } else { sub = nodes[numberNodes-1]; } if ((whichWay&1)==0) sub->problemStatus_=whichWay|1; else sub->problemStatus_=whichWay&~1; } if (!numberNodes) { // was good at start! - create fake clpSolver->resolve(); ClpSimplex * simplex = clpSolver->getModelPtr(); CbcSubProblem * sub = new CbcSubProblem(clpSolver,lowerBefore,upperBefore, simplex->statusArray(),numberNodes); nodes[numberNodes]=sub; // other stuff sub->branchValue_=0.0; sub->problemStatus_=0; sub->branchVariable_=-1; sub->objectiveValue_ = simplex->objectiveValue(); sub->sumInfeasibilities_ = 0.0; sub->numberInfeasibilities_ = 0; printf("DiveNode %d column %d way %d bvalue %g obj %g\n", numberNodes,sub->branchVariable_,sub->problemStatus_, sub->branchValue_,sub->objectiveValue_); numberNodes++; assert (solver->isProvenOptimal()); } nodes[numberNodes-1]->problemStatus_ |= 256*reasonToStop; // use djs as well if (solver->isProvenPrimalInfeasible()&&cuts) { // can do conflict cut and re-order printf("could do final conflict cut\n"); bool localCut; OsiRowCut * cut = model_->conflictCut(solver,localCut); if (cut) { printf("cut - need to use conflict and previous djs\n"); if (!localCut) { model_->makePartialCut(cut,solver); cuts[numberCuts++]=cut; } else { delete cut; } } else { printf("bad conflict - just use previous djs\n"); } } } // re-compute new solution value double objOffset = 0.0; solver->getDblParam(OsiObjOffset, objOffset); newSolutionValue = -objOffset; for (int i = 0 ; i < numberColumns ; i++ ) newSolutionValue += objective[i] * newSolution[i]; newSolutionValue *= direction; //printf("new solution value %g %g\n",newSolutionValue,solutionValue); if (newSolutionValue < solutionValue && !reasonToStop) { double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); // paranoid check memset(rowActivity, 0, numberRows*sizeof(double)); for (int i = 0; i < numberColumns; i++) { int j; double value = newSolution[i]; if (value) { for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } // check was approximately feasible bool feasible = true; for (int i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i]) { if (rowActivity[i] < rowLower[i] - 1000.0*primalTolerance) feasible = false; } else if (rowActivity[i] > rowUpper[i]) { if (rowActivity[i] > rowUpper[i] + 1000.0*primalTolerance) feasible = false; } } for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { feasible = false; break; } } if (feasible) { // new solution solutionValue = newSolutionValue; //printf("** Solution of %g found by CbcHeuristicDive\n",newSolutionValue); //if (cuts) //clpSolver->getModelPtr()->writeMps("good8.mps", 2); returnCode = 1; } else { // Can easily happen //printf("Debug CbcHeuristicDive giving bad solution\n"); } delete [] rowActivity; } #ifdef DIVE_DEBUG std::cout << "nRoundInfeasible = " << nRoundInfeasible << ", nRoundFeasible = " << nRoundFeasible << ", returnCode = " << returnCode << ", reasonToStop = " << reasonToStop << ", simplexIts = " << numberSimplexIterations << ", iterations = " << iteration << std::endl; #endif delete [] columnFixed; delete [] originalBound; delete [] fixedAtLowerBound; delete [] candidate; delete [] random; delete [] downArray_; downArray_ = NULL; delete [] upArray_; upArray_ = NULL; delete solver; return returnCode; } // See if diving will give better solution // Sets value of solution // Returns 1 if solution, 0 if not int CbcHeuristicDive::solution(double & solutionValue, double * betterSolution) { int nodeCount = model_->getNodeCount(); if (feasibilityPumpOptions_>0 && (nodeCount % feasibilityPumpOptions_) != 0) return 0; #ifdef DIVE_DEBUG std::cout << "solutionValue = " << solutionValue << std::endl; #endif ++numCouldRun_; // test if the heuristic can run if (!canHeuristicRun()) return 0; #ifdef JJF_ZERO // See if to do if (!when() || (when() % 10 == 1 && model_->phase() != 1) || (when() % 10 == 2 && (model_->phase() != 2 && model_->phase() != 3))) return 0; // switched off #endif // Get solution array for heuristic solution int numberColumns = model_->solver()->getNumCols(); double * newSolution = new double [numberColumns]; int numberCuts=0; int numberNodes=-1; CbcSubProblem ** nodes=NULL; int returnCode=solution(solutionValue,numberNodes,numberCuts, NULL,nodes, newSolution); if (returnCode==1) memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); delete [] newSolution; return returnCode; } /* returns 0 if no solution, 1 if valid solution with better objective value than one passed in also returns list of nodes This does Fractional Diving */ int CbcHeuristicDive::fathom(CbcModel * model, int & numberNodes, CbcSubProblem ** & nodes) { double solutionValue = model->getCutoff(); numberNodes=0; // Get solution array for heuristic solution int numberColumns = model_->solver()->getNumCols(); double * newSolution = new double [4*numberColumns]; double * lastDjs = newSolution+numberColumns; double * originalLower = lastDjs+numberColumns; double * originalUpper = originalLower+numberColumns; memcpy(originalLower,model_->solver()->getColLower(), numberColumns*sizeof(double)); memcpy(originalUpper,model_->solver()->getColUpper(), numberColumns*sizeof(double)); int numberCuts=0; OsiRowCut ** cuts = NULL; //new OsiRowCut * [maxIterations_]; nodes=new CbcSubProblem * [maxIterations_+2]; int returnCode=solution(solutionValue,numberNodes,numberCuts, cuts,nodes, newSolution); if (returnCode==1) { // copy to best solution ? or put in solver printf("Solution from heuristic fathom\n"); } int numberFeasibleNodes=numberNodes; if (returnCode!=1) numberFeasibleNodes--; if (numberFeasibleNodes>0) { CoinWarmStartBasis * basis = nodes[numberFeasibleNodes-1]->status_; //double * sort = new double [numberFeasibleNodes]; //int * whichNode = new int [numberFeasibleNodes]; //int numberNodesNew=0; // use djs on previous unless feasible for (int iNode=0;iNodebranchValue_; int iStatus=sub->problemStatus_; int iColumn = sub->branchVariable_; bool secondBranch = (iStatus&2)!=0; bool branchUp; if (!secondBranch) branchUp = (iStatus&1)!=0; else branchUp = (iStatus&1)==0; double djValue=lastDjs[iColumn]; sub->djValue_=fabs(djValue); if (!branchUp&&floor(branchValue)==originalLower[iColumn] &&basis->getStructStatus(iColumn) == CoinWarmStartBasis::atLowerBound) { if (djValue>0.0) { // naturally goes to LB printf("ignoring branch down on %d (node %d) from value of %g - branch was %s - dj %g\n", iColumn,iNode,branchValue,secondBranch ? "second" : "first", djValue); sub->problemStatus_ |= 4; //} else { // put on list //sort[numberNodesNew]=djValue; //whichNode[numberNodesNew++]=iNode; } } else if (branchUp&&ceil(branchValue)==originalUpper[iColumn] &&basis->getStructStatus(iColumn) == CoinWarmStartBasis::atUpperBound) { if (djValue<0.0) { // naturally goes to UB printf("ignoring branch up on %d (node %d) from value of %g - branch was %s - dj %g\n", iColumn,iNode,branchValue,secondBranch ? "second" : "first", djValue); sub->problemStatus_ |= 4; //} else { // put on list //sort[numberNodesNew]=-djValue; //whichNode[numberNodesNew++]=iNode; } } } // use conflict to order nodes for (int iCut=0;iCutnumberIntegers() != model_->numberObjects() && (model_->numberObjects() || (model_->specialOptions()&1024) == 0)) { int numberOdd = 0; for (int i = 0; i < model_->numberObjects(); i++) { if (!model_->object(i)->canDoHeuristics()) numberOdd++; } if (numberOdd) setWhen(0); } } int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); delete [] downLocks_; delete [] upLocks_; downLocks_ = new unsigned short [numberIntegers]; upLocks_ = new unsigned short [numberIntegers]; // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); const double * rowLower = model_->solver()->getRowLower(); const double * rowUpper = model_->solver()->getRowUpper(); for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; int down = 0; int up = 0; if (columnLength[iColumn] > 65535) { setWhen(0); break; // unlikely to work } for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (rowLower[iRow] > -1.0e20 && rowUpper[iRow] < 1.0e20) { up++; down++; } else if (element[j] > 0.0) { if (rowUpper[iRow] < 1.0e20) up++; else down++; } else { if (rowLower[iRow] > -1.0e20) up++; else down++; } } downLocks_[i] = static_cast (down); upLocks_[i] = static_cast (up); } #ifdef DIVE_FIX_BINARY_VARIABLES selectBinaryVariables(); #endif } // Select candidate binary variables for fixing void CbcHeuristicDive::selectBinaryVariables() { // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); const int numberRows = matrixByRow_.getNumRows(); const int numberCols = matrixByRow_.getNumCols(); const double * lower = model_->solver()->getColLower(); const double * upper = model_->solver()->getColUpper(); const double * rowLower = model_->solver()->getRowLower(); const double * rowUpper = model_->solver()->getRowUpper(); // const char * integerType = model_->integerType(); // const int numberIntegers = model_->numberIntegers(); // const int * integerVariable = model_->integerVariable(); const double * objective = model_->solver()->getObjCoefficients(); // vector to store the row number of variable bound rows int* rowIndexes = new int [numberCols]; memset(rowIndexes, -1, numberCols*sizeof(int)); for (int i = 0; i < numberRows; i++) { int positiveBinary = -1; int negativeBinary = -1; int nPositiveOther = 0; int nNegativeOther = 0; for (int k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) { int iColumn = column[k]; if (model_->solver()->isInteger(iColumn) && lower[iColumn] == 0.0 && upper[iColumn] == 1.0 && objective[iColumn] == 0.0 && elementByRow[k] > 0.0 && positiveBinary < 0) positiveBinary = iColumn; else if (model_->solver()->isInteger(iColumn) && lower[iColumn] == 0.0 && upper[iColumn] == 1.0 && objective[iColumn] == 0.0 && elementByRow[k] < 0.0 && negativeBinary < 0) negativeBinary = iColumn; else if ((elementByRow[k] > 0.0 && lower[iColumn] >= 0.0) || (elementByRow[k] < 0.0 && upper[iColumn] <= 0.0)) nPositiveOther++; else if ((elementByRow[k] > 0.0 && lower[iColumn] <= 0.0) || (elementByRow[k] < 0.0 && upper[iColumn] >= 0.0)) nNegativeOther++; if (nPositiveOther > 0 && nNegativeOther > 0) break; } int binVar = -1; if (positiveBinary >= 0 && (negativeBinary >= 0 || nNegativeOther > 0) && nPositiveOther == 0 && rowLower[i] == 0.0 && rowUpper[i] > 0.0) binVar = positiveBinary; else if (negativeBinary >= 0 && (positiveBinary >= 0 || nPositiveOther > 0) && nNegativeOther == 0 && rowLower[i] < 0.0 && rowUpper[i] == 0.0) binVar = negativeBinary; if (binVar >= 0) { if (rowIndexes[binVar] == -1) rowIndexes[binVar] = i; else if (rowIndexes[binVar] >= 0) rowIndexes[binVar] = -2; } } for (int j = 0; j < numberCols; j++) { if (rowIndexes[j] >= 0) { binVarIndex_.push_back(j); vbRowIndex_.push_back(rowIndexes[j]); } } #ifdef DIVE_DEBUG std::cout << "number vub Binary = " << binVarIndex_.size() << std::endl; #endif delete [] rowIndexes; } /* Perform reduced cost fixing on integer variables. The variables in question are already nonbasic at bound. We're just nailing down the current situation. */ int CbcHeuristicDive::reducedCostFix (OsiSolverInterface* solver) { //return 0; // temp #ifndef JJF_ONE if (!model_->solverCharacteristics()->reducedCostsAccurate()) return 0; //NLP #endif double cutoff = model_->getCutoff() ; if (cutoff > 1.0e20) return 0; #ifdef DIVE_DEBUG std::cout << "cutoff = " << cutoff << std::endl; #endif double direction = solver->getObjSense() ; double gap = cutoff - solver->getObjValue() * direction ; gap *= 0.5; // Fix more double tolerance; solver->getDblParam(OsiDualTolerance, tolerance) ; if (gap <= 0.0) gap = tolerance; //return 0; gap += 100.0 * tolerance; double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); const double *lower = solver->getColLower() ; const double *upper = solver->getColUpper() ; const double *solution = solver->getColSolution() ; const double *reducedCost = solver->getReducedCost() ; int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int numberFixed = 0 ; # ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver); ClpSimplex * clpSimplex = NULL; if (clpSolver) clpSimplex = clpSolver->getModelPtr(); # endif for (int i = 0 ; i < numberIntegers ; i++) { int iColumn = integerVariable[i] ; double djValue = direction * reducedCost[iColumn] ; if (upper[iColumn] - lower[iColumn] > integerTolerance) { if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) { #ifdef COIN_HAS_CLP // may just have been fixed before if (clpSimplex) { if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) { #ifdef COIN_DEVELOP printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n", iColumn, clpSimplex->getColumnStatus(iColumn), djValue, gap, lower[iColumn], upper[iColumn]); #endif } else { assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atLowerBound || clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed); } } #endif solver->setColUpper(iColumn, lower[iColumn]) ; numberFixed++ ; } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) { #ifdef COIN_HAS_CLP // may just have been fixed before if (clpSimplex) { if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) { #ifdef COIN_DEVELOP printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n", iColumn, clpSimplex->getColumnStatus(iColumn), djValue, gap, lower[iColumn], upper[iColumn]); #endif } else { assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atUpperBound || clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed); } } #endif solver->setColLower(iColumn, upper[iColumn]) ; numberFixed++ ; } } } return numberFixed; } // Fix other variables at bounds int CbcHeuristicDive::fixOtherVariables(OsiSolverInterface * solver, const double * solution, PseudoReducedCost * candidate, const double * random) { const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double* reducedCost = solver->getReducedCost(); // fix other integer variables that are at their bounds int cnt = 0; #ifdef GAP double direction = solver->getObjSense(); // 1 for min, -1 for max double gap = 1.0e30; #endif #ifdef GAP double cutoff = model_->getCutoff() ; if (cutoff < 1.0e20 && false) { double direction = solver->getObjSense() ; gap = cutoff - solver->getObjValue() * direction ; gap *= 0.1; // Fix more if plausible double tolerance; solver->getDblParam(OsiDualTolerance, tolerance) ; if (gap <= 0.0) gap = tolerance; gap += 100.0 * tolerance; } int nOverGap = 0; #endif int numberFree = 0; int numberFixedAlready = 0; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { numberFree++; double value = solution[iColumn]; if (fabs(floor(value + 0.5) - value) <= integerTolerance) { candidate[cnt].var = iColumn; candidate[cnt++].pseudoRedCost = fabs(reducedCost[iColumn] * random[i]); #ifdef GAP if (fabs(reducedCost[iColumn]) > gap) nOverGap++; #endif } } else { numberFixedAlready++; } } #ifdef GAP int nLeft = maxNumberToFix - numberFixedAlready; #ifdef CLP_INVESTIGATE4 printf("cutoff %g obj %g nover %d - %d free, %d fixed\n", cutoff, solver->getObjValue(), nOverGap, numberFree, numberFixedAlready); #endif if (nOverGap > nLeft && true) { nOverGap = CoinMin(nOverGap, nLeft + maxNumberToFix / 2); maxNumberToFix += nOverGap - nLeft; } #else #ifdef CLP_INVESTIGATE4 printf("cutoff %g obj %g - %d free, %d fixed\n", model_->getCutoff(), solver->getObjValue(), numberFree, numberFixedAlready); #endif #endif return cnt; } Cbc-2.8.12/src/CbcHeuristicRandRound.cpp0000644000076600007660000004234412131315050016426 0ustar coincoin/* $Id: CbcHeuristicRandRound.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include #include "CoinHelperFunctions.hpp" #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcHeuristicRandRound.hpp" #include "OsiClpSolverInterface.hpp" #include "CoinTime.hpp" static inline int intRand(const int range) { return static_cast (floor(CoinDrand48() * range)); } // Default Constructor CbcHeuristicRandRound::CbcHeuristicRandRound() : CbcHeuristic() { } // Constructor with model - assumed before cuts CbcHeuristicRandRound::CbcHeuristicRandRound(CbcModel & model) : CbcHeuristic(model) { model_ = &model; setWhen(1); } // Destructor CbcHeuristicRandRound::~CbcHeuristicRandRound () { } // Clone CbcHeuristic * CbcHeuristicRandRound::clone() const { return new CbcHeuristicRandRound(*this); } // Create C++ lines to get to current state void CbcHeuristicRandRound::generateCpp( FILE * fp) { CbcHeuristicRandRound other; fprintf(fp, "0#include \"CbcHeuristicRandRound.hpp\"\n"); fprintf(fp, "3 CbcHeuristicRandRound heuristicPFX(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicPFX"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicPFX);\n"); } // Copy constructor CbcHeuristicRandRound::CbcHeuristicRandRound(const CbcHeuristicRandRound & rhs) : CbcHeuristic(rhs) { } // Assignment operator CbcHeuristicRandRound & CbcHeuristicRandRound::operator=( const CbcHeuristicRandRound & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); } return *this; } // Resets stuff if model changes void CbcHeuristicRandRound::resetModel(CbcModel * model) { CbcHeuristic::resetModel(model); } /* Randomized Rounding Heuristic Returns 1 if solution, 0 if not */ int CbcHeuristicRandRound::solution(double & solutionValue, double * betterSolution) { // rlh: Todo: Memory Cleanup // std::cout << "Entering the Randomized Rounding Heuristic" << std::endl; setWhen(1); // setWhen(1) didn't have the effect I expected (e.g., run once). // Run only once. // // See if at root node bool atRoot = model_->getNodeCount() == 0; int passNumber = model_->getCurrentPassNumber(); // Just do once if (!atRoot || passNumber != 1) { // std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl; return 0; } std::cout << "Entering the Randomized Rounding Heuristic" << std::endl; typedef struct { int numberSolutions; int maximumSolutions; int numberColumns; double ** solution; int * numberUnsatisfied; } clpSolution; double start = CoinCpuTime(); numCouldRun_++; // // Todo: Ask JJHF what "number of times // the heuristic could run" means. OsiSolverInterface * solver = model_->solver()->clone(); double primalTolerance ; solver->getDblParam(OsiPrimalTolerance, primalTolerance) ; OsiClpSolverInterface * clpSolver = dynamic_cast (solver); assert (clpSolver); ClpSimplex * simplex = clpSolver->getModelPtr(); // Initialize the structure holding the solutions for the Simplex iterations clpSolution solutions; // Set typeStruct field of ClpTrustedData struct to 1 to indicate // desired behavior for RandRound heuristic (which is what?) ClpTrustedData trustedSolutions; trustedSolutions.typeStruct = 1; trustedSolutions.data = &solutions; solutions.numberSolutions = 0; solutions.maximumSolutions = 0; solutions.numberColumns = simplex->numberColumns(); solutions.solution = NULL; solutions.numberUnsatisfied = NULL; simplex->setTrustedUserPointer(&trustedSolutions); // Solve from all slack to get some points simplex->allSlackBasis(); // Calling primal() invalidates pointers to some rim vectors, // like...row sense (!) simplex->primal(); // 1. Okay - so a workaround would be to copy the data I want BEFORE // calling primal. // 2. Another approach is to ask the simplex solvers NOT to mess up my // rims. // 3. See freeCachedResults() for what is getting // deleted. Everything else points into the structure. // ...or use collower and colupper rather than rowsense. // ..store address of where one of these // Store the basic problem information // -Get the number of columns, rows and rhs vector int numCols = clpSolver->getNumCols(); int numRows = clpSolver->getNumRows(); // Find the integer variables (use columnType(?)) // One if not continuous, that is binary or general integer) // columnType() = 0 continuous // = 1 binary // = 2 general integer bool * varClassInt = new bool[numCols]; const char* columnType = clpSolver->columnType(); int numGenInt = 0; for (int i = 0; i < numCols; i++) { if (clpSolver->isContinuous(i)) varClassInt[i] = 0; else varClassInt[i] = 1; if (columnType[i] == 2) numGenInt++; } // Heuristic is for problems with general integer variables. // If there are none, quit. if (numGenInt++ < 1) { delete [] varClassInt ; std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl; return 0; } // -Get the rows sense const char * rowSense; rowSense = clpSolver->getRowSense(); // -Get the objective coefficients double *originalObjCoeff = CoinCopyOfArray(clpSolver->getObjCoefficients(), numCols); // -Get the matrix of the problem // rlh: look at using sparse representation double ** matrix = new double * [numRows]; for (int i = 0; i < numRows; i++) { matrix[i] = new double[numCols]; for (int j = 0; j < numCols; j++) matrix[i][j] = 0; } const CoinPackedMatrix* matrixByRow = clpSolver->getMatrixByRow(); const double * matrixElements = matrixByRow->getElements(); const int * matrixIndices = matrixByRow->getIndices(); const int * matrixStarts = matrixByRow->getVectorStarts(); for (int j = 0; j < numRows; j++) { for (int i = matrixStarts[j]; i < matrixStarts[j+1]; i++) { matrix[j][matrixIndices[i]] = matrixElements[i]; } } double * newObj = new double [numCols]; srand ( static_cast(time(NULL) + 1)); int randNum; // Shuffle the rows: // Put the rows in a random order // so that the optimal solution is a different corner point than the // starting point. int * index = new int [numRows]; for (int i = 0; i < numRows; i++) index[i] = i; for (int i = 0; i < numRows; i++) { int temp = index[i]; int randNumTemp = i + intRand(numRows - i); index[i] = index[randNumTemp]; index[randNumTemp] = temp; } // Start finding corner points by iteratively doing the following: // - contruct a randomly tilted objective // - solve for (int i = 0; i < numRows; i++) { // TODO: that 10,000 could be a param in the member data if (solutions.numberSolutions > 10000) break; randNum = intRand(2); for (int j = 0; j < numCols; j++) { // for row i and column j vary the coefficient "a bit" if (randNum == 1) // if the element is zero, then set the new obj // coefficient to 0.1 (i.e., round up) if (fabs(matrix[index[i]][j]) < primalTolerance) newObj[j] = 0.1; else // if the element is nonzero, then increase the new obj // coefficient "a bit" newObj[j] = matrix[index[i]][j] * 1.1; else // if randnum is 2, then // if the element is zero, then set the new obj coeffient // to NEGATIVE 0.1 (i.e., round down) if (fabs(matrix[index[i]][j]) < primalTolerance) newObj[j] = -0.1; else // if the element is nonzero, then DEcrease the new obj coeffienct "a bit" newObj[j] = matrix[index[i]][j] * 0.9; } // Use the new "tilted" objective clpSolver->setObjective(newObj); // Based on the row sense, we decide whether to max or min if (rowSense[i] == 'L') clpSolver->setObjSense(-1); else clpSolver->setObjSense(1); // Solve with primal simplex simplex->primal(1); // rlh+ll: This was the original code. But we already have the // model pointer (it's in simplex). And, calling getModelPtr() // invalidates the cached data in the OsiClpSolverInterface // object, which means our precious rowsens is lost. So let's // not use the line below... /******* clpSolver->getModelPtr()->primal(1); */ printf("---------------------------------------------------------------- %d\n", i); } // Iteratively do this process until... // either you reach the max number of corner points (aka 10K) // or all the rows have been used as an objective. // Look at solutions int numberSolutions = solutions.numberSolutions; //const char * integerInfo = simplex->integerInformation(); //const double * columnLower = simplex->columnLower(); //const double * columnUpper = simplex->columnUpper(); printf("there are %d solutions\n", numberSolutions); // Up to here we have all the corner points // Now we need to do the random walks and roundings double ** cornerPoints = new double * [numberSolutions]; for (int j = 0; j < numberSolutions; j++) cornerPoints[j] = solutions.solution[j]; bool feasibility = 1; // rlh: use some COIN max instead of 1e30 (?) double bestObj = 1e30; std::vector< std::vector > feasibles; int numFeasibles = 0; // Check the feasibility of the corner points int numCornerPoints = numberSolutions; const double * rhs = clpSolver->getRightHandSide(); // rlh: row sense hasn't changed. why a fresh copy? // Delete next line. rowSense = clpSolver->getRowSense(); for (int i = 0; i < numCornerPoints; i++) { //get the objective value for this this point double objValue = 0; for (int k = 0; k < numCols; k++) objValue += cornerPoints[i][k] * originalObjCoeff[k]; if (objValue < bestObj) { // check integer feasibility feasibility = 1; for (int j = 0; j < numCols; j++) { if (varClassInt[j]) { double closest = floor(cornerPoints[i][j] + 0.5); if (fabs(cornerPoints[i][j] - closest) > primalTolerance) { feasibility = 0; break; } } } // check all constraints satisfied if (feasibility) { for (int irow = 0; irow < numRows; irow++) { double lhs = 0; for (int j = 0; j < numCols; j++) { lhs += matrix[irow][j] * cornerPoints[i][j]; } if (rowSense[irow] == 'L' && lhs > rhs[irow] + primalTolerance) { feasibility = 0; break; } if (rowSense[irow] == 'G' && lhs < rhs[irow] - primalTolerance) { feasibility = 0; break; } if (rowSense[irow] == 'E' && (lhs - rhs[irow] > primalTolerance || lhs - rhs[irow] < -primalTolerance)) { feasibility = 0; break; } } } if (feasibility) { numFeasibles++; feasibles.push_back(std::vector (numCols)); for (int k = 0; k < numCols; k++) feasibles[numFeasibles-1][k] = cornerPoints[i][k]; printf("obj: %f\n", objValue); if (objValue < bestObj) bestObj = objValue; } } } int numFeasibleCorners; numFeasibleCorners = numFeasibles; //find the center of gravity of the corner points as the first random point double * rp = new double[numCols]; for (int i = 0; i < numCols; i++) { rp[i] = 0; for (int j = 0; j < numCornerPoints; j++) { rp[i] += cornerPoints[j][i]; } rp[i] = rp[i] / numCornerPoints; } //------------------------------------------- //main loop: // -generate the next random point // -round the random point // -check the feasibility of the random point //------------------------------------------- srand ( static_cast(time(NULL) + 1)); int numRandomPoints = 0; while (numRandomPoints < 50000) { numRandomPoints++; //generate the next random point int randomIndex = intRand(numCornerPoints); double random = CoinDrand48(); for (int i = 0; i < numCols; i++) { rp[i] = (random * (cornerPoints[randomIndex][i] - rp[i])) + rp[i]; } //CRISP ROUNDING //round the random point just generated double * roundRp = new double[numCols]; for (int i = 0; i < numCols; i++) { roundRp[i] = rp[i]; if (varClassInt[i]) { if (rp[i] >= 0) { if (fmod(rp[i], 1) > 0.5) roundRp[i] = floor(rp[i]) + 1; else roundRp[i] = floor(rp[i]); } else { if (fabs(fmod(rp[i], 1)) > 0.5) roundRp[i] = floor(rp[i]); else roundRp[i] = floor(rp[i]) + 1; } } } //SOFT ROUNDING // Look at original files for the "how to" on soft rounding; // Soft rounding omitted here. //Check the feasibility of the rounded random point // -Check the feasibility // -Get the rows sense rowSense = clpSolver->getRowSense(); rhs = clpSolver->getRightHandSide(); //get the objective value for this feasible point double objValue = 0; for (int i = 0; i < numCols; i++) objValue += roundRp[i] * originalObjCoeff[i]; if (objValue < bestObj) { feasibility = 1; for (int i = 0; i < numRows; i++) { double lhs = 0; for (int j = 0; j < numCols; j++) { lhs += matrix[i][j] * roundRp[j]; } if (rowSense[i] == 'L' && lhs > rhs[i] + primalTolerance) { feasibility = 0; break; } if (rowSense[i] == 'G' && lhs < rhs[i] - primalTolerance) { feasibility = 0; break; } if (rowSense[i] == 'E' && (lhs - rhs[i] > primalTolerance || lhs - rhs[i] < -primalTolerance)) { feasibility = 0; break; } } if (feasibility) { printf("Feasible Found.\n"); printf("%.2f\n", CoinCpuTime() - start); numFeasibles++; feasibles.push_back(std::vector (numCols)); for (int i = 0; i < numCols; i++) feasibles[numFeasibles-1][i] = roundRp[i]; printf("obj: %f\n", objValue); if (objValue < bestObj) bestObj = objValue; } } delete [] roundRp; } printf("Number of Feasible Corners: %d\n", numFeasibleCorners); printf("Number of Feasibles Found: %d\n", numFeasibles); if (numFeasibles > 0) printf("Best Objective: %f\n", bestObj); printf("time: %.2f\n", CoinCpuTime() - start); if (numFeasibles == 0) { // cleanup delete [] varClassInt; for (int i = 0; i < numRows; i++) delete matrix[i]; delete [] matrix; delete [] newObj; delete [] index; for (int i = 0; i < numberSolutions; i++) delete cornerPoints[i]; delete [] cornerPoints; delete [] rp; return 0; } // We found something better solutionValue = bestObj; for (int k = 0; k < numCols; k++) { betterSolution[k] = feasibles[numFeasibles-1][k]; } delete [] varClassInt; for (int i = 0; i < numRows; i++) delete matrix[i]; delete [] matrix; delete [] newObj; delete [] index; for (int i = 0; i < numberSolutions; i++) delete cornerPoints[i]; delete [] cornerPoints; delete [] rp; std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl; return 1; } // update model void CbcHeuristicRandRound::setModel(CbcModel * model) { CbcHeuristic::setModel(model); } Cbc-2.8.12/src/CbcHeuristicDiveVectorLength.hpp0000644000076600007660000000320612131315050017745 0ustar coincoin/* $Id: CbcHeuristicDiveVectorLength.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicDiveVectorLength_H #define CbcHeuristicDiveVectorLength_H #include "CbcHeuristicDive.hpp" /** DiveVectorLength class */ class CbcHeuristicDiveVectorLength : public CbcHeuristicDive { public: // Default Constructor CbcHeuristicDiveVectorLength (); // Constructor with model - assumed before cuts CbcHeuristicDiveVectorLength (CbcModel & model); // Copy constructor CbcHeuristicDiveVectorLength ( const CbcHeuristicDiveVectorLength &); // Destructor ~CbcHeuristicDiveVectorLength (); /// Clone virtual CbcHeuristicDiveVectorLength * clone() const; /// Assignment operator CbcHeuristicDiveVectorLength & operator=(const CbcHeuristicDiveVectorLength& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Selects the next variable to branch on /** Returns true if all the fractional variables can be trivially rounded. Returns false, if there is at least one fractional variable that is not trivially roundable. In this case, the bestColumn returned will not be trivially roundable. */ virtual bool selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound); }; #endif Cbc-2.8.12/src/CbcBranchDynamic.hpp0000644000076600007660000001634111510742604015370 0ustar coincoin/* $Id: CbcBranchDynamic.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcBranchDynamic_H #define CbcBranchDynamic_H #include "CoinPackedMatrix.hpp" #include "CbcSimpleIntegerDynamicPseudoCost.hpp" #include "CbcBranchActual.hpp" /** Branching decision dynamic class This class implements a simple algorithm (betterBranch()) for choosing a branching variable when dynamic pseudo costs. */ class CbcBranchDynamicDecision : public CbcBranchDecision { public: // Default Constructor CbcBranchDynamicDecision (); // Copy constructor CbcBranchDynamicDecision ( const CbcBranchDynamicDecision &); virtual ~CbcBranchDynamicDecision(); /// Clone virtual CbcBranchDecision * clone() const; /// Initialize, e.g. before the start of branch selection at a node virtual void initialize(CbcModel * model); /** \brief Compare two branching objects. Return nonzero if \p thisOne is better than \p bestSoFar. The routine compares branches using the values supplied in \p numInfUp and \p numInfDn until a solution is found by search, after which it uses the values supplied in \p changeUp and \p changeDn. The best branching object seen so far and the associated parameter values are remembered in the \c CbcBranchDynamicDecision object. The nonzero return value is +1 if the up branch is preferred, -1 if the down branch is preferred. As the names imply, the assumption is that the values supplied for \p numInfUp and \p numInfDn will be the number of infeasibilities reported by the branching object, and \p changeUp and \p changeDn will be the estimated change in objective. Other measures can be used if desired. Because an \c CbcBranchDynamicDecision object remembers the current best branching candidate (#bestObject_) as well as the values used in the comparison, the parameter \p bestSoFar is redundant, hence unused. */ virtual int betterBranch(CbcBranchingObject * thisOne, CbcBranchingObject * bestSoFar, double changeUp, int numInfUp, double changeDn, int numInfDn); /** Sets or gets best criterion so far */ virtual void setBestCriterion(double value); virtual double getBestCriterion() const; /** Says whether this method can handle both methods - 1 better, 2 best, 3 both */ virtual int whichMethod() { return 3; } /** Saves a clone of current branching object. Can be used to update information on object causing branch - after branch */ virtual void saveBranchingObject(OsiBranchingObject * object) ; /** Pass in information on branch just done. assumes object can get information from solver */ virtual void updateInformation(OsiSolverInterface * solver, const CbcNode * node); private: /// Illegal Assignment operator CbcBranchDynamicDecision & operator=(const CbcBranchDynamicDecision& rhs); /// data /// "best" so far double bestCriterion_; /// Change up for best double bestChangeUp_; /// Number of infeasibilities for up int bestNumberUp_; /// Change down for best double bestChangeDown_; /// Number of infeasibilities for down int bestNumberDown_; /// Pointer to best branching object CbcBranchingObject * bestObject_; }; /** Simple branching object for an integer variable with pseudo costs This object can specify a two-way branch on an integer variable. For each arm of the branch, the upper and lower bounds on the variable can be independently specified. Variable_ holds the index of the integer variable in the integerVariable_ array of the model. */ class CbcDynamicPseudoCostBranchingObject : public CbcIntegerBranchingObject { public: /// Default constructor CbcDynamicPseudoCostBranchingObject (); /** Create a standard floor/ceiling branch object Specifies a simple two-way branch. Let \p value = x*. One arm of the branch will be is lb <= x <= floor(x*), the other ceil(x*) <= x <= ub. Specify way = -1 to set the object state to perform the down arm first, way = 1 for the up arm. */ CbcDynamicPseudoCostBranchingObject (CbcModel *model, int variable, int way , double value, CbcSimpleIntegerDynamicPseudoCost * object) ; /** Create a degenerate branch object Specifies a `one-way branch'. Calling branch() for this object will always result in lowerValue <= x <= upperValue. Used to fix a variable when lowerValue = upperValue. */ CbcDynamicPseudoCostBranchingObject (CbcModel *model, int variable, int way, double lowerValue, double upperValue) ; /// Copy constructor CbcDynamicPseudoCostBranchingObject ( const CbcDynamicPseudoCostBranchingObject &); /// Assignment operator CbcDynamicPseudoCostBranchingObject & operator= (const CbcDynamicPseudoCostBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; /// Destructor virtual ~CbcDynamicPseudoCostBranchingObject (); /// Does part of constructor void fillPart (int variable, int way , double value, CbcSimpleIntegerDynamicPseudoCost * object) ; using CbcBranchingObject::branch ; /** \brief Sets the bounds for the variable according to the current arm of the branch and advances the object state to the next arm. This version also changes guessed objective value */ virtual double branch(); /** Some branchingObjects may claim to be able to skip strong branching. If so they have to fill in CbcStrongInfo. The object mention in incoming CbcStrongInfo must match. Returns nonzero if skip is wanted */ virtual int fillStrongInfo( CbcStrongInfo & info); /// Change in guessed inline double changeInGuessed() const { return changeInGuessed_; } /// Set change in guessed inline void setChangeInGuessed(double value) { changeInGuessed_ = value; } /// Return object inline CbcSimpleIntegerDynamicPseudoCost * object() const { return object_; } /// Set object inline void setObject(CbcSimpleIntegerDynamicPseudoCost * object) { object_ = object; } /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return DynamicPseudoCostBranchObj; } // LL: compareOriginalObject and compareBranchingObject are inherited from // CbcIntegerBranchingObject thus need not be declared/defined here. After // all, this kind of branching object is simply using pseudocosts to make // decisions, but once the decisions are made they are the same kind as in // the underlying class. protected: /// Change in guessed objective value for next branch double changeInGuessed_; /// Pointer back to object CbcSimpleIntegerDynamicPseudoCost * object_; }; #endif Cbc-2.8.12/src/config_cbc.h.in0000644000076600007660000000042312131315050014360 0ustar coincoin/* src/config_cbc.h.in. */ /* Version number of project */ #undef CBC_VERSION /* Major Version number of project */ #undef CBC_VERSION_MAJOR /* Minor Version number of project */ #undef CBC_VERSION_MINOR /* Release Version number of project */ #undef CBC_VERSION_RELEASE Cbc-2.8.12/src/CbcHeuristicRINS.hpp0000644000076600007660000000522712131315050015311 0ustar coincoin/* $Id: CbcHeuristicRINS.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicRINS_H #define CbcHeuristicRINS_H #include "CbcHeuristic.hpp" // for backward compatibility include 3 other headers #include "CbcHeuristicRENS.hpp" #include "CbcHeuristicDINS.hpp" #include "CbcHeuristicVND.hpp" /** LocalSearch class */ class CbcHeuristicRINS : public CbcHeuristic { public: // Default Constructor CbcHeuristicRINS (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicRINS (CbcModel & model); // Copy constructor CbcHeuristicRINS ( const CbcHeuristicRINS &); // Destructor ~CbcHeuristicRINS (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicRINS & operator=(const CbcHeuristicRINS& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) This does Relaxation Induced Neighborhood Search */ virtual int solution(double & objectiveValue, double * newSolution); /// This version fixes stuff and does IP int solutionFix(double & objectiveValue, double * newSolution, const int * keep); /// Sets how often to do it inline void setHowOften(int value) { howOften_ = value; } /// Used array so we can set inline char * used() const { return used_; } /// Resets lastNode inline void setLastNode(int value) { lastNode_ = value; } protected: // Data /// Number of solutions so we can do something at solution int numberSolutions_; /// How often to do (code can change) int howOften_; /// Number of successes int numberSuccesses_; /// Number of tries int numberTries_; /** State of fixing continuous variables - 0 - not tried +n - this divisor makes small enough -n - this divisor still not small enough */ int stateOfFixing_; /// Node when last done int lastNode_; /// Whether a variable has been in a solution char * used_; }; #endif Cbc-2.8.12/src/CbcStrategy.cpp0000644000076600007660000011273311552601170014463 0ustar coincoin/* $Id: CbcStrategy.cpp 1641 2011-04-17 15:08:40Z forrest $ */ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" #include #include #include #include #include "OsiSolverInterface.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #endif #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcStrategy.hpp" #include "CbcCutGenerator.hpp" #include "CbcBranchActual.hpp" #include "CbcNode.hpp" #include "CoinWarmStart.hpp" #include "CglPreProcess.hpp" // Cuts #include "CglGomory.hpp" #include "CglProbing.hpp" #include "CglKnapsackCover.hpp" #include "CglOddHole.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglMixedIntegerRounding2.hpp" // Heuristics #include "CbcHeuristic.hpp" #include "CbcHeuristicLocal.hpp" #include "CbcHeuristicRINS.hpp" // Default Constructor CbcStrategy::CbcStrategy() : depth_(0), preProcessState_(0), process_(NULL) { } // Destructor CbcStrategy::~CbcStrategy () { delete process_; } // Delete pre-processing object to save memory void CbcStrategy::deletePreProcess() { delete process_; process_ = NULL; } // Return a new Full node information pointer (descendant of CbcFullNodeInfo) CbcNodeInfo * CbcStrategy::fullNodeInfo(CbcModel * model, int numberRowsAtContinuous) const { return new CbcFullNodeInfo(model, numberRowsAtContinuous); } // Return a new Partial node information pointer (descendant of CbcPartialNodeInfo) CbcNodeInfo * CbcStrategy::partialNodeInfo(CbcModel * /*model*/, CbcNodeInfo * parent, CbcNode * owner, int numberChangedBounds, const int * variables, const double * boundChanges, const CoinWarmStartDiff *basisDiff) const { return new CbcPartialNodeInfo(parent, owner, numberChangedBounds, variables, boundChanges, basisDiff); } /* After a CbcModel::resolve this can return a status -1 no effect 0 treat as optimal 1 as 0 but do not do any more resolves (i.e. no more cuts) 2 treat as infeasible */ int CbcStrategy::status(CbcModel * /*model*/, CbcNodeInfo * /*parent*/, int /*whereFrom*/) { return -1; } // Default Constructor CbcStrategyDefault::CbcStrategyDefault(int cutsOnlyAtRoot, int numberStrong, int numberBeforeTrust, int printLevel) : CbcStrategy(), cutsOnlyAtRoot_(cutsOnlyAtRoot), numberStrong_(numberStrong), numberBeforeTrust_(numberBeforeTrust), printLevel_(printLevel), desiredPreProcess_(0), preProcessPasses_(0) { } // Destructor CbcStrategyDefault::~CbcStrategyDefault () { } // Clone CbcStrategy * CbcStrategyDefault::clone() const { return new CbcStrategyDefault(*this); } // Copy constructor CbcStrategyDefault::CbcStrategyDefault(const CbcStrategyDefault & rhs) : CbcStrategy(rhs), cutsOnlyAtRoot_(rhs.cutsOnlyAtRoot_), numberStrong_(rhs.numberStrong_), numberBeforeTrust_(rhs.numberBeforeTrust_), printLevel_(rhs.printLevel_), desiredPreProcess_(rhs.desiredPreProcess_), preProcessPasses_(rhs.preProcessPasses_) { setNested(rhs.getNested()); } /* Set up cut generators. Will instantiate Probing, Gomory, Knapsack, Clique, FlowCover, and MIR2 generators. Probing should be the first in the vector of generators as it tightens bounds on continuous variables. Cut generators already installed will dominate cut generators instantiated here. There's a classic magic number overloaded parameter example here. The variable genFlags below is interpreted as single-bit flags to control whether a cut generator will be instantiated: Probing:1, Gomory:2, Knapsack:4, Clique:8, FlowCover:16, MIR2:32. Normally it's hardcoded to 63. If CBC_GENERATE_TEST is defined, and the model's node limit is set between 190000 and 190064, genFlags is loaded with the low-order bits. */ void CbcStrategyDefault::setupCutGenerators(CbcModel & model) { if (cutsOnlyAtRoot_ < 0) return; // no cuts wanted // Magic number overloaded parameter -- see comment at head. int genFlags = 63; # ifdef CBC_GENERATE_TEST int nNodes = model.getMaximumNodes(); if (nNodes >= 190000 && nNodes < 190064) genFlags = nNodes - 190000; # endif CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(1); generator1.setMaxPassRoot(1); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); // How far to follow the consequences generator1.setMaxLook(10); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); generator1.setMaxElementsRoot(300); //generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; //CglOddHole generator4; //generator4.setMinimumViolation(0.005); //generator4.setMinimumViolationPer(0.00002); // try larger limit //generator4.setMaximumEntries(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding2 mixedGen; CglFlowCover flowGen; /* Add in generators. Do not override generators already installed. */ int setting = cutsOnlyAtRoot_ ? -99 : -1; int numberGenerators = model.numberCutGenerators(); int iGenerator; bool found; found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglProbing * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found && (genFlags&1) != 0) model.addCutGenerator(&generator1, setting, "Probing"); found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglGomory * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found && (genFlags&2) != 0) model.addCutGenerator(&generator2, setting, "Gomory"); found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglKnapsackCover * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found && (genFlags&4) != 0) model.addCutGenerator(&generator3, setting, "Knapsack"); //model.addCutGenerator(&generator4,setting,"OddHole"); found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglClique * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found && (genFlags&8) != 0) model.addCutGenerator(&generator5, setting, "Clique"); found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglFlowCover * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found && (genFlags&16) != 0) model.addCutGenerator(&flowGen, setting, "FlowCover"); found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglMixedIntegerRounding2 * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found && (genFlags&32) != 0) model.addCutGenerator(&mixedGen, setting, "MixedIntegerRounding2"); // Say we want timings int newNumberGenerators = model.numberCutGenerators(); for (iGenerator = numberGenerators; iGenerator < newNumberGenerators; iGenerator++) { CbcCutGenerator * generator = model.cutGenerator(iGenerator); generator->setTiming(true); } // Caution! Undocumented magic numbers. int currentPasses = model.getMaximumCutPassesAtRoot(); if (currentPasses >= 0) { if (model.getNumCols() < 5000) model.setMaximumCutPassesAtRoot(CoinMax(50, currentPasses)); // use minimum drop else model.setMaximumCutPassesAtRoot(CoinMax(20, currentPasses)); } else { currentPasses = -currentPasses; if (model.getNumCols() < 500) model.setMaximumCutPassesAtRoot(-CoinMax(100, currentPasses)); // always do 100 if possible else model.setMaximumCutPassesAtRoot(-CoinMax(20, currentPasses)); } } // Setup heuristics void CbcStrategyDefault::setupHeuristics(CbcModel & model) { // Allow rounding heuristic CbcRounding heuristic1(model); heuristic1.setHeuristicName("rounding"); int numberHeuristics = model.numberHeuristics(); int iHeuristic; bool found; found = false; for (iHeuristic = 0; iHeuristic < numberHeuristics; iHeuristic++) { CbcHeuristic * heuristic = model.heuristic(iHeuristic); CbcRounding * cgl = dynamic_cast(heuristic); if (cgl) { found = true; break; } } if (!found) model.addHeuristic(&heuristic1); #ifdef JJF_ZERO // Allow join solutions CbcHeuristicLocal heuristic2(model); heuristic2.setHeuristicName("join solutions"); heuristic2.setSearchType(1); found = false; for (iHeuristic = 0; iHeuristic < numberHeuristics; iHeuristic++) { CbcHeuristic * heuristic = model.heuristic(iHeuristic); CbcHeuristicLocal * cgl = dynamic_cast(heuristic); if (cgl) { found = true; break; } } if (!found) model.addHeuristic(&heuristic2); #endif } // Do printing stuff void CbcStrategyDefault::setupPrinting(CbcModel & model, int modelLogLevel) { if (!modelLogLevel) { model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); model.messageHandler()->setLogLevel(0); model.solver()->messageHandler()->setLogLevel(0); } else if (modelLogLevel == 1) { model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); model.messageHandler()->setLogLevel(1); model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(CoinMax(2, model.messageHandler()->logLevel())); model.solver()->messageHandler()->setLogLevel(CoinMax(1, model.solver()->messageHandler()->logLevel())); model.setPrintFrequency(CoinMin(50, model.printFrequency())); } } /* Aside from setting CbcModel::numberStrong_ and numberBeforeTrust, the big activity is integer preprocessing. Surely this code to do preprocessing duplicates code to do preprocessing up in the solver main routine. Most of the effort goes into manipulating SOS sets. */ // Other stuff e.g. strong branching void CbcStrategyDefault::setupOther(CbcModel & model) { // See if preprocessing wanted if (desiredPreProcess_) { delete process_; /* Inaccurate as of 080122 --- assignSolver (below) can now be instructed not to delete the existing solver when the preprocessed solver is assigned to the model. 'Course, we do need to hold on to a pointer somewhere, and that must be captured before this call. */ // solver_ should have been cloned outside CglPreProcess * process = new CglPreProcess(); // Pass in models message handler process->passInMessageHandler(model.messageHandler()); OsiSolverInterface * solver = model.solver(); #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); if (clpSolver && false) { // see if all coefficients multiple of 0.01 (close enough) CoinPackedMatrix * matrix = clpSolver->getModelPtr()->matrix(); double * element = matrix->getMutableElements(); //const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); int numberInt = 0; int numberNon = 0; int numberClose = 0; int numberColumns = clpSolver->getNumCols(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { //int iRow = row[j]; double value1 = element[j]; double value = fabs(value1); if (value > 1.0e7) { if (value != floor(value)) numberNon++; else numberInt++; } else { int iValue = static_cast( 100 * (value + 0.005)); double value2 = iValue; if (value2 == 100.0*value) { numberInt++; } else if (fabs(value2 - 100.0*value) < 1.0e-5) { numberClose++; } else { numberNon++; } } } } if (!numberNon && numberClose) { COIN_DETAIL_PRINT(printf("Tidying %d multiples of 0.01, %d close\n", numberInt, numberClose)); for (iColumn = 0; iColumn < numberColumns; iColumn++) { for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { //int iRow = row[j]; double value1 = element[j]; double value = fabs(value1); if (value < 1.0e7) { int iValue = static_cast( 100 * (value + 0.005)); double value2 = iValue; if (value2 != 100.0*value) { value2 *= 0.01; if (fabs(value - floor(value + 0.5)) <= 1.0e-7) value2 = floor(value + 0.5); if (value1 < 0.0) value2 = -value2; element[j] = value2; } } } } } } #endif { // mark some columns as ineligible for presolve int numberColumns = solver->getNumCols(); char * prohibited = new char[numberColumns]; memset(prohibited, 0, numberColumns); int numberProhibited = 0; /* Create CbcSimpleInteger objects would be more accurate in the general case. The `false' parameter says we won't delete existing objects. Only Clp will produce SOS objects in findIntegers (080122), and that's where a possible conversion can occur. If clp is holding OsiSOS objects, they'll be converted to CbcSOS objects. */ // convert to Cbc integers model.findIntegers(false); int numberObjects = model.numberObjects(); if (numberObjects) { OsiObject ** objects = model.objects(); for (int iObject = 0; iObject < numberObjects; iObject++) { CbcSOS * obj = dynamic_cast (objects[iObject]) ; if (obj) { // SOS int n = obj->numberMembers(); const int * which = obj->members(); for (int i = 0; i < n; i++) { int iColumn = which[i]; prohibited[iColumn] = 1; numberProhibited++; } } } } if (numberProhibited) process->passInProhibited(prohibited, numberColumns); delete [] prohibited; } int logLevel = model.messageHandler()->logLevel(); #ifdef COIN_HAS_CLP //OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); ClpSimplex * lpSolver = NULL; if (clpSolver) { if (clpSolver->messageHandler()->logLevel()) clpSolver->messageHandler()->setLogLevel(1); if (logLevel > -1) clpSolver->messageHandler()->setLogLevel(CoinMin(logLevel, clpSolver->messageHandler()->logLevel())); lpSolver = clpSolver->getModelPtr(); /// If user left factorization frequency then compute lpSolver->defaultFactorizationFrequency(); } #endif // Tell solver we are in Branch and Cut solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ; // Default set of cut generators // Limited set that could reduce problem size (drop rows / fix values) CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(1); generator1.setMaxPassRoot(1); generator1.setMaxProbeRoot(CoinMin(3000, solver->getNumCols())); generator1.setMaxProbeRoot(123); generator1.setMaxElements(100); generator1.setMaxElementsRoot(200); generator1.setMaxLookRoot(50); generator1.setRowCuts(3); //generator1.messageHandler()->setLogLevel(logLevel); // Not needed with pass in process->messageHandler()->setLogLevel(logLevel); // Add in generators process->addCutGenerator(&generator1); int translate[] = {9999, 0, 2, -2, 3, 4, 4, 4}; OsiSolverInterface * solver2 = process->preProcessNonDefault(*solver, translate[desiredPreProcess_], preProcessPasses_, 6); // Tell solver we are not in Branch and Cut solver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (solver2) solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; bool feasible = true; if (!solver2) { feasible = false; //printf("Pre-processing says infeasible\n"); delete process; preProcessState_ = -1; process_ = NULL; } else { // now tighten bounds #ifdef COIN_HAS_CLP if (clpSolver) { // model has changed solver = model.solver(); OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); ClpSimplex * lpSolver = clpSolver->getModelPtr(); lpSolver->passInMessageHandler(solver->messageHandler()); if (lpSolver->tightenPrimalBounds() == 0) { lpSolver->dual(); } else { feasible = false; } } #endif if (feasible) { preProcessState_ = 1; process_ = process; /* Note that original solver will be kept (with false) and that final solver will also be kept. This is for post-processing Keep in mind when examining this that linear presolve does not understand SOS. */ OsiSolverInterface * solver3 = solver2->clone(); model.assignSolver(solver3, false); if (process_->numberSOS()) { int numberSOS = process_->numberSOS(); int numberIntegers = model.numberIntegers(); /* model may not have created objects If none then create NOTE - put back to original column numbers as CbcModel will pack down ALL as it doesn't know where from */ bool someObjects = model.numberObjects() > 0; if (!numberIntegers || !model.numberObjects()) { model.findIntegers(true); numberIntegers = model.numberIntegers(); } OsiObject ** oldObjects = model.objects(); // Do sets and priorities OsiObject ** objects = new OsiObject * [numberSOS]; // set old objects to have low priority int numberOldObjects = model.numberObjects(); int numberColumns = model.getNumCols(); for (int iObj = 0; iObj < numberOldObjects; iObj++) { int oldPriority = oldObjects[iObj]->priority(); oldObjects[iObj]->setPriority(numberColumns + oldPriority); } const int * starts = process_->startSOS(); const int * which = process_->whichSOS(); const int * type = process_->typeSOS(); const double * weight = process_->weightSOS(); int iSOS; for (iSOS = 0; iSOS < numberSOS; iSOS++) { int iStart = starts[iSOS]; int n = starts[iSOS+1] - iStart; objects[iSOS] = new CbcSOS(&model, n, which + iStart, weight + iStart, iSOS, type[iSOS]); // branch on long sets first objects[iSOS]->setPriority(numberColumns - n); } model.addObjects(numberSOS, objects); for (iSOS = 0; iSOS < numberSOS; iSOS++) delete objects[iSOS]; delete [] objects; if (!someObjects) { // put back old column numbers const int * originalColumns = process_->originalColumns(); // use reverse lookup to fake it int n = originalColumns[numberColumns-1] + 1; int * fake = new int[n]; int i; // This was wrong (now is correct) - so could never have been called abort(); for ( i = 0; i < n; i++) fake[i] = -1; for (i = 0; i < numberColumns; i++) fake[originalColumns[i]] = i; for (int iObject = 0; iObject < model.numberObjects(); iObject++) { // redo ids etc CbcSimpleInteger * obj = dynamic_cast (model.modifiableObject(iObject)) ; if (obj) { obj->resetSequenceEtc(n, fake); } else { // redo ids etc CbcObject * obj = dynamic_cast (model.modifiableObject(iObject)) ; assert (obj); obj->redoSequenceEtc(&model, n, fake); } } delete [] fake; } } } else { //printf("Pre-processing says infeasible\n"); delete process; preProcessState_ = -1; process_ = NULL; } } } model.setNumberStrong(numberStrong_); model.setNumberBeforeTrust(numberBeforeTrust_); } // Create C++ lines to get to current state void CbcStrategyDefault::generateCpp( FILE * fp) { fprintf(fp, "0#include \"CbcStrategy.hpp\"\n"); fprintf(fp, "3 CbcStrategyDefault strategy(%s,%d,%d,%d);\n", cutsOnlyAtRoot_ ? "1" : "0", numberStrong_, numberBeforeTrust_, printLevel_); fprintf(fp, "3 strategy.setupPreProcessing(%d,%d);\n", desiredPreProcess_, preProcessPasses_); } // Default Constructor CbcStrategyDefaultSubTree::CbcStrategyDefaultSubTree(CbcModel * parent , int cutsOnlyAtRoot, int numberStrong, int numberBeforeTrust, int printLevel) : CbcStrategy(), parentModel_(parent), cutsOnlyAtRoot_(cutsOnlyAtRoot), numberStrong_(numberStrong), numberBeforeTrust_(numberBeforeTrust), printLevel_(printLevel) { } // Destructor CbcStrategyDefaultSubTree::~CbcStrategyDefaultSubTree () { } // Clone CbcStrategy * CbcStrategyDefaultSubTree::clone() const { return new CbcStrategyDefaultSubTree(*this); } // Copy constructor CbcStrategyDefaultSubTree::CbcStrategyDefaultSubTree(const CbcStrategyDefaultSubTree & rhs) : CbcStrategy(rhs), parentModel_(rhs.parentModel_), cutsOnlyAtRoot_(rhs.cutsOnlyAtRoot_), numberStrong_(rhs.numberStrong_), numberBeforeTrust_(rhs.numberBeforeTrust_), printLevel_(rhs.printLevel_) { setNested(rhs.getNested()); } // Setup cut generators void CbcStrategyDefaultSubTree::setupCutGenerators(CbcModel & model) { // Set up some cut generators and defaults if (cutsOnlyAtRoot_ < 0) return; // no cuts wanted // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(1); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); // How far to follow the consequences generator1.setMaxLook(10); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); //generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; //CglOddHole generator4; //generator4.setMinimumViolation(0.005); //generator4.setMinimumViolationPer(0.00002); // try larger limit //generator4.setMaximumEntries(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding2 mixedGen; CglFlowCover flowGen; // Add in generators int setting = cutsOnlyAtRoot_ ? -99 : -1; int numberGenerators = model.numberCutGenerators(); int numberParentGenerators = parentModel_->numberCutGenerators(); int iGenerator; bool found; found = false; int howOften = 0; for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) { CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator(); CglProbing * cgl = dynamic_cast(generator); if (cgl) { found = true; howOften = parentModel_->cutGenerator(iGenerator)->howOften(); break; } } if (found && (howOften >= -1 || howOften == -98)) { found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglProbing * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found) { if (howOften == -1) howOften = -98; else if (howOften == -98) howOften = -99; model.addCutGenerator(&generator1, setting, "Probing"); CbcCutGenerator * generator = model.cutGenerator(numberGenerators); generator->setHowOften(howOften); numberGenerators++; } } found = false; for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) { CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator(); CglGomory * cgl = dynamic_cast(generator); if (cgl) { found = true; howOften = parentModel_->cutGenerator(iGenerator)->howOften(); break; } } if (found && howOften >= 0) { found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglGomory * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found) model.addCutGenerator(&generator2, setting, "Gomory"); } found = false; for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) { CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator(); CglKnapsackCover * cgl = dynamic_cast(generator); if (cgl) { found = true; howOften = parentModel_->cutGenerator(iGenerator)->howOften(); break; } } if (found && howOften >= 0) { found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglKnapsackCover * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found) model.addCutGenerator(&generator3, setting, "Knapsack"); } found = false; for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) { CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator(); CglClique * cgl = dynamic_cast(generator); if (cgl) { found = true; howOften = parentModel_->cutGenerator(iGenerator)->howOften(); break; } } if (found && howOften >= 0) { found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglClique * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found) model.addCutGenerator(&generator5, setting, "Clique"); } found = false; for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) { CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator(); CglFlowCover * cgl = dynamic_cast(generator); if (cgl) { found = true; howOften = parentModel_->cutGenerator(iGenerator)->howOften(); break; } } if (found && howOften >= 0) { found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglFlowCover * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found) model.addCutGenerator(&flowGen, setting, "FlowCover"); found = false; } for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) { CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator(); CglMixedIntegerRounding2 * cgl = dynamic_cast(generator); if (cgl) { found = true; howOften = parentModel_->cutGenerator(iGenerator)->howOften(); break; } } if (found && howOften >= 0) { found = false; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglMixedIntegerRounding2 * cgl = dynamic_cast(generator); if (cgl) { found = true; break; } } if (!found) model.addCutGenerator(&mixedGen, setting, "MixedIntegerRounding2"); } #ifdef JJF_ZERO // Say we want timings int newNumberGenerators = model.numberCutGenerators(); for (iGenerator = numberGenerators; iGenerator < newNumberGenerators; iGenerator++) { CbcCutGenerator * generator = model.cutGenerator(iGenerator); generator->setTiming(true); } #endif if (model.getNumCols() < -500) model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (model.getNumCols() < 5000) model.setMaximumCutPassesAtRoot(100); // use minimum drop else model.setMaximumCutPassesAtRoot(20); } // Setup heuristics void CbcStrategyDefaultSubTree::setupHeuristics(CbcModel & model) { // Allow rounding heuristic CbcRounding heuristic1(model); heuristic1.setHeuristicName("rounding"); int numberHeuristics = model.numberHeuristics(); int iHeuristic; bool found; found = false; for (iHeuristic = 0; iHeuristic < numberHeuristics; iHeuristic++) { CbcHeuristic * heuristic = model.heuristic(iHeuristic); CbcRounding * cgl = dynamic_cast(heuristic); if (cgl) { found = true; break; } } if (!found) model.addHeuristic(&heuristic1); if ((model.moreSpecialOptions()&32768)!=0) { // Allow join solutions CbcHeuristicLocal heuristic2(model); heuristic2.setHeuristicName("join solutions"); //sheuristic2.setSearchType(1); found = false; for (iHeuristic = 0; iHeuristic < numberHeuristics; iHeuristic++) { CbcHeuristic * heuristic = model.heuristic(iHeuristic); CbcHeuristicLocal * cgl = dynamic_cast(heuristic); if (cgl) { found = true; break; } } if (!found) model.addHeuristic(&heuristic2); // Allow RINS CbcHeuristicRINS heuristic5(model); heuristic5.setHeuristicName("RINS"); heuristic5.setFractionSmall(0.5); heuristic5.setDecayFactor(5.0); //heuristic5.setSearchType(1); found = false; for (iHeuristic = 0; iHeuristic < numberHeuristics; iHeuristic++) { CbcHeuristic * heuristic = model.heuristic(iHeuristic); CbcHeuristicLocal * cgl = dynamic_cast(heuristic); if (cgl) { found = true; break; } } if (!found) model.addHeuristic(&heuristic5); } } // Do printing stuff void CbcStrategyDefaultSubTree::setupPrinting(CbcModel & model, int modelLogLevel) { if (!modelLogLevel) { model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); model.messageHandler()->setLogLevel(0); model.solver()->messageHandler()->setLogLevel(0); } else if (modelLogLevel == 1) { model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); model.messageHandler()->setLogLevel(1); model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); model.setPrintFrequency(50); } } // Other stuff e.g. strong branching void CbcStrategyDefaultSubTree::setupOther(CbcModel & model) { model.setNumberStrong(numberStrong_); model.setNumberBeforeTrust(numberBeforeTrust_); } // For uniform setting of cut and heuristic options void setCutAndHeuristicOptions(CbcModel & model) { int numberGenerators = model.numberCutGenerators(); int iGenerator; for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator(); CglProbing * cglProbing = dynamic_cast(generator); if (cglProbing) { cglProbing->setUsingObjective(1); cglProbing->setMaxPass(1); cglProbing->setMaxPassRoot(1); // Number of unsatisfied variables to look at cglProbing->setMaxProbe(10); cglProbing->setMaxProbeRoot(50); //cglProbing->setMaxProbeRoot(123); // How far to follow the consequences cglProbing->setMaxLook(5); cglProbing->setMaxLookRoot(50); cglProbing->setMaxLookRoot(10); // Only look at rows with fewer than this number of elements cglProbing->setMaxElements(200); cglProbing->setMaxElementsRoot(300); cglProbing->setRowCuts(3); } #ifdef JJF_ZERO CglGomory * cglGomory = dynamic_cast(generator); if (cglGomory) { // try larger limit cglGomory->setLimitAtRoot(1000); cglGomory->setLimit(50); } CglKnapsackCover * cglKnapsackCover = dynamic_cast(generator); if (cglKnapsackCover) { } #endif } } Cbc-2.8.12/src/CbcBranchLotsize.hpp0000644000076600007660000001742711510742604015443 0ustar coincoin/* $Id: CbcBranchLotsize.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcBranchLotsize_H #define CbcBranchLotsize_H #include "CbcBranchBase.hpp" /** Lotsize class */ class CbcLotsize : public CbcObject { public: // Default Constructor CbcLotsize (); /* Useful constructor - passed model index. Also passed valid values - if range then pairs */ CbcLotsize (CbcModel * model, int iColumn, int numberPoints, const double * points, bool range = false); // Copy constructor CbcLotsize ( const CbcLotsize &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcLotsize & operator=( const CbcLotsize& rhs); // Destructor ~CbcLotsize (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /** Set bounds to contain the current solution. More precisely, for the variable associated with this object, take the value given in the current solution, force it within the current bounds if required, then set the bounds to fix the variable at the integer nearest the solution value. */ virtual void feasibleRegion(); /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /** \brief Given a valid solution (with reduced costs, etc.), return a branching object which would give a new feasible point in the good direction. The preferred branching object will force the variable to be +/-1 from its current value, depending on the reduced cost and objective sense. If movement in the direction which improves the objective is impossible due to bounds on the variable, the branching object will move in the other direction. If no movement is possible, the method returns NULL. Only the bounds on this variable are considered when determining if the new point is feasible. */ virtual CbcBranchingObject * preferredNewFeasible() const; /** \brief Given a valid solution (with reduced costs, etc.), return a branching object which would give a new feasible point in a bad direction. As for preferredNewFeasible(), but the preferred branching object will force movement in a direction that degrades the objective. */ virtual CbcBranchingObject * notPreferredNewFeasible() const ; /** Reset original upper and lower bound values from the solver. Handy for updating bounds held in this object after bounds held in the solver have been tightened. */ virtual void resetBounds(const OsiSolverInterface * solver); /** Finds range of interest so value is feasible in range range_ or infeasible between hi[range_] and lo[range_+1]. Returns true if feasible. */ bool findRange(double value) const; /** Returns floor and ceiling */ virtual void floorCeiling(double & floorLotsize, double & ceilingLotsize, double value, double tolerance) const; /// Model column number inline int modelSequence() const { return columnNumber_; } /// Set model column number inline void setModelSequence(int value) { columnNumber_ = value; } /** Column number if single column object -1 otherwise, so returns >= 0 Used by heuristics */ virtual int columnNumber() const; /// Original variable bounds inline double originalLowerBound() const { return bound_[0]; } inline double originalUpperBound() const { return bound_[rangeType_*numberRanges_-1]; } /// Type - 1 points, 2 ranges inline int rangeType() const { return rangeType_; } /// Number of points inline int numberRanges() const { return numberRanges_; } /// Ranges inline double * bound() const { return bound_; } /** \brief Return true if object can take part in normal heuristics */ virtual bool canDoHeuristics() const { return false; } private: /// Just for debug (CBC_PRINT defined in CbcBranchLotsize.cpp) void printLotsize(double value, bool condition, int type) const; private: /// data /// Column number in model int columnNumber_; /// Type - 1 points, 2 ranges int rangeType_; /// Number of points int numberRanges_; // largest gap double largestGap_; /// Ranges double * bound_; /// Current range mutable int range_; }; /** Lotsize branching object This object can specify a two-way branch on an integer variable. For each arm of the branch, the upper and lower bounds on the variable can be independently specified. Variable_ holds the index of the integer variable in the integerVariable_ array of the model. */ class CbcLotsizeBranchingObject : public CbcBranchingObject { public: /// Default constructor CbcLotsizeBranchingObject (); /** Create a lotsize floor/ceiling branch object Specifies a simple two-way branch. Let \p value = x*. One arm of the branch will be is lb <= x <= valid range below(x*), the other valid range above(x*) <= x <= ub. Specify way = -1 to set the object state to perform the down arm first, way = 1 for the up arm. */ CbcLotsizeBranchingObject (CbcModel *model, int variable, int way , double value, const CbcLotsize * lotsize) ; /** Create a degenerate branch object Specifies a `one-way branch'. Calling branch() for this object will always result in lowerValue <= x <= upperValue. Used to fix in valid range */ CbcLotsizeBranchingObject (CbcModel *model, int variable, int way, double lowerValue, double upperValue) ; /// Copy constructor CbcLotsizeBranchingObject ( const CbcLotsizeBranchingObject &); /// Assignment operator CbcLotsizeBranchingObject & operator= (const CbcLotsizeBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; /// Destructor virtual ~CbcLotsizeBranchingObject (); using CbcBranchingObject::branch ; /** \brief Sets the bounds for the variable according to the current arm of the branch and advances the object state to the next arm. */ virtual double branch(); using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return LotsizeBranchObj; } // LL: compareOriginalObject can be inherited from the CbcBranchingObject // since variable_ uniquely defines the lot sizing object. /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); protected: /// Lower [0] and upper [1] bounds for the down arm (way_ = -1) double down_[2]; /// Lower [0] and upper [1] bounds for the up arm (way_ = 1) double up_[2]; }; #endif Cbc-2.8.12/src/CbcCountRowCut.cpp0000644000076600007660000004002112130022033015067 0ustar coincoin/* $Id: CbcCountRowCut.cpp 1883 2013-04-06 13:33:15Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include "OsiRowCut.hpp" #include "CbcModel.hpp" #include "CbcCountRowCut.hpp" #include "CbcNode.hpp" //#define CHECK_CUT_COUNTS // Default Constructor CbcCountRowCut::CbcCountRowCut () : OsiRowCut(), owner_(NULL), ownerCut_(-1), numberPointingToThis_(0), whichCutGenerator_(-1) { #ifdef CHECK_CUT_COUNTS printf("CbcCountRowCut default constructor %x\n", this); #endif } // Copy Constructor CbcCountRowCut::CbcCountRowCut (const OsiRowCut & rhs) : OsiRowCut(rhs), owner_(NULL), ownerCut_(-1), numberPointingToThis_(0), whichCutGenerator_(-1) { #ifdef CHECK_CUT_COUNTS printf("CbcCountRowCut constructor %x from RowCut\n", this); #endif } // Copy Constructor CbcCountRowCut::CbcCountRowCut (const OsiRowCut & rhs, CbcNodeInfo * info, int whichOne, int whichGenerator, int numberPointingToThis) : OsiRowCut(rhs), owner_(info), ownerCut_(whichOne), numberPointingToThis_(numberPointingToThis), whichCutGenerator_(whichGenerator) { #ifdef CHECK_CUT_COUNTS printf("CbcCountRowCut constructor %x from RowCut and info %d\n", this, numberPointingToThis_); #endif //assert (!numberPointingToThis||numberPointingToThis==1000000000); } CbcCountRowCut::~CbcCountRowCut() { #ifdef CHECK_CUT_COUNTS printf("CbcCountRowCut destructor %x - references %d\n", this, numberPointingToThis_); #endif // Look at owner and delete if (owner_) owner_->deleteCut(ownerCut_); ownerCut_ = -1234567; } // Increment number of references void CbcCountRowCut::increment(int change) { assert(ownerCut_ != -1234567); numberPointingToThis_ += change; } // Decrement number of references and return number left int CbcCountRowCut::decrement(int change) { assert(ownerCut_ != -1234567); // See if plausible number if (change < 900000000) { //assert(numberPointingToThis_>=change); assert(numberPointingToThis_ >= 0); if (numberPointingToThis_ < change) { assert(numberPointingToThis_ > 0); COIN_DETAIL_PRINT(printf("negative cut count %d - %d\n", numberPointingToThis_, change)); change = numberPointingToThis_; } numberPointingToThis_ -= change; } return numberPointingToThis_; } // Set information void CbcCountRowCut::setInfo(CbcNodeInfo * info, int whichOne) { owner_ = info; ownerCut_ = whichOne; } // Returns true if can drop cut if slack basic bool CbcCountRowCut::canDropCut(const OsiSolverInterface * solver, int iRow) const { // keep if COIN_DBL_MAX otherwise keep if slack zero if (effectiveness() < 1.0e20) { return true; } else if (effectiveness() != COIN_DBL_MAX) { if (iRow >= solver->getNumRows()) return true; const double * rowActivity = solver->getRowActivity(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); double tolerance; solver->getDblParam(OsiPrimalTolerance, tolerance) ; double value = rowActivity[iRow]; if (value < rowLower[iRow] + tolerance || value > rowUpper[iRow] - tolerance) return false; else return true; } else { return false; } } static double multiplier[] = {1.23456789e2,-9.87654321}; static int hashCut (const OsiRowCut2 & x, int size) { int xN =x.row().getNumElements(); double xLb = x.lb(); double xUb = x.ub(); const int * xIndices = x.row().getIndices(); const double * xElements = x.row().getElements(); unsigned int hashValue; double value=1.0; if (xLb>-1.0e10) value += xLb*multiplier[0]; if (xUb<1.0e10) value += xUb*multiplier[1]; for( int j=0;jsizeof(hashValue)) { assert (sizeof(value)==2*sizeof(hashValue)); union { double d; int i[2]; } xx; xx.d = value; hashValue = (xx.i[0] + xx.i[1]); } else { assert (sizeof(value)==sizeof(hashValue)); union { double d; unsigned int i[2]; } xx; xx.d = value; hashValue = xx.i[0]; } return hashValue%(size); } static int hashCut2 (const OsiRowCut2 & x, int size) { int xN =x.row().getNumElements(); double xLb = x.lb(); double xUb = x.ub(); const int * xIndices = x.row().getIndices(); const double * xElements = x.row().getElements(); unsigned int hashValue; double value=1.0; if (xLb>-1.0e10) value += xLb*multiplier[0]; if (xUb<1.0e10) value += xUb*multiplier[1]; for( int j=0;jsizeof(hashValue)) { assert (sizeof(value)==2*sizeof(hashValue)); union { double d; int i[2]; } xx; xx.d = value; hashValue = (xx.i[0] + xx.i[1]); } else { assert (sizeof(value)==sizeof(hashValue)); union { double d; unsigned int i[2]; } xx; xx.d = value; hashValue = xx.i[0]; } return hashValue%(size); } static bool same (const OsiRowCut2 & x, const OsiRowCut2 & y) { int xN =x.row().getNumElements(); int yN =y.row().getNumElements(); bool identical=false; if (xN==yN) { double xLb = x.lb(); double xUb = x.ub(); double yLb = y.lb(); double yUb = y.ub(); if (fabs(xLb-yLb)<1.0e-8&&fabs(xUb-yUb)<1.0e-8) { const int * xIndices = x.row().getIndices(); const double * xElements = x.row().getElements(); const int * yIndices = y.row().getIndices(); const double * yElements = y.row().getElements(); int j; for( j=0;j1.0e-12) break; } identical = (j==xN); } } return identical; } static bool same2 (const OsiRowCut2 & x, const OsiRowCut2 & y) { int xN =x.row().getNumElements(); int yN =y.row().getNumElements(); bool identical=false; if (xN==yN) { double xLb = x.lb(); double xUb = x.ub(); double yLb = y.lb(); double yUb = y.ub(); if (fabs(xLb-yLb)<1.0e-8&&fabs(xUb-yUb)<1.0e-8) { const int * xIndices = x.row().getIndices(); const double * xElements = x.row().getElements(); const int * yIndices = y.row().getIndices(); const double * yElements = y.row().getElements(); int j; for( j=0;j1.0e-12) break; } identical = (j==xN); } } return identical; } CbcRowCuts::CbcRowCuts(int initialMaxSize, int hashMultiplier) { numberCuts_=0; size_ = initialMaxSize; hashMultiplier_ = hashMultiplier; int hashSize=hashMultiplier_*size_; if (size_) { rowCut_ = new OsiRowCut2 * [size_]; hash_ = new CoinHashLink[hashSize]; } else { rowCut_ = NULL; hash_ = NULL; } for (int i=0;i=0&&sequence= 0 ) { if (j1!=sequence) { int k = hash_[ipos].next; if ( k != -1 ) ipos = k; else break; } else { found = j1; break; } } else { break; } } assert (found>=0); assert (hash_[ipos].index==sequence); // shuffle up while (hash_[ipos].next>=0) { int k = hash_[ipos].next; hash_[ipos]=hash_[k]; ipos=k; } delete cut; // move last to found numberCuts_--; if (numberCuts_) { ipos = hashCut(*rowCut_[numberCuts_],hashSize); while ( true ) { int j1 = hash_[ipos].index; if (j1!=numberCuts_) { int k = hash_[ipos].next; ipos = k; } else { // change hash_[ipos].index=found; rowCut_[found]=rowCut_[numberCuts_]; rowCut_[numberCuts_]=NULL; break; } } } assert (!rowCut_[numberCuts_]); } // Return 0 if added, 1 if not, -1 if not added because of space int CbcRowCuts::addCutIfNotDuplicate(const OsiRowCut & cut,int whichType) { int hashSize= size_*hashMultiplier_; if (numberCuts_==size_) { size_ = 2*size_+100; hashSize=hashMultiplier_*size_; OsiRowCut2 ** temp = new OsiRowCut2 * [size_]; delete [] hash_; hash_ = new CoinHashLink[hashSize]; for (int i=0;i= 0 ) { if ( !same(*temp[i],*temp[j1]) ) { int k = hash_[ipos].next; if ( k != -1 ) ipos = k; else break; } else { found = j1; break; } } else { break; } } if (found<0) { assert (hash_[ipos].next==-1); if (ipos==jpos) { // first hash_[ipos].index=i; } else { // find next space while ( true ) { ++lastHash_; assert (lastHash_1.0e12) bad=true; } if (bad) return 1; OsiRowCut2 newCut(whichType); newCut.setLb(newLb); newCut.setUb(newUb); newCut.setRow(vector); int ipos = hashCut(newCut,hashSize); int found = -1; int jpos=ipos; while ( true ) { int j1 = hash_[ipos].index; if ( j1 >= 0 ) { if ( !same(newCut,*rowCut_[j1]) ) { int k = hash_[ipos].next; if ( k != -1 ) ipos = k; else break; } else { found = j1; break; } } else { break; } } if (found<0) { assert (hash_[ipos].next==-1); if (ipos==jpos) { // first hash_[ipos].index=numberCuts_; } else { // find next space while ( true ) { ++lastHash_; assert (lastHash_setLb(newLb); newCutPtr->setUb(newUb); newCutPtr->setRow(vector); rowCut_[numberCuts_++]=newCutPtr; return 0; } else { return 1; } } else { return -1; } } // Return 0 if added, 1 if not, -1 if not added because of space int CbcRowCuts::addCutIfNotDuplicateWhenGreedy(const OsiRowCut & cut,int whichType) { int hashSize= size_*hashMultiplier_; if (numberCuts_==size_) { size_ = 2*size_+100; hashSize=hashMultiplier_*size_; OsiRowCut2 ** temp = new OsiRowCut2 * [size_]; delete [] hash_; hash_ = new CoinHashLink[hashSize]; for (int i=0;i= 0 ) { if ( !same2(*temp[i],*temp[j1]) ) { int k = hash_[ipos].next; if ( k != -1 ) ipos = k; else break; } else { found = j1; break; } } else { break; } } if (found<0) { assert (hash_[ipos].next==-1); if (ipos==jpos) { // first hash_[ipos].index=i; } else { // find next space while ( true ) { ++lastHash_; assert (lastHash_1.0e12) bad=true; } if (bad) return 1; OsiRowCut2 newCut(whichType); newCut.setLb(newLb); newCut.setUb(newUb); newCut.setRow(vector); int ipos = hashCut2(newCut,hashSize); int found = -1; int jpos=ipos; while ( true ) { int j1 = hash_[ipos].index; if ( j1 >= 0 ) { if ( !same2(newCut,*rowCut_[j1]) ) { int k = hash_[ipos].next; if ( k != -1 ) ipos = k; else break; } else { found = j1; break; } } else { break; } } if (found<0) { assert (hash_[ipos].next==-1); if (ipos==jpos) { // first hash_[ipos].index=numberCuts_; } else { // find next space while ( true ) { ++lastHash_; assert (lastHash_setLb(newLb); newCutPtr->setUb(newUb); newCutPtr->setRow(vector); rowCut_[numberCuts_++]=newCutPtr; return 0; } else { return 1; } } else { return -1; } } // Add in cuts as normal cuts and delete void CbcRowCuts::addCuts(OsiCuts & cs) { for (int i=0;i #include #include #include #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "OsiChooseVariable.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchBase.hpp" // Default Constructor CbcObject::CbcObject() : OsiObject(), model_(NULL), id_(-1), position_(-1), preferredWay_(0) { } // Constructor from model CbcObject::CbcObject(CbcModel * model) : OsiObject(), model_(model), id_(-1), position_(-1), preferredWay_(0) { } // Destructor CbcObject::~CbcObject () { } // Copy constructor CbcObject::CbcObject ( const CbcObject & rhs) : OsiObject(rhs) { model_ = rhs.model_; id_ = rhs.id_; position_ = rhs.position_; preferredWay_ = rhs.preferredWay_; } // Assignment operator CbcObject & CbcObject::operator=( const CbcObject & rhs) { if (this != &rhs) { OsiObject::operator=(rhs); model_ = rhs.model_; id_ = rhs.id_; position_ = rhs.position_; preferredWay_ = rhs.preferredWay_; } return *this; } /* Returns floor and ceiling i.e. closest valid points */ void CbcObject::floorCeiling(double & floorValue, double & ceilingValue, double value, double tolerance) const { if (fabs(floor(value + 0.5) - value) > tolerance) { floorValue = floor(value); } else { floorValue = floor(value + 0.5); } ceilingValue = floorValue + 1.0; } /* For the variable(s) referenced by the object, look at the current solution and set bounds to match the solution. Returns measure of how much it had to move solution to make feasible */ double CbcObject::feasibleRegion(OsiSolverInterface * /*solver*/) const { //assert (solver==model_->solver()); CbcObject * fudge = const_cast(this); fudge->feasibleRegion(); return 0.0; } /* For the variable(s) referenced by the object, look at the current solution and set bounds to match the solution. Returns measure of how much it had to move solution to make feasible */ double CbcObject::feasibleRegion(OsiSolverInterface * /*solver*/, const OsiBranchingInformation * /*info*/) const { //assert (solver==model_->solver()); CbcObject * fudge = const_cast(this); fudge->feasibleRegion(); return 0.0; } /* Create a branching object and indicate which way to branch first. The branching object has to know how to create branches (fix variables, etc.) */ OsiBranchingObject * CbcObject::createOsiBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const { //assert (solver==model_->solver()); CbcObject * fudge = const_cast(this); return fudge->createBranch(solver, info, way); } /* Create an OsiSolverBranch object This returns NULL if branch not represented by bound changes */ OsiSolverBranch * CbcObject::solverBranch() const { return NULL; } /* Pass in information on branch just done and create CbcObjectUpdateData instance. If object does not need data then backward pointer will be NULL. Assumes can get information from solver */ CbcObjectUpdateData CbcObject::createUpdateInformation(const OsiSolverInterface * /*solver*/, const CbcNode * /*node*/, const CbcBranchingObject * /*branchingObject*/) { return CbcObjectUpdateData(); } Cbc-2.8.12/src/CbcHeuristicPivotAndFix.hpp0000644000076600007660000000303412131315050016723 0ustar coincoin/* $Id: CbcHeuristicPivotAndFix.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicPivotAndFix_H #define CbcHeuristicPivotAndFix_H #include "CbcHeuristic.hpp" /** LocalSearch class */ class CbcHeuristicPivotAndFix : public CbcHeuristic { public: // Default Constructor CbcHeuristicPivotAndFix (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicPivotAndFix (CbcModel & model); // Copy constructor CbcHeuristicPivotAndFix ( const CbcHeuristicPivotAndFix &); // Destructor ~CbcHeuristicPivotAndFix (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicPivotAndFix & operator=(const CbcHeuristicPivotAndFix& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) needs comments */ virtual int solution(double & objectiveValue, double * newSolution); protected: }; #endif Cbc-2.8.12/src/CbcGenCtlBlk.cpp0000644000076600007660000004345712131315050014465 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenCtlBlk.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #include "CbcConfig.h" #include "CoinPragma.hpp" #include #include "CbcGenCtlBlk.hpp" namespace { char svnid[] = "$Id: CbcGenCtlBlk.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } /* Constructor for cbc-generic control block. Set up defaults for the cbc-generic control block. Note that prototypes for cut generators and heuristics will be created on demand; see the access functions. Once this structure settles down, simple intialisation should move up to the standard `:' block. In the meantime, this avoids complaints about ordering. */ CbcGenCtlBlk::CbcGenCtlBlk () { version_ = CBC_GENERIC_VERSION ; /* It's unclear to me that this is a good choice for dfltDirectory. Makes sense for commands, but seems unnecessary for data files. Perhaps a null string instead? */ char dirsep = CoinFindDirSeparator() ; dfltDirectory_ = (dirsep == '/' ? "./" : ".\\") ; lastMpsIn_ = "" ; allowImportErrors_ = false ; lastSolnOut_ = "stdout" ; printMode_ = 0 ; printMask_ = "" ; paramVec_ = 0 ; genParams_.first_ = 0 ; genParams_.last_ = 0 ; cbcParams_.first_ = 0 ; cbcParams_.last_ = 0 ; osiParams_.first_ = 0 ; osiParams_.last_ = 0 ; verbose_ = 0 ; paramsProcessed_ = 0 ; defaultSettings_ = true ; debugCreate_ = "" ; debugFile_ = "" ; debugSol_.numCols_ = -1 ; debugSol_.values_ = 0 ; printOpt_ = 0 ; /* Assigning us_en to cur_lang_ is entirely bogus, but CoinMessages::Language does not provide an `unspecified' code. */ msgHandler_ = new CoinMessageHandler() ; ourMsgHandler_ = true ; cur_lang_ = CoinMessages::us_en ; msgs_ = 0 ; logLvl_ = 0 ; totalTime_ = 0.0 ; model_ = 0 ; dfltSolver_ = 0 ; goodModel_ = false ; bab_.majorStatus_ = BACInvalid ; bab_.minorStatus_ = BACmInvalid ; bab_.where_ = BACwInvalid ; bab_.haveAnswer_ = false ; bab_.answerSolver_ = 0 ; preProcess_ = CbcGenCtlBlk::IPPSOS ; cutDepth_ = -1 ; probing_.action_ = CbcGenCtlBlk::CGIfMove ; probing_.proto_ = 0 ; probing_.usingObjective_ = true ; probing_.maxPass_ = 3 ; probing_.maxPassRoot_ = 3 ; probing_.maxProbe_ = 10 ; probing_.maxProbeRoot_ = 50 ; probing_.maxLook_ = 10 ; probing_.maxLookRoot_ = 50 ; probing_.maxElements_ = 200 ; probing_.rowCuts_ = 3 ; clique_.action_ = CbcGenCtlBlk::CGIfMove ; clique_.proto_ = 0 ; clique_.starCliqueReport_ = false ; clique_.rowCliqueReport_ = false ; clique_.minViolation_ = 0.1 ; flow_.action_ = CbcGenCtlBlk::CGIfMove ; flow_.proto_ = 0 ; gomory_.action_ = CbcGenCtlBlk::CGIfMove ; gomory_.proto_ = 0 ; gomory_.limit_ = 50 ; gomory_.limitAtRoot_ = 512 ; knapsack_.action_ = CbcGenCtlBlk::CGIfMove ; knapsack_.proto_ = 0 ; // landp_action_ = CbcGenCtlBlk::CGOff ; // landp_.proto_ = 0 ; mir_.action_ = CbcGenCtlBlk::CGIfMove ; mir_.proto_ = 0 ; oddHole_.action_ = CbcGenCtlBlk::CGOff ; oddHole_.proto_ = 0 ; redSplit_.action_ = CbcGenCtlBlk::CGRoot ; redSplit_.proto_ = 0 ; twomir_.action_ = CbcGenCtlBlk::CGRoot ; twomir_.proto_ = 0 ; twomir_.maxElements_ = 250 ; fpump_.action_ = CbcGenCtlBlk::CGOn ; fpump_.proto_ = 0 ; combine_.action_ = CbcGenCtlBlk::CGOn ; combine_.proto_ = 0 ; combine_.trySwap_ = 1 ; greedyCover_.action_ = CbcGenCtlBlk::CGOn ; greedyCover_.proto_ = 0 ; greedyEquality_.action_ = CbcGenCtlBlk::CGOn ; greedyEquality_.proto_ = 0 ; localTree_.action_ = CbcGenCtlBlk::CGOff ; localTree_.proto_ = 0 ; localTree_.soln_ = 0 ; localTree_.range_ = 10 ; localTree_.typeCuts_ = 0 ; localTree_.maxDiverge_ = 0 ; localTree_.timeLimit_ = 10000 ; localTree_.nodeLimit_ = 2000 ; localTree_.refine_ = true ; rounding_.action_ = CbcGenCtlBlk::CGOn ; rounding_.proto_ = 0 ; djFix_.action_ = false ; djFix_.threshold_ = 1.0e100 ; priorityAction_ = CbcGenCtlBlk::BPOff ; /* The value for numBeforeTrust is as recommended by Achterberg. Cbc's implementation doesn't really have a parameter equivalent to Achterberg's dynamic limit on number of strong branching evaluations, so go with a fairly large default. As of 06.12.16, the magic number for shadow price mode meant `use shadow prices (penalties, I think) if there's no strong branching info'. */ chooseStrong_.numBeforeTrust_ = 8 ; chooseStrong_.numStrong_ = 100 ; chooseStrong_.shadowPriceMode_ = 1 ; return ; } /* Note that we don't want to delete dfltSolver_ here because it's just a copy of the pointer held in the solvers map over in CbcGenSolvers.cpp. */ CbcGenCtlBlk::~CbcGenCtlBlk () { if (model_) delete model_ ; if (bab_.answerSolver_) delete bab_.answerSolver_ ; if (probing_.proto_) delete probing_.proto_ ; if (clique_.proto_) delete clique_.proto_ ; if (flow_.proto_) delete flow_.proto_ ; if (gomory_.proto_) delete gomory_.proto_ ; if (knapsack_.proto_) delete knapsack_.proto_ ; if (mir_.proto_) delete mir_.proto_ ; if (oddHole_.proto_) delete oddHole_.proto_ ; if (redSplit_.proto_) delete redSplit_.proto_ ; if (twomir_.proto_) delete twomir_.proto_ ; if (fpump_.proto_) delete fpump_.proto_ ; if (combine_.proto_) delete combine_.proto_ ; if (greedyCover_.proto_) delete greedyCover_.proto_ ; if (greedyEquality_.proto_) delete greedyEquality_.proto_ ; if (rounding_.proto_) delete rounding_.proto_ ; if (msgHandler_ && ourMsgHandler_) delete msgHandler_ ; if (msgs_) delete msgs_ ; return ; } /* Access functions for cut generators and heuristics. These support lazy creation --- if action_ is other than CGOff, an object is created if necessary and a pointer is stored in proto_. The pointer is returned as a generic CglCutGenerator or CbcHeuristic. The return value of the function is the value of action_. Because the model may have changed, the default for heuristics is to delete any existing object and create a new one. This can be suppressed if desired. */ CbcGenCtlBlk::CGControl CbcGenCtlBlk::getProbing (CglCutGenerator *&gen) { if (probing_.action_ != CbcGenCtlBlk::CGOff && probing_.proto_ == 0) { probing_.proto_ = new CglProbing() ; probing_.proto_->setUsingObjective(probing_.usingObjective_) ; probing_.proto_->setMaxPass(probing_.maxPass_) ; probing_.proto_->setMaxPassRoot(probing_.maxPassRoot_) ; probing_.proto_->setMaxProbe(probing_.maxProbe_) ; probing_.proto_->setMaxProbeRoot(probing_.maxProbeRoot_) ; probing_.proto_->setMaxLook(probing_.maxLook_) ; probing_.proto_->setMaxLookRoot(probing_.maxLookRoot_) ; probing_.proto_->setMaxElements(probing_.maxElements_) ; probing_.proto_->setRowCuts(probing_.rowCuts_) ; } gen = dynamic_cast(probing_.proto_) ; return (probing_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getClique (CglCutGenerator *&gen) { if (clique_.action_ != CbcGenCtlBlk::CGOff && clique_.proto_ == 0) { clique_.proto_ = new CglClique() ; clique_.proto_->setStarCliqueReport(clique_.starCliqueReport_) ; clique_.proto_->setRowCliqueReport(clique_.rowCliqueReport_) ; clique_.proto_->setMinViolation(clique_.minViolation_) ; } gen = dynamic_cast(clique_.proto_) ; return (clique_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getFlow (CglCutGenerator *&gen) { if (flow_.action_ != CbcGenCtlBlk::CGOff && flow_.proto_ == 0) { flow_.proto_ = new CglFlowCover() ; } gen = dynamic_cast(flow_.proto_) ; return (flow_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getGomory (CglCutGenerator *&gen) { if (gomory_.action_ != CbcGenCtlBlk::CGOff && gomory_.proto_ == 0) { gomory_.proto_ = new CglGomory() ; gomory_.proto_->setLimitAtRoot(gomory_.limitAtRoot_) ; gomory_.proto_->setLimit(gomory_.limit_) ; } gen = dynamic_cast(gomory_.proto_) ; return (gomory_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getKnapsack (CglCutGenerator *&gen) { if (knapsack_.action_ != CbcGenCtlBlk::CGOff && knapsack_.proto_ == 0) { knapsack_.proto_ = new CglKnapsackCover() ; } gen = dynamic_cast(knapsack_.proto_) ; return (knapsack_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getMir (CglCutGenerator *&gen) { if (mir_.action_ != CbcGenCtlBlk::CGOff && mir_.proto_ == 0) { mir_.proto_ = new CglMixedIntegerRounding2() ; } gen = dynamic_cast(mir_.proto_) ; return (mir_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getRedSplit (CglCutGenerator *&gen) { if (redSplit_.action_ != CbcGenCtlBlk::CGOff && redSplit_.proto_ == 0) { redSplit_.proto_ = new CglRedSplit() ; } gen = dynamic_cast(redSplit_.proto_) ; return (redSplit_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getTwomir (CglCutGenerator *&gen) { if (twomir_.action_ != CbcGenCtlBlk::CGOff && twomir_.proto_ == 0) { twomir_.proto_ = new CglTwomir() ; twomir_.proto_->setMaxElements(twomir_.maxElements_) ; } gen = dynamic_cast(twomir_.proto_) ; return (twomir_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getFPump (CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate) { if (fpump_.action_ != CbcGenCtlBlk::CGOff && (fpump_.proto_ == 0 || alwaysCreate)) { if (fpump_.proto_) { delete fpump_.proto_ ; } fpump_.proto_ = new CbcHeuristicFPump(*model) ; fpump_.proto_->setMaximumPasses(fpump_.iters_) ; } gen = dynamic_cast(fpump_.proto_) ; return (fpump_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getCombine (CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate) { if (combine_.action_ != CbcGenCtlBlk::CGOff && (combine_.proto_ == 0 || alwaysCreate)) { if (combine_.proto_) { delete combine_.proto_ ; } combine_.proto_ = new CbcHeuristicLocal(*model) ; combine_.proto_->setSearchType(combine_.trySwap_) ; } gen = dynamic_cast(combine_.proto_) ; return (combine_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getGreedyCover (CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate) { if (greedyCover_.action_ != CbcGenCtlBlk::CGOff && (greedyCover_.proto_ == 0 || alwaysCreate)) { if (greedyCover_.proto_) { delete greedyCover_.proto_ ; } greedyCover_.proto_ = new CbcHeuristicGreedyCover(*model) ; } gen = dynamic_cast(greedyCover_.proto_) ; return (greedyCover_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getGreedyEquality (CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate) { if (greedyEquality_.action_ != CbcGenCtlBlk::CGOff && (greedyEquality_.proto_ == 0 || alwaysCreate)) { if (greedyEquality_.proto_) { delete greedyEquality_.proto_ ; } greedyEquality_.proto_ = new CbcHeuristicGreedyEquality(*model) ; } gen = dynamic_cast(greedyEquality_.proto_) ; return (greedyEquality_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getRounding (CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate) { if (rounding_.action_ != CbcGenCtlBlk::CGOff && (rounding_.proto_ == 0 || alwaysCreate)) { if (rounding_.proto_) { delete rounding_.proto_ ; } rounding_.proto_ = new CbcRounding(*model) ; } gen = dynamic_cast(rounding_.proto_) ; return (rounding_.action_) ; } CbcGenCtlBlk::CGControl CbcGenCtlBlk::getTreeLocal (CbcTreeLocal *&localTree, CbcModel *model, bool alwaysCreate) { if (localTree_.action_ != CbcGenCtlBlk::CGOff && (localTree_.proto_ == 0 || alwaysCreate)) { if (localTree_.proto_) { delete localTree_.proto_ ; } localTree_.proto_ = new CbcTreeLocal(model, localTree_.soln_, localTree_.range_, localTree_.typeCuts_, localTree_.maxDiverge_, localTree_.timeLimit_, localTree_.nodeLimit_, localTree_.refine_) ; } localTree = localTree_.proto_ ; return (localTree_.action_) ; } /* A bunch of little translation helper routines leading up to a version of setBaBStatus that figures it all out given a CbcModel and BACWhere code. This translation needs to be centralised to avoid sprinkling magic numbers all through the code. Be a bit careful with the translation routines --- they aren't sensitive to where the search stopped. */ CbcGenCtlBlk::BACMajor CbcGenCtlBlk::translateMajor (int status) { switch (status) { case -1: { return (BACNotRun) ; } case 0: { return (BACFinish) ; } case 1: { return (BACStop) ; } case 2: { return (BACAbandon) ; } case 5: { return (BACUser) ; } default: { return (BACInvalid) ; } } } CbcGenCtlBlk::BACMinor CbcGenCtlBlk::translateMinor (int status) { switch (status) { case -1: { return (BACmInvalid) ; } case 0: { return (BACmFinish) ; } case 1: { return (BACmInfeas) ; } case 2: { return (BACmGap) ; } case 3: { return (BACmNodeLimit) ; } case 4: { return (BACmTimeLimit) ; } case 5: { return (BACmUser) ; } case 6: { return (BACmSolnLimit) ; } case 7: { return (BACmUbnd) ; } default: { return (BACmOther) ; } } } /* A bit different --- given an OSI, use its interrogation functions to choose an appropriate BACMinor code. Not everything matches up, eh? */ CbcGenCtlBlk::BACMinor CbcGenCtlBlk::translateMinor (const OsiSolverInterface *osi) { if (osi->isProvenOptimal()) { return (BACmFinish) ; } else if (osi->isProvenPrimalInfeasible()) { return (BACmInfeas) ; } else if (osi->isProvenDualInfeasible()) { return (BACmUbnd) ; } else { return (BACmOther) ; } } /* A routine to set the bab_ status block given a CbcModel and an indication of where we're at in the search. Really, this is just a big mapping from CbcModel codes to CbcGeneric codes. */ void CbcGenCtlBlk::setBaBStatus (const CbcModel *model, BACWhere where, bool haveAnswer, OsiSolverInterface *answerSolver) { CbcGenCtlBlk::BACMajor major ; CbcGenCtlBlk::BACMinor minor ; major = translateMajor(model->status()) ; if (where == CbcGenCtlBlk::BACwBareRoot || where == CbcGenCtlBlk::BACwIPPRelax) { minor = translateMinor(model->solver()) ; } else { minor = translateMinor(model->secondaryStatus()) ; } setBaBStatus(major, minor, where, haveAnswer, answerSolver) ; return ; } /* Last, but not least, a routine to print the result. */ void CbcGenCtlBlk::printBaBStatus () { std::cout << "BAC result: stopped " ; switch (bab_.where_) { case BACwNotStarted: { std::cout << "before root relaxation" ; break ; } case BACwBareRoot: { std::cout << "after root relaxation" ; break ; } case BACwIPP: { std::cout << "after integer preprocessing" ; break ; } case BACwIPPRelax: { std::cout << "after solving preprocessed relaxation" ; break ; } case BACwBAC: { std::cout << "after branch-and-cut" ; break ; } default: { std::cout << "!!invalid phase code!!" ; break ; } } std::cout << std::endl << " Branch-and-cut " ; switch (bab_.majorStatus_) { case BACNotRun: { std::cout << "never got started" ; break ; } case BACFinish: { std::cout << "finished" ; break ; } case BACStop: { std::cout << "stopped on a limit" ; break ; } case BACAbandon: { std::cout << "was abandoned" ; break ; } case BACUser: { std::cout << "stopped due to a user event" ; break ; } default: { std::cout << "!!invalid major status code!!" ; break ; } } std::cout << "; minor status is " ; switch (bab_.minorStatus_) { case BACmFinish: { std::cout << "optimal" ; break ; } case BACmInfeas: { std::cout << "infeasible" ; break ; } case BACmUbnd: { std::cout << "unbounded" ; break ; } case BACmGap: { std::cout << "reached specified integrality gap." ; break ; } case BACmNodeLimit: { std::cout << "reached node limit" ; break ; } case BACmTimeLimit: { std::cout << "reached time limit" ; break ; } case BACmSolnLimit: { std::cout << "reached limit on number of solutions" ; break ; } case BACmUser: { std::cout << "stopped due to a user event" ; break ; } case BACmOther: { std::cout << "other" ; break ; } default: { std::cout << "!!invalid minor status code!!" ; break ; } } std::cout << "." << std::endl ; } Cbc-2.8.12/src/CbcCompareEstimate.hpp0000644000076600007660000000253512131315050015737 0ustar coincoin// $Id: CbcCompareEstimate.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCompareActual #ifndef CbcCompareEstimate_H #define CbcCompareEstimate_H //############################################################################# /* These are alternative strategies for node traversal. They can take data etc for fine tuning At present the node list is stored as a heap and the "test" comparison function returns true if node y is better than node x. */ #include "CbcNode.hpp" #include "CbcCompareBase.hpp" #include "CbcCompare.hpp" class CbcModel; /* This is when rounding is being done */ class CbcCompareEstimate : public CbcCompareBase { public: // Default Constructor CbcCompareEstimate () ; ~CbcCompareEstimate() ; // Copy constructor CbcCompareEstimate ( const CbcCompareEstimate &rhs); // Assignment operator CbcCompareEstimate & operator=( const CbcCompareEstimate& rhs); /// Clone virtual CbcCompareBase * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp); virtual bool test (CbcNode * x, CbcNode * y) ; }; #endif //CbcCompareEstimate_H Cbc-2.8.12/src/CbcHeuristicRENS.cpp0000644000076600007660000007751412131315050015310 0ustar coincoin// $Id: CbcHeuristicRENS.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // edwin 12/5/09 carved out of CbcHeuristicRINS #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcHeuristicRENS.hpp" #include "CoinWarmStartBasis.hpp" #include "CoinSort.hpp" #include "CbcBranchActual.hpp" #include "CbcStrategy.hpp" #include "CglPreProcess.hpp" // Default Constructor CbcHeuristicRENS::CbcHeuristicRENS() : CbcHeuristic() { numberTries_ = 0; rensType_ = 0; whereFrom_ = 256 + 1; } // Constructor with model - assumed before cuts CbcHeuristicRENS::CbcHeuristicRENS(CbcModel & model) : CbcHeuristic(model) { numberTries_ = 0; rensType_ = 0; whereFrom_ = 256 + 1; } // Destructor CbcHeuristicRENS::~CbcHeuristicRENS () { } // Clone CbcHeuristic * CbcHeuristicRENS::clone() const { return new CbcHeuristicRENS(*this); } // Assignment operator CbcHeuristicRENS & CbcHeuristicRENS::operator=( const CbcHeuristicRENS & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); numberTries_ = rhs.numberTries_; rensType_ = rhs.rensType_; } return *this; } // Copy constructor CbcHeuristicRENS::CbcHeuristicRENS(const CbcHeuristicRENS & rhs) : CbcHeuristic(rhs), numberTries_(rhs.numberTries_), rensType_(rhs.rensType_) { } // Resets stuff if model changes void CbcHeuristicRENS::resetModel(CbcModel * ) { } int CbcHeuristicRENS::solution(double & solutionValue, double * betterSolution) { int returnCode = 0; const double * bestSolution = model_->bestSolution(); if ((numberTries_&&(rensType_&16)==0) || numberTries_>1 || (when() < 2 && bestSolution)) return 0; numberTries_++; double saveFractionSmall=fractionSmall_; OsiSolverInterface * solver = model_->solver(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); OsiSolverInterface * newSolver = cloneBut(3); // was model_->continuousSolver()->clone(); const double * currentSolution = newSolver->getColSolution(); int type = rensType_&15; if (type<12) newSolver->resolve(); double direction = newSolver->getObjSense(); double cutoff=model_->getCutoff(); newSolver->setDblParam(OsiDualObjectiveLimit, 1.0e100); //cutoff *= direction; double gap = cutoff - newSolver->getObjValue() * direction ; double tolerance; newSolver->getDblParam(OsiDualTolerance, tolerance) ; if ((gap > 0.0 || !newSolver->isProvenOptimal())&&type<12) { gap += 100.0 * tolerance; int nFix = newSolver->reducedCostFix(gap); if (nFix) { char line [200]; sprintf(line, "Reduced cost fixing fixed %d variables", nFix); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << line << CoinMessageEol; } } else if (type<12) { return 0; // finished? } int numberColumns = solver->getNumCols(); double * dj = CoinCopyOfArray(solver->getReducedCost(),numberColumns); double djTolerance = (type!=1) ? -1.0e30 : 1.0e-4; const double * colLower = newSolver->getColLower(); const double * colUpper = newSolver->getColUpper(); double * contribution = NULL; int numberFixed = 0; if (type==3) { double total=0.0; int n=0; CoinWarmStartBasis * basis = dynamic_cast(solver->getWarmStart()) ; if (basis&&basis->getNumArtificial()) { for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (colUpper[iColumn]>colLower[iColumn]&& basis->getStructStatus(iColumn) != CoinWarmStartBasis::basic) { n++; total += fabs(dj[iColumn]); } } if (n) djTolerance = (0.01*total)/static_cast(n); delete basis; } } else if (type>=5&&type<=12) { /* 5 fix sets at one 6 fix on dj but leave unfixed SOS slacks 7 fix sets at one but use pi 8 fix all at zero but leave unfixed SOS slacks 9 as 8 but only fix all at zero if just one in set nonzero 10 fix all "stable" ones 11 fix all "stable" ones - approach 2 12 layered approach */ // SOS type fixing bool fixSets = (type==5)||(type==7)||(type==10)||(type==11); CoinWarmStartBasis * basis = dynamic_cast(solver->getWarmStart()) ; if (basis&&basis->getNumArtificial()) { //const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = solver->getNumRows(); // Column copy const CoinPackedMatrix * matrix = solver->getMatrixByCol(); const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); double * bestDj = new double [numberRows]; for (int i=0;icolLower[iColumn]) { CoinBigIndex j; if (currentSolution[iColumn]>1.0e-6&& currentSolution[iColumn]<0.999999) { for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (bestDj[iRow]<1.0e30) { if (element[j] != 1.0) bestDj[iRow]=1.0e30; else bestDj[iRow]=1.0e25; } } } else if ( basis->getStructStatus(iColumn) != CoinWarmStartBasis::basic) { for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (bestDj[iRow]<1.0e25) { if (element[j] != 1.0) bestDj[iRow]=1.0e30; else bestDj[iRow]=CoinMin(fabs(dj[iColumn]),bestDj[iRow]); } } } } } // Just leave one slack in each set { const double * objective = newSolver->getObjCoefficients(); int * best = new int [numberRows]; double * cheapest = new double[numberRows]; for (int i=0;icolLower[iColumn]) { if (columnLength[iColumn]==1) { CoinBigIndex j = columnStart[iColumn]; int iRow = row[j]; if (bestDj[iRow]<1.0e30) { double obj = direction*objective[iColumn]; if (objcolLower[iColumn]) { if (columnLength[iColumn]==1) { CoinBigIndex j = columnStart[iColumn]; int iRow = row[j]; if (bestDj[iRow]<1.0e30) { if (best[iRow]!=-1&&iColumn!=best[iRow]) { newSolver->setColUpper(iColumn,0.0); } } } } } delete [] best; delete [] cheapest; } int nSOS=0; double * sort = new double [numberRows]; const double * pi = newSolver->getRowPrice(); if (type==12) { contribution = new double [numberRows]; for (int i=0;i8*numberRows) { if (type<10) { std::sort(sort,sort+nSOS); int last = static_cast(nSOS*0.9*fractionSmall_); double tolerance = sort[last]; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (colUpper[iColumn]>colLower[iColumn]) { CoinBigIndex j; if (currentSolution[iColumn]<=1.0e-6|| currentSolution[iColumn]>=0.999999) { if (fixSets) { for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double useDj; if (type==5) useDj = bestDj[iRow]; else if (type==7) useDj= -fabs(pi[iRow]); else useDj= fabs(pi[iRow]); if (bestDj[iRow]<1.0e30&&useDj>=tolerance) { numberFixed++; if (currentSolution[iColumn]<=1.0e-6) newSolver->setColUpper(iColumn,0.0); else if (currentSolution[iColumn]>=0.999999) newSolver->setColLower(iColumn,1.0); } } } else if (columnLength[iColumn]==1) { // leave more slacks int iRow = row[columnStart[iColumn]]; if (bestDj[iRow]<1.0e30) { // fake dj dj[iColumn] *= 0.000001; } } else if (type==8||type==9) { if (currentSolution[iColumn]<=1.0e-6) { if (type==8) { dj[iColumn] *= 1.0e6; } else { bool fix=false; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (bestDj[iRow]<1.0e25) { fix=true; break; } } if (fix) { dj[iColumn] *= 1.0e6; } } } else { dj[iColumn] *= 0.000001; } } } } } if (fixSets) djTolerance = 1.0e30; } else if (type==10) { double * saveUpper = new double [numberRows]; memset(saveUpper,0,numberRows*sizeof(double)); char * mark = new char [numberColumns]; char * nonzero = new char [numberColumns]; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (colUpper[iColumn]>colLower[iColumn]) { CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; saveUpper[iRow] += element[j]; } } } double sum=0.0; double sumRhs=0.0; const double * rowUpper = newSolver->getRowUpper(); for (int i=0;i=1.0e30) { sum += saveUpper[i]; sumRhs += rowUpper[i]; } } double averagePerSet = sum/static_cast(numberRows); // allow this extra double factor = averagePerSet*fractionSmall_*numberRows; factor = 1.0+factor/sumRhs; fractionSmall_ = 0.5; memcpy(saveUpper,rowUpper,numberRows*sizeof(double)); // loosen up for (int i=0;i=1.0e30) { newSolver->setRowUpper(i,factor*saveUpper[i]); } } newSolver->resolve(); const double * solution = newSolver->getColSolution(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { mark[iColumn]=0; nonzero[iColumn]=0; if (colUpper[iColumn]>colLower[iColumn]&& solution[iColumn]>0.9999) mark[iColumn]=1; else if (solution[iColumn]>0.00001) nonzero[iColumn]=1; } // slightly small for (int i=0;i=1.0e30) { newSolver->setRowUpper(i,saveUpper[i]*0.9999); } } newSolver->resolve(); int nCheck=2; if (newSolver->isProvenOptimal()) { for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (colUpper[iColumn]>colLower[iColumn]&& solution[iColumn]>0.9999) mark[iColumn]++; else if (solution[iColumn]>0.00001) nonzero[iColumn]=1; } } else { nCheck=1; } // correct values for (int i=0;i=1.0e30) { newSolver->setRowUpper(i,saveUpper[i]); } } newSolver->resolve(); int nFixed=0; int nFixedToZero=0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (colUpper[iColumn]>colLower[iColumn]) { if (solution[iColumn]>0.9999&&mark[iColumn]==nCheck) { newSolver->setColLower(iColumn,1.0); nFixed++; } else if (!mark[iColumn]&&!nonzero[iColumn]&& columnLength[iColumn]>1&&solution[iColumn]<0.00001) { newSolver->setColUpper(iColumn,0.0); nFixedToZero++; } } } char line[100]; sprintf(line,"Heuristic %s fixed %d to one (and %d to zero)", heuristicName(), nFixed,nFixedToZero); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << line << CoinMessageEol; delete [] mark; delete []nonzero; delete [] saveUpper; numberFixed=numberColumns; djTolerance = 1.0e30; } else if (type==11) { double * saveUpper = CoinCopyOfArray(newSolver->getRowUpper(),numberRows); char * mark = new char [numberColumns]; char * nonzero = new char [numberColumns]; // save basis and solution CoinWarmStartBasis * basis = dynamic_cast(newSolver->getWarmStart()) ; assert(basis != NULL); double * saveSolution = CoinCopyOfArray(newSolver->getColSolution(), numberColumns); double factors[] = {1.1,1.05,1.01,0.98}; int nPass = (sizeof(factors)/sizeof(double))-1; double factor=factors[0]; double proportion = fractionSmall_; fractionSmall_ = 0.5; // loosen up for (int i=0;i=1.0e30) { newSolver->setRowUpper(i,factor*saveUpper[i]); } } bool takeHint; OsiHintStrength strength; newSolver->getHintParam(OsiDoDualInResolve, takeHint, strength); newSolver->setHintParam(OsiDoDualInResolve, false, OsiHintDo); newSolver->resolve(); newSolver->setHintParam(OsiDoDualInResolve, true, OsiHintDo); const double * solution = newSolver->getColSolution(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { mark[iColumn]=0; nonzero[iColumn]=0; if (colUpper[iColumn]>colLower[iColumn]&& solution[iColumn]>0.9999) mark[iColumn]=1; else if (solution[iColumn]>0.00001) nonzero[iColumn]=1; } int nCheck=2; for (int iPass=0;iPass=1.0e30) { newSolver->setRowUpper(i,saveUpper[i]*factor); } } newSolver->resolve(); if (newSolver->isProvenOptimal()) { nCheck++; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (colUpper[iColumn]>colLower[iColumn]&& solution[iColumn]>0.9999) mark[iColumn]++; else if (solution[iColumn]>0.00001) nonzero[iColumn]++; } } } // correct values for (int i=0;i=1.0e30) { newSolver->setRowUpper(i,saveUpper[i]); } } newSolver->setColSolution(saveSolution); delete [] saveSolution; newSolver->setWarmStart(basis); delete basis ; newSolver->setHintParam(OsiDoDualInResolve, takeHint, strength); newSolver->resolve(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (colUpper[iColumn]>colLower[iColumn]&& solution[iColumn]>0.9999) mark[iColumn]++; else if (solution[iColumn]>0.00001) nonzero[iColumn]++; } int nFixed=0; int numberSetsToFix = static_cast(nSOS*(1.0-proportion)); int * mixed = new int[numberRows]; memset(mixed,0,numberRows*sizeof(int)); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (colUpper[iColumn]>colLower[iColumn]) { int iSOS=-1; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (bestDj[iRow]<1.0e25) { iSOS=iRow; break; } } if (iSOS>=0) { int numberTimesAtOne = mark[iColumn]; int numberTimesNonZero = nonzero[iColumn]+ numberTimesAtOne; if (numberTimesAtOnecolLower[iColumn]) { if (solution[iColumn]>0.9999) { int iSOS=-1; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (bestDj[iRow]<1.0e25) { iSOS=iRow; break; } } if (iSOS>=0&&sort[iSOS]) { newSolver->setColLower(iColumn,1.0); nFixed++; } } } } char line[100]; sprintf(line,"Heuristic %s fixed %d to one (%d sets)", heuristicName(), nFixed,nSOS); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << line << CoinMessageEol; delete [] mark; delete [] nonzero; delete [] saveUpper; numberFixed=numberColumns; djTolerance = 1.0e30; } } delete basis; delete [] sort; delete [] bestDj; if (10*nSOS<=8*numberRows) { // give up delete [] contribution; delete newSolver; return 0; } } } // Do dj to get right number if (type==4||type==6||(type>7&&type<10)) { double * sort = new double [numberColumns]; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { sort[iColumn]=1.0e30; if (colUpper[iColumn]>colLower[iColumn]) { sort[iColumn] = fabs(dj[iColumn]); } } std::sort(sort,sort+numberColumns); int last = static_cast(numberColumns*fractionSmall_); djTolerance = CoinMax(sort[last],1.0e-5); delete [] sort; } else if (type==12) { // Do layered in a different way int numberRows = solver->getNumRows(); // Column copy const CoinPackedMatrix * matrix = newSolver->getMatrixByCol(); const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); int * whichRow = new int[numberRows]; int * whichSet = new int [numberColumns]; int nSOS=0; for (int i=0;icolLower[iColumn]) { CoinBigIndex j; double sum=0.0; int iSOS=-1; int n=0; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (contribution[iRow]>=0.0) { iSOS=iRow; n++; } else { sum += fabs(element[j]); } } if (n>1) COIN_DETAIL_PRINT(printf("Too many SOS entries (%d) for column %d\n", n,iColumn)); if (sum) { assert (iSOS>=0); contribution[iSOS] += sum; whichRow[iSOS]++; whichSet[iColumn]=iSOS; } else { whichSet[iColumn]=iSOS+numberRows; } } } int * chunk = new int [numberRows]; for (int i=0;i(whichRow[i]); } else { contribution[i] = COIN_DBL_MAX; } whichRow[i]=i; } newSolver->setDblParam(OsiDualObjectiveLimit, 1.0e100); double * saveLower = CoinCopyOfArray(colLower,numberColumns); double * saveUpper = CoinCopyOfArray(colUpper,numberColumns); CoinSort_2(contribution,contribution+numberRows,whichRow); // Set do nothing solution for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if(whichSet[iColumn]>=numberRows) newSolver->setColLower(iColumn,1.0); } newSolver->resolve(); int nChunk = (nSOS+9)/10; int nPass=0; int inChunk=0; for (int i=0;i=0) { if (iSOS>=numberRows) iSOS-=numberRows; if (chunk[iSOS]==iPass-1&&betterSolution[iColumn]>0.9999) { newSolver->setColLower(iColumn,1.0); } else if (chunk[iSOS]==iPass) { newSolver->setColLower(iColumn,saveLower[iColumn]); newSolver->setColUpper(iColumn,saveUpper[iColumn]); } } } // solve returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicRENS"); if (returnCode < 0) { returnCode = 0; // returned on size break; } else if ((returnCode&1)==0) { // no good break; } } if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } delete [] chunk; delete [] saveLower; delete [] saveUpper; delete [] whichRow; delete [] whichSet; delete [] contribution; delete newSolver; return returnCode; } double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); int i; int numberTightened = 0; int numberAtBound = 0; int numberContinuous = numberColumns - numberIntegers; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = currentSolution[iColumn]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; value = CoinMax(value, lower); value = CoinMin(value, upper); double djValue=dj[iColumn]*direction; #define RENS_FIX_ONLY_LOWER #ifndef RENS_FIX_ONLY_LOWER if (fabs(value - floor(value + 0.5)) < 1.0e-8) { value = floor(value + 0.5); if (value == lower || value == upper) numberAtBound++; newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); numberFixed++; } else if (colUpper[iColumn] - colLower[iColumn] >= 2.0) { numberTightened++; newSolver->setColLower(iColumn, floor(value)); newSolver->setColUpper(iColumn, ceil(value)); } #else if (fabs(value - floor(value + 0.5)) < 1.0e-8 && floor(value + 0.5) == lower && djValue > djTolerance ) { value = floor(value + 0.5); numberAtBound++; newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); numberFixed++; } else if (fabs(value - floor(value + 0.5)) < 1.0e-8 && floor(value + 0.5) == upper && -djValue > djTolerance && (djTolerance > 0.0||type==2)) { value = floor(value + 0.5); numberAtBound++; newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); numberFixed++; } else if (colUpper[iColumn] - colLower[iColumn] >= 2.0 && djTolerance <0.0) { numberTightened++; if (fabs(value - floor(value + 0.5)) < 1.0e-8) { value = floor(value + 0.5); if (value < upper) { newSolver->setColLower(iColumn, CoinMax(value - 1.0, lower)); newSolver->setColUpper(iColumn, CoinMin(value + 1.0, upper)); } else { newSolver->setColLower(iColumn, upper - 1.0); } } else { newSolver->setColLower(iColumn, floor(value)); newSolver->setColUpper(iColumn, ceil(value)); } } #endif } delete [] dj; if (numberFixed > numberIntegers / 5) { if ( numberFixed < numberColumns / 5) { #define RENS_FIX_CONTINUOUS #ifdef RENS_FIX_CONTINUOUS const double * colLower = newSolver->getColLower(); //const double * colUpper = newSolver->getColUpper(); int nAtLb = 0; double sumDj = 0.0; const double * dj = newSolver->getReducedCost(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { double value = currentSolution[iColumn]; if (value < colLower[iColumn] + 1.0e-8) { double djValue = dj[iColumn] * direction; nAtLb++; sumDj += djValue; } } } if (nAtLb) { // fix some continuous double * sort = new double[nAtLb]; int * which = new int [nAtLb]; double threshold = CoinMax((0.01 * sumDj) / static_cast(nAtLb), 1.0e-6); int nFix2 = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { double value = currentSolution[iColumn]; if (value < colLower[iColumn] + 1.0e-8) { double djValue = dj[iColumn] * direction; if (djValue > threshold) { sort[nFix2] = -djValue; which[nFix2++] = iColumn; } } } } CoinSort_2(sort, sort + nFix2, which); nFix2 = CoinMin(nFix2, (numberColumns - numberFixed) / 2); for (int i = 0; i < nFix2; i++) { int iColumn = which[i]; newSolver->setColUpper(iColumn, colLower[iColumn]); } delete [] sort; delete [] which; #ifdef CLP_INVESTIGATE2 printf("%d integers fixed (%d tightened) (%d at bound), and %d continuous fixed at lb\n", numberFixed, numberTightened, numberAtBound, nFix2); #endif } #endif } #ifdef COIN_DEVELOP printf("%d integers fixed and %d tightened\n", numberFixed, numberTightened); #endif returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicRENS"); if (returnCode < 0 || returnCode == 0) { #ifdef RENS_FIX_CONTINUOUS if (numberContinuous > numberIntegers && numberFixed >= numberColumns / 5) { const double * colLower = newSolver->getColLower(); //const double * colUpper = newSolver->getColUpper(); int nAtLb = 0; double sumDj = 0.0; const double * dj = newSolver->getReducedCost(); double direction = newSolver->getObjSense(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { double value = currentSolution[iColumn]; if (value < colLower[iColumn] + 1.0e-8) { double djValue = dj[iColumn] * direction; nAtLb++; sumDj += djValue; } } } if (nAtLb) { // fix some continuous double * sort = new double[nAtLb]; int * which = new int [nAtLb]; double threshold = CoinMax((0.01 * sumDj) / static_cast(nAtLb), 1.0e-6); int nFix2 = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { double value = currentSolution[iColumn]; if (value < colLower[iColumn] + 1.0e-8) { double djValue = dj[iColumn] * direction; if (djValue > threshold) { sort[nFix2] = -djValue; which[nFix2++] = iColumn; } } } } CoinSort_2(sort, sort + nFix2, which); nFix2 = CoinMin(nFix2, (numberColumns - numberFixed) / 2); for (int i = 0; i < nFix2; i++) { int iColumn = which[i]; newSolver->setColUpper(iColumn, colLower[iColumn]); } delete [] sort; delete [] which; #ifdef CLP_INVESTIGATE2 printf("%d integers fixed (%d tightened) (%d at bound), and %d continuous fixed at lb\n", numberFixed, numberTightened, numberAtBound, nFix2); #endif } returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicRENS"); } #endif if (returnCode < 0 || returnCode == 0) { // Do passes fixing up those >0.9 and // down those < 0.05 #define RENS_PASS 3 //#define KEEP_GOING #ifdef KEEP_GOING double * saveLower = CoinCopyOfArray(colLower,numberColumns); double * saveUpper = CoinCopyOfArray(colUpper,numberColumns); bool badPass=false; int nSolved=0; #endif for (int iPass=0;iPasscolLower[iColumn]) { if (newSolver->isInteger(iColumn)) { double value = currentSolution[iColumn]; double fixTo = floor(value+0.1); if (fixTo>value || value-fixTo < 0.05) { // above 0.9 or below 0.05 nFixed++; newSolver->setColLower(iColumn, fixTo); newSolver->setColUpper(iColumn, fixTo); } } } else if (newSolver->isInteger(iColumn)) { nFixedAlready++; } else { nFixedContinuous++; } } #ifdef CLP_INVESTIGATE2 printf("%d more integers fixed (total %d) plus %d continuous\n", nFixed,nFixed+nFixedAlready,nFixedContinuous); #endif #ifdef KEEP_GOING if (nFixed) { newSolver->resolve(); if (!newSolver->isProvenOptimal()) { badPass=true; break; } else { nSolved++; memcpy(saveLower,colLower,numberColumns*sizeof(double)); memcpy(saveUpper,colUpper,numberColumns*sizeof(double)); } } else { break; } #else if (nFixed) { newSolver->resolve(); if (!newSolver->isProvenOptimal()) { returnCode=0; break; } returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicRENS"); } else { returnCode=0; } if (returnCode>=0) break; } if (returnCode < 0) returnCode = 0; // returned on size #endif } #ifdef KEEP_GOING if (badPass) { newSolver->setColLower(saveLower); newSolver->setColUpper(saveUpper); newSolver->resolve(); } delete [] saveLower; delete [] saveUpper; if (nSolved) returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicRENS"); else returnCode=0; } #endif } //printf("return code %d",returnCode); if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; #ifdef COIN_DEVELOP if (!numberTightened && numberFixed == numberAtBound) printf("could add cut with %d elements\n", numberFixed); #endif } else { //printf("\n"); } } //delete [] whichRow; //delete [] contribution; delete newSolver; fractionSmall_ = saveFractionSmall; return returnCode; } // update model void CbcHeuristicRENS::setModel(CbcModel * model) { model_ = model; } Cbc-2.8.12/src/CbcGenOsiParam.cpp0000644000076600007660000000664312131315050015021 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenOsiParam.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include "CoinParam.hpp" #include "CbcModel.hpp" #include "CbcGenCtlBlk.hpp" #include "CbcGenParam.hpp" #include "CbcGenCbcParam.hpp" #include "CbcGenOsiParam.hpp" namespace { char svnid[] = "$Id: CbcGenOsiParam.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } /* Constructors and destructors There's a generic constructor and one for integer, double, keyword, string, and action parameters. */ /* Default constructor. */ CbcOsiParam::CbcOsiParam () : CoinParam(), paramCode_(CbcOsiParamCode(0)), obj_(0) { /* Nothing to be done here */ } /* Constructor for double parameter */ CbcOsiParam::CbcOsiParam (CbcOsiParamCode code, std::string name, std::string help, double lower, double upper, double dflt, bool display) : CoinParam(name, help, lower, upper, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for integer parameter */ CbcOsiParam::CbcOsiParam (CbcOsiParamCode code, std::string name, std::string help, int lower, int upper, int dflt, bool display) : CoinParam(name, help, lower, upper, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for keyword parameter. */ CbcOsiParam::CbcOsiParam (CbcOsiParamCode code, std::string name, std::string help, std::string firstValue, int dflt, bool display) : CoinParam(name, help, firstValue, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for string parameter. */ CbcOsiParam::CbcOsiParam (CbcOsiParamCode code, std::string name, std::string help, std::string dflt, bool display) : CoinParam(name, help, dflt, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Constructor for action parameter. */ CbcOsiParam::CbcOsiParam (CbcOsiParamCode code, std::string name, std::string help, bool display) : CoinParam(name, help, display), paramCode_(code), obj_(0) { /* Nothing to be done here */ } /* Copy constructor. */ CbcOsiParam::CbcOsiParam (const CbcOsiParam &orig) : CoinParam(orig), paramCode_(orig.paramCode_), obj_(orig.obj_) { /* Nothing to be done here */ } /* Clone */ CbcOsiParam *CbcOsiParam::clone () { return (new CbcOsiParam(*this)) ; } CbcOsiParam &CbcOsiParam::operator= (const CbcOsiParam & rhs) { if (this != &rhs) { CoinParam::operator=(rhs) ; paramCode_ = rhs.paramCode_ ; obj_ = rhs.obj_ ; } return *this ; } /* Destructor */ CbcOsiParam::~CbcOsiParam () { /* Nothing more to do */ } Cbc-2.8.12/src/CbcHeuristicDiveFractional.hpp0000644000076600007660000000315412131315050017425 0ustar coincoin/* $Id: CbcHeuristicDiveFractional.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicDiveFractional_H #define CbcHeuristicDiveFractional_H #include "CbcHeuristicDive.hpp" /** DiveFractional class */ class CbcHeuristicDiveFractional : public CbcHeuristicDive { public: // Default Constructor CbcHeuristicDiveFractional (); // Constructor with model - assumed before cuts CbcHeuristicDiveFractional (CbcModel & model); // Copy constructor CbcHeuristicDiveFractional ( const CbcHeuristicDiveFractional &); // Destructor ~CbcHeuristicDiveFractional (); /// Clone virtual CbcHeuristicDiveFractional * clone() const; /// Assignment operator CbcHeuristicDiveFractional & operator=(const CbcHeuristicDiveFractional& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Selects the next variable to branch on /** Returns true if all the fractional variables can be trivially rounded. Returns false, if there is at least one fractional variable that is not trivially roundable. In this case, the bestColumn returned will not be trivially roundable. */ virtual bool selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound); }; #endif Cbc-2.8.12/src/CbcGeneric.cpp0000644000076600007660000003720012131315050014221 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGeneric.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #include "CbcConfig.h" #include "CoinPragma.hpp" #include #include #include #include #include #include #include #include "CoinFileIO.hpp" #include "CoinMpsIO.hpp" #include "CoinPackedMatrix.hpp" #include "CoinPackedVector.hpp" #include "CoinWarmStartBasis.hpp" #include "CoinTime.hpp" #include "OsiSolverInterface.hpp" #include "OsiCuts.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" #include "CglCutGenerator.hpp" #include "CglProbing.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglGomory.hpp" #include "CglKnapsackCover.hpp" #include "CglMixedIntegerRounding2.hpp" #include "CglOddHole.hpp" #include "CglRedSplit.hpp" #include "CglTwomir.hpp" #include "CglPreProcess.hpp" #include "CbcModel.hpp" #include "CbcEventHandler.hpp" #include "CbcTree.hpp" #include "CbcCutGenerator.hpp" #include "CbcHeuristic.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcHeuristicGreedy.hpp" #include "CbcHeuristicLocal.hpp" #include "CbcTreeLocal.hpp" #include "CbcCompareActual.hpp" #include "CoinParam.hpp" #include "CbcGenCtlBlk.hpp" #include "CbcGenParam.hpp" #include "CbcGenCbcParam.hpp" #include "CbcGenOsiParam.hpp" namespace { char svnid[] = "$Id: CbcGeneric.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } namespace CbcGenSolvers { OsiSolverInterface *setupSolvers() ; void deleteSolvers() ; } /* Unnamed local namespace for cbc-generic support types and functions. */ namespace { /* Utility to mark the parameter as having been set by the user. This is a bit clumsy --- we need to cast to a derived parameter type to get the parameter code. But it'll do 'til I think of a better way. */ void markAsSetByUser (CbcGenCtlBlk &ctlBlk, CoinParam *param) { CbcGenParam *genParam = dynamic_cast(param) ; CbcCbcParam *cbcParam = dynamic_cast(param) ; CbcOsiParam *osiParam = dynamic_cast(param) ; int code = -1 ; if (genParam != 0) { code = genParam->paramCode() ; } else if (cbcParam != 0) { code = cbcParam->paramCode() ; } else if (osiParam != 0) { code = osiParam->paramCode() ; } else { std::cerr << "Unrecognised parameter class! Serious internal confusion." << std::endl ; } if (code >= 0) { ctlBlk.setByUser_[code] = true ; } return ; } } // end unnamed namespace int main (int argc, const char *argv[]) { /* This interior block contains all memory allocation; useful for debugging. */ { double time1 = CoinCpuTime() ; double time2 ; /* Try and get all the various i/o to come out in order. Synchronise with C stdio and make stderr and stdout unbuffered. */ std::ios::sync_with_stdio() ; setbuf(stderr, 0) ; setbuf(stdout, 0) ; /* The constructor for ctlBlk establishes the default values for cbc-generic parameters. A little more work is required to create the vector of available solvers and set the default. */ CbcGenCtlBlk ctlBlk ; ctlBlk.setMessages() ; ctlBlk.setLogLevel(1) ; OsiSolverInterface *dfltSolver = CbcGenSolvers::setupSolvers() ; ctlBlk.dfltSolver_ = dfltSolver ; assert (ctlBlk.dfltSolver_) ; /* Now we can begin to initialise the parameter vector. Create a vector of the proper size, then load up the parameters that are relevant to the main program (specifically, values held in ctlBlk and actions evoked from the main program). */ int numParams = 0 ; CoinParamVec paramVec ; paramVec.reserve(CbcOsiParam::CBCOSI_LASTPARAM) ; ctlBlk.paramVec_ = ¶mVec ; ctlBlk.genParams_.first_ = numParams ; CbcGenParamUtils::addCbcGenParams(numParams, paramVec, &ctlBlk) ; ctlBlk.genParams_.last_ = numParams - 1 ; /* Establish a CbcModel object with the default lp solver. Install any defaults that are available from ctlBlk. */ CbcModel *model = new CbcModel(*dfltSolver) ; ctlBlk.model_ = model ; model->messageHandler()->setLogLevel(1) ; model->setNumberStrong(ctlBlk.chooseStrong_.numStrong_) ; model->setNumberBeforeTrust(ctlBlk.chooseStrong_.numBeforeTrust_) ; CbcCbcParamUtils::setCbcModelDefaults(model) ; OsiSolverInterface *osi = model->solver() ; /* Set up the remaining classes of parameters, taking defaults from the CbcModel and OsiSolverInterface objects we've set up. There are parameters that belong to CbcModel (CbcCbcParam) and to the underlying OsiSolverInterface (CbcOsiParam). */ ctlBlk.cbcParams_.first_ = numParams ; CbcCbcParamUtils::addCbcCbcParams(numParams, paramVec, model) ; ctlBlk.cbcParams_.last_ = numParams - 1 ; ctlBlk.osiParams_.first_ = numParams ; CbcOsiParamUtils::addCbcOsiParams(numParams, paramVec, osi) ; ctlBlk.osiParams_.last_ = numParams - 1 ; /* Initialise the vector that tracks parameters that have been changed by user command. */ ctlBlk.setByUser_.resize(CbcOsiParam::CBCOSI_LASTPARAM, false) ; /* The main command parsing loop. Call getCommand to get the next parameter. (The user will be prompted in interactive mode.) If we find something, proceed to process it. If we don't find anything, behaviour depends on what we've seen so far: * An empty command/parameter and no history of previous success gets a brief message. If we're in interactive mode, allow the user to try again, otherwise quit. * An empty command/parameter in interactive mode with some history of successful commands is ignored. Iterate and try again. * An empty command/parameter when we're not interactive is taken as the end of commands. If we have a good model, force branchAndBound. (This is one aspect of giving the expected behaviour for `cbc-generic [parameters] foo.mps'.) */ bool keepParsing = true ; bool forceImport = false ; std::string forceImportFile = "" ; std::string prompt = "cbcGen: " ; std::string pfx = "" ; while (keepParsing) { std::string paramName = CoinParamUtils::getCommand(argc, argv, prompt, &pfx); if (paramName.length() == 0) { if (ctlBlk.paramsProcessed_ == 0) { if (CoinParamUtils::isInteractive()) { std::cout << "Type `?' or `help' for usage and command keywords." << " Type `quit' to quit." ; } else { std::cout << "Type `cbc-generic -help' for usage and parameter keywords." ; keepParsing = false ; } std::cout << std::endl ; } else if (!CoinParamUtils::isInteractive()) { keepParsing = false ; if (ctlBlk.goodModel_ == true && ctlBlk.bab_.majorStatus_ == CbcGenCtlBlk::BACNotRun) { paramName = "branchAndCut" ; pfx = "-" ; } } } if (paramName == "") { continue ; } /* Do we have a parameter we recognise? In command line mode, if there was no prefix (either `-' or `--'), the user didn't intend this as a command keyword. */ int matchNdx ; if (!CoinParamUtils::isCommandLine() || pfx == "-" || pfx == "--") { matchNdx = CoinParamUtils::lookupParam(paramName, paramVec) ; } else { matchNdx = -3 ; } std::cout << "Command is `" << paramName << "', pfx `" << pfx << "', match = " << matchNdx << std::endl ; /* If matchNdx is positive, we have a unique parameter match and we can get on with processing. If the return value is negative, and we're not interactive, quit. If we're interactive, react as appropriate: -1: There was a `?' in the command string. Prompt again. -2: No `?', and one or more short matches. Prompt again. -3: No `?', but we didn't match anything either. If we're in command line mode, and there was no `-' or `--' prefix, try forcing `import' (but just once, eh). This is the other piece required to get `cbc-generic [parameters] foo.mps' to work as expected.) In interactive mode, we'll require the user to say `import'. Interactive mode and no history of successful commands gets the help message. -4: Configuration error, offer `report to maintainers' message. */ if (matchNdx < 0) { if (matchNdx == -3) { if (CoinParamUtils::isCommandLine() && pfx == "") { if (!forceImport) { forceImportFile = paramName ; paramName = "import" ; matchNdx = CoinParamUtils::lookupParam(paramName, paramVec) ; forceImport = true ; } else { std::cout << "No commands matched `" << paramName << "'." << std::endl ; } } else { std::cout << "No commands matched `" << paramName << "'." << std::endl ; if (ctlBlk.paramsProcessed_ == 0) { std::cout << "Type `?' or `help' for usage and command keywords." << " Type `quit' to quit." << std::endl ; } } } else if (matchNdx == -4) { std::cout << "Please report this error by filing a ticket at " << "https://projects.coin-or.org/Cbc/wiki." << std::endl ; } } if (matchNdx < 0) { keepParsing = CoinParamUtils::isInteractive() ; continue ; } CoinParam *param = paramVec[matchNdx] ; ctlBlk.paramsProcessed_++ ; /* Depending on the type, we may need a parameter. For keyword parameters, check that the keyword is recognised --- setKwdVal will quietly fail on a bad keyword. */ CoinParam::CoinParamType type = param->type() ; int valid = 0 ; switch (type) { case CoinParam::coinParamAct: { break ; } case CoinParam::coinParamInt: { int ival = CoinParamUtils::getIntField(argc, argv, &valid) ; if (valid == 0) { param->setIntVal(ival) ; } break ; } case CoinParam::coinParamDbl: { double dval = CoinParamUtils::getDoubleField(argc, argv, &valid) ; if (valid == 0) { param->setDblVal(dval) ; } break ; } case CoinParam::coinParamStr: { if (forceImport) { param->setStrVal(forceImportFile) ; } else { const std::string tmp = CoinParamUtils::getStringField(argc, argv, &valid) ; if (valid == 0) { param->setStrVal(tmp) ; } } break ; } case CoinParam::coinParamKwd: { const std::string tmp = CoinParamUtils::getStringField(argc, argv, &valid) ; if (valid == 0) { param->setKwdVal(tmp) ; if (param->kwdVal() != tmp) { std::cout << "Unrecognised keyword `" << tmp << "' for parameter " << param->name() << std::endl ; param->printKwds() ; std::cout << std::endl ; valid = 1 ; } } break ; } default: { assert (false) ; break ; } } /* Deal with missing or incorrect values. If valid came back as 2, we're short a parameter. This is interpreted as a request to tell the user the current value. If valid came back as 1, we had some sort of parse error. Print an error message. */ if (valid != 0) { switch (valid) { case 1: { std::cout << "Could not parse the value given for parameter `" << param->name() << "'." << std::endl ; break ; } case 2: { std::cout << "Current value of " << param->name() << " parameter is `" << *param << "'." << std::endl ; break ; } default: { std::cout << "Parse status is " << valid << "; this indicates internal confusion." << std::endl << "Please report this error by filing a ticket at " << "https://projects.coin-or.org/Cbc/wiki." << std::endl ; } } keepParsing = CoinParamUtils::isInteractive() ; continue ; } /* Ok, call the parameter's push function to do the heavy lifting. Push and pull functions return 0 for success, 1 for non-fatal error, -1 for fatal error. */ if (param->pushFunc() == 0) { std::cout << "Parameter `" << param->name() << "' is not implemented." << std::endl ; } else { int retval = (param->pushFunc())(param) ; markAsSetByUser(ctlBlk, param) ; if (retval < 0) { keepParsing = false ; } } } /* End of loop to parse and execute parameter actions. Time to do cleanup. The destructor for CbcGenCtlBlk will delete anything with a non-null pointer, so we need to be careful that the default solver is deleted only once. */ ctlBlk.dfltSolver_ = 0 ; CbcGenSolvers::deleteSolvers() ; for (int i = 0 ; i < paramVec.size() ; i++) { if (paramVec[i] != 0) delete paramVec[i] ; } } /* End of memory allocation block. There should be no allocated objects at this point. */ return (0) ; } Cbc-2.8.12/src/CbcFathom.hpp0000644000076600007660000000652512131315050014076 0ustar coincoin/* $Id: CbcFathom.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcFathom_H #define CbcFathom_H #include "CbcConfig.h" /* This file contains two classes, CbcFathom and CbcOsiSolver. It's unclear why they're in the same file. CbcOsiSolver is a base class for CbcLinked. --lh, 071031 -- */ class CbcModel; //############################################################################# /** Fathom base class. The idea is that after some branching the problem will be effectively smaller than the original problem and maybe there will be a more specialized technique which can completely fathom this branch quickly. One method is to presolve the problem to give a much smaller new problem and then do branch and cut on that. Another might be dynamic programming. */ class CbcFathom { public: // Default Constructor CbcFathom (); // Constructor with model - assumed before cuts CbcFathom (CbcModel & model); virtual ~CbcFathom(); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); /// Clone virtual CbcFathom * clone() const = 0; /// Resets stuff if model changes virtual void resetModel(CbcModel * model) = 0; /** returns 0 if no fathoming attempted, 1 fully fathomed, 2 incomplete search, 3 incomplete search but treat as complete. If solution then newSolution will not be NULL and will be freed by CbcModel. It is expected that the solution is better than best so far but CbcModel will double check. If returns 3 then of course there is no guarantee of global optimum */ virtual int fathom(double *& newSolution) = 0; // Is this method possible inline bool possible() const { return possible_; } protected: /// Model CbcModel * model_; /// Possible - if this method of fathoming can be used bool possible_; private: /// Illegal Assignment operator CbcFathom & operator=(const CbcFathom& rhs); }; #include "OsiClpSolverInterface.hpp" //############################################################################# /** This is for codes where solver needs to know about CbcModel Seems to provide only one value-added feature, a CbcModel object. */ class CbcOsiSolver : public OsiClpSolverInterface { public: /**@name Constructors and destructors */ //@{ /// Default Constructor CbcOsiSolver (); /// Clone virtual OsiSolverInterface * clone(bool copyData = true) const; /// Copy constructor CbcOsiSolver (const CbcOsiSolver &); /// Assignment operator CbcOsiSolver & operator=(const CbcOsiSolver& rhs); /// Destructor virtual ~CbcOsiSolver (); //@} /**@name Sets and Gets */ //@{ /// Set Cbc Model inline void setCbcModel(CbcModel * model) { cbcModel_ = model; } /// Return Cbc Model inline CbcModel * cbcModel() const { return cbcModel_; } //@} //--------------------------------------------------------------------------- protected: /**@name Private member data */ //@{ /// Pointer back to CbcModel CbcModel * cbcModel_; //@} }; #endif Cbc-2.8.12/src/CbcCutSubsetModifier.hpp0000644000076600007660000000317512131315050016256 0ustar coincoin// $Id: CbcCutSubsetModifier.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2003, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCutGenerator #ifndef CbcCutSubsetModifier_H #define CbcCutSubsetModifier_H #include "OsiSolverInterface.hpp" #include "OsiCuts.hpp" #include "CglCutGenerator.hpp" #include "CbcCutModifier.hpp" class CbcModel; class OsiRowCut; class OsiRowCutDebugger; /** Simple cut modifier base class In exotic circumstances - cuts may need to be modified a) strengthened - changed b) weakened - changed c) deleted - set to NULL d) unchanged initially get rid of cuts with variables >= k could weaken */ class CbcCutSubsetModifier : public CbcCutModifier { public: /// Default Constructor CbcCutSubsetModifier (); /// Useful Constructor CbcCutSubsetModifier (int firstOdd); // Copy constructor CbcCutSubsetModifier ( const CbcCutSubsetModifier &); /// Destructor virtual ~CbcCutSubsetModifier(); /// Assignment CbcCutSubsetModifier & operator=(const CbcCutSubsetModifier& rhs); /// Clone virtual CbcCutModifier * clone() const ; /** Returns 0 unchanged 1 strengthened 2 weakened 3 deleted */ virtual int modify(const OsiSolverInterface * solver, OsiRowCut & cut) ; /// Create C++ lines to get to current state virtual void generateCpp( FILE * ) {} protected: /// data /// First odd variable int firstOdd_; }; #endif //CbcCutSubsetModifier_H Cbc-2.8.12/src/CbcLinkedUtils.cpp0000644000076600007660000006167712131315050015113 0ustar coincoin// Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* $Id: CbcLinkedUtils.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /*! \file CbcAugmentClpSimplex.cpp \brief Hooks to Ampl (for CbcLinked) This code is a condensation of ClpAmplStuff.cpp, renamed to better reflect its current place in cbc. The code here had ties to NEW_STYLE_SOLVER code. During the 091209 Watson meeting, NEW_STYLE_SOLVER code was eliminated. The code here was condensed from ClpAmplStuff.cpp. The hook into CbcLinked is loadNonLinear. Once you bring that in, all the rest follows. Still, we're down about 400 lines of code. In the process, it appears that ClpAmplObjective.cpp was never needed here; the code was hooked into ClpAmplStuff.cpp. --lh, 091209 -- */ #include "ClpConfig.h" #include "CbcConfig.h" #ifdef COIN_HAS_ASL #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "ClpFactorization.hpp" #include "ClpSimplex.hpp" #include "ClpAmplObjective.hpp" #include "ClpConstraintAmpl.hpp" #include "ClpMessage.hpp" #include "CoinUtilsConfig.h" #include "CoinHelperFunctions.hpp" #include "CoinWarmStartBasis.hpp" #include "OsiSolverInterface.hpp" #include "Cbc_ampl.h" #include "CoinTime.hpp" #include "CglStored.hpp" #include "CoinModel.hpp" #include "CbcLinked.hpp" extern "C" { //# include "getstub.h" # include "asl_pfgh.h" } // stolen from IPopt with changes typedef struct { double obj_sign_; ASL_pfgh * asl_; double * non_const_x_; int * column_; // for jacobian int * rowStart_; double * gradient_; double * constraintValues_; int nz_h_full_; // number of nonzeros in hessian int nerror_; bool objval_called_with_current_x_; bool conval_called_with_current_x_; bool jacval_called_with_current_x_; } CbcAmplInfo; //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpAmplObjective::ClpAmplObjective () : ClpObjective() { type_ = 12; objective_ = NULL; amplObjective_ = NULL; gradient_ = NULL; offset_ = 0.0; } bool get_constraints_linearity(void * amplInfo, int n, int * const_types) { CbcAmplInfo * info = (CbcAmplInfo *) amplInfo; ASL_pfgh* asl = info->asl_; //check that n is good assert(n == n_con); // check that there are no network constraints assert(nlnc == 0 && lnc == 0); //the first nlc constraints are non linear the rest is linear int i; for (i = 0; i < nlc; i++) { const_types[i] = 1; } // the rest is linear for (i = nlc; i < n_con; i++) const_types[i] = 0; return true; } static bool internal_objval(CbcAmplInfo * info , double & obj_val) { ASL_pfgh* asl = info->asl_; info->objval_called_with_current_x_ = false; // in case the call below fails if (n_obj == 0) { obj_val = 0; info->objval_called_with_current_x_ = true; return true; } else { double retval = objval(0, info->non_const_x_, (fint*)&info->nerror_); if (!info->nerror_) { obj_val = info->obj_sign_ * retval; info->objval_called_with_current_x_ = true; return true; } else { abort(); } } return false; } static bool internal_conval(CbcAmplInfo * info , double * g) { ASL_pfgh* asl = info->asl_; info->conval_called_with_current_x_ = false; // in case the call below fails assert (g); conval(info->non_const_x_, g, (fint*)&info->nerror_); if (!info->nerror_) { info->conval_called_with_current_x_ = true; return true; } else { abort(); } return false; } static bool apply_new_x(CbcAmplInfo * info , bool new_x, int n, const double * x) { ASL_pfgh* asl = info->asl_; if (new_x) { // update the flags so these methods are called // before evaluating the hessian info->conval_called_with_current_x_ = false; info->objval_called_with_current_x_ = false; info->jacval_called_with_current_x_ = false; //copy the data to the non_const_x_ if (!info->non_const_x_) { info->non_const_x_ = new double [n]; } for (int i = 0; i < n; i++) { info->non_const_x_[i] = x[i]; } // tell ampl that we have a new x xknowne(info->non_const_x_, (fint*)&info->nerror_); return info->nerror_ ? false : true; } return true; } static bool eval_f(void * amplInfo, int n, const double * x, bool new_x, double & obj_value) { CbcAmplInfo * info = (CbcAmplInfo *) amplInfo; if (!apply_new_x(info, new_x, n, x)) { return false; } return internal_objval(info, obj_value); } static bool eval_grad_f(void * amplInfo, int n, const double * x, bool new_x, double * grad_f) { CbcAmplInfo * info = (CbcAmplInfo *) amplInfo; ASL_pfgh* asl = info->asl_; if (!apply_new_x(info, new_x, n, x)) { return false; } int i; if (n_obj == 0) { for (i = 0; i < n; i++) { grad_f[i] = 0.; } } else { objgrd(0, info->non_const_x_, grad_f, (fint*)&info->nerror_); if (info->nerror_) { return false; } if (info->obj_sign_ == -1) { for (i = 0; i < n; i++) { grad_f[i] = -grad_f[i]; } } } return true; } static bool eval_g(void * amplInfo, int n, const double * x, bool new_x, double * g) { CbcAmplInfo * info = (CbcAmplInfo *) amplInfo; #ifndef NDEBUG ASL_pfgh* asl = info->asl_; #endif // warning: n_var is a macro that assumes we have a variable called asl assert(n == n_var); if (!apply_new_x(info, new_x, n, x)) { return false; } return internal_conval(info, g); } static bool eval_jac_g(void * amplInfo, int n, const double * x, bool new_x, double * values) { CbcAmplInfo * info = (CbcAmplInfo *) amplInfo; ASL_pfgh* asl = info->asl_; assert(n == n_var); assert (values); if (!apply_new_x(info, new_x, n, x)) { return false; } jacval(info->non_const_x_, values, (fint*)&info->nerror_); if (!info->nerror_) { return true; } else { abort(); } return false; } //------------------------------------------------------------------- // Useful Constructor //------------------------------------------------------------------- ClpAmplObjective::ClpAmplObjective (void * amplInfo) : ClpObjective() { type_ = 12; activated_ = 1; gradient_ = NULL; objective_ = NULL; offset_ = 0.0; amplObjective_ = amplInfo; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpAmplObjective::ClpAmplObjective (const ClpAmplObjective & rhs) : ClpObjective(rhs) { amplObjective_ = rhs.amplObjective_; offset_ = rhs.offset_; type_ = rhs.type_; if (!amplObjective_) { objective_ = NULL; gradient_ = NULL; } else { CbcAmplInfo * info = (CbcAmplInfo *) amplObjective_; ASL_pfgh* asl = info->asl_; int numberColumns = n_var;; if (rhs.objective_) { objective_ = new double [numberColumns]; memcpy(objective_, rhs.objective_, numberColumns*sizeof(double)); } else { objective_ = NULL; } if (rhs.gradient_) { gradient_ = new double [numberColumns]; memcpy(gradient_, rhs.gradient_, numberColumns*sizeof(double)); } else { gradient_ = NULL; } } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpAmplObjective::~ClpAmplObjective () { delete [] objective_; delete [] gradient_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpAmplObjective & ClpAmplObjective::operator=(const ClpAmplObjective & rhs) { if (this != &rhs) { delete [] objective_; delete [] gradient_; amplObjective_ = rhs.amplObjective_; offset_ = rhs.offset_; type_ = rhs.type_; if (!amplObjective_) { objective_ = NULL; gradient_ = NULL; } else { CbcAmplInfo * info = (CbcAmplInfo *) amplObjective_; ASL_pfgh* asl = info->asl_; int numberColumns = n_var;; if (rhs.objective_) { objective_ = new double [numberColumns]; memcpy(objective_, rhs.objective_, numberColumns*sizeof(double)); } else { objective_ = NULL; } if (rhs.gradient_) { gradient_ = new double [numberColumns]; memcpy(gradient_, rhs.gradient_, numberColumns*sizeof(double)); } else { gradient_ = NULL; } } } return *this; } // Returns gradient double * ClpAmplObjective::gradient(const ClpSimplex * model, const double * solution, double & offset, bool refresh, int includeLinear) { if (model) assert (model->optimizationDirection() == 1.0); #ifndef NDEBUG bool scaling = model && (model->rowScale() || model->objectiveScale() != 1.0 || model->optimizationDirection() != 1.0); #endif const double * cost = NULL; if (model) cost = model->costRegion(); if (!cost) { // not in solve cost = objective_; #ifndef NDEBUG scaling = false; #endif } assert (!scaling); if (!amplObjective_ || !solution || !activated_) { offset = offset_; return objective_; } else { if (refresh || !gradient_) { CbcAmplInfo * info = (CbcAmplInfo *) amplObjective_; ASL_pfgh* asl = info->asl_; int numberColumns = n_var;; if (!gradient_) gradient_ = new double[numberColumns]; assert (solution); eval_grad_f(amplObjective_, numberColumns, solution, true, gradient_); // Is this best way? double objValue = 0.0; eval_f(amplObjective_, numberColumns, solution, false, objValue); double objValue2 = 0.0; for (int i = 0; i < numberColumns; i++) objValue2 += gradient_[i] * solution[i]; offset_ = objValue2 - objValue; // or other way??? if (model && model->optimizationDirection() != 1.0) { offset *= model->optimizationDirection(); for (int i = 0; i < numberColumns; i++) gradient_[i] *= -1.0; } } offset = offset_; return gradient_; } } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpObjective * ClpAmplObjective::clone() const { return new ClpAmplObjective(*this); } // Resize objective void ClpAmplObjective::resize(int newNumberColumns) { CbcAmplInfo * info = (CbcAmplInfo *) amplObjective_; ASL_pfgh* asl = info->asl_; int numberColumns = n_var;; if (numberColumns != newNumberColumns) { abort(); } } // Delete columns in objective void ClpAmplObjective::deleteSome(int numberToDelete, const int * which) { if (numberToDelete) abort(); } /* Returns reduced gradient.Returns an offset (to be added to current one). */ double ClpAmplObjective::reducedGradient(ClpSimplex * model, double * region, bool useFeasibleCosts) { int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); //work space CoinIndexedVector * workSpace = model->rowArray(0); CoinIndexedVector arrayVector; arrayVector.reserve(numberRows + 1); int iRow; #ifdef CLP_DEBUG workSpace->checkClear(); #endif double * array = arrayVector.denseVector(); int * index = arrayVector.getIndices(); int number = 0; const double * costNow = gradient(model, model->solutionRegion(), offset_, true, useFeasibleCosts ? 2 : 1); double * cost = model->costRegion(); const int * pivotVariable = model->pivotVariable(); for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; double value; if (iPivot < numberColumns) value = costNow[iPivot]; else if (!useFeasibleCosts) value = cost[iPivot]; else value = 0.0; if (value) { array[iRow] = value; index[number++] = iRow; } } arrayVector.setNumElements(number); // Btran basic costs model->factorization()->updateColumnTranspose(workSpace, &arrayVector); double * work = workSpace->denseVector(); ClpFillN(work, numberRows, 0.0); // now look at dual solution double * rowReducedCost = region + numberColumns; double * dual = rowReducedCost; const double * rowCost = cost + numberColumns; for (iRow = 0; iRow < numberRows; iRow++) { dual[iRow] = array[iRow]; } double * dj = region; ClpDisjointCopyN(costNow, numberColumns, dj); model->transposeTimes(-1.0, dual, dj); for (iRow = 0; iRow < numberRows; iRow++) { // slack double value = dual[iRow]; value += rowCost[iRow]; rowReducedCost[iRow] = value; } return offset_; } /* Returns step length which gives minimum of objective for solution + theta * change vector up to maximum theta. arrays are numberColumns+numberRows */ double ClpAmplObjective::stepLength(ClpSimplex * model, const double * solution, const double * change, double maximumTheta, double & currentObj, double & predictedObj, double & thetaObj) { // Assume convex CbcAmplInfo * info = (CbcAmplInfo *) amplObjective_; ASL_pfgh* asl = info->asl_; int numberColumns = n_var;; double * tempSolution = new double [numberColumns]; double * tempGradient = new double [numberColumns]; // current eval_f(amplObjective_, numberColumns, solution, true, currentObj); double objA = currentObj; double thetaA = 0.0; // at maximum int i; for (i = 0; i < numberColumns; i++) tempSolution[i] = solution[i] + maximumTheta * change[i]; eval_f(amplObjective_, numberColumns, tempSolution, true, thetaObj); double objC = thetaObj; double thetaC = maximumTheta; double objB = 0.5 * (objA + objC); double thetaB = 0.5 * maximumTheta; double gradientNorm = 1.0e6; while (gradientNorm > 1.0e-6 && thetaC - thetaA > 1.0e-8) { for (i = 0; i < numberColumns; i++) tempSolution[i] = solution[i] + thetaB * change[i]; eval_grad_f(amplObjective_, numberColumns, tempSolution, true, tempGradient); eval_f(amplObjective_, numberColumns, tempSolution, false, objB); double changeObj = 0.0; gradientNorm = 0.0; for (i = 0; i < numberColumns; i++) { changeObj += tempGradient[i] * change[i]; gradientNorm += tempGradient[i] * tempGradient[i]; } gradientNorm = fabs(changeObj) / sqrt(gradientNorm); // Should try and get quadratic convergence by interpolation if (changeObj < 0.0) { // increasing is good thetaA = thetaB; } else { // decreasing is good thetaC = thetaB; } thetaB = 0.5 * (thetaA + thetaC); } delete [] tempSolution; delete [] tempGradient; predictedObj = objB; return thetaB; } // Return objective value (without any ClpModel offset) (model may be NULL) double ClpAmplObjective::objectiveValue(const ClpSimplex * model, const double * solution) const { CbcAmplInfo * info = (CbcAmplInfo *) amplObjective_; ASL_pfgh* asl = info->asl_; int numberColumns = n_var;; // current double currentObj = 0.0; eval_f(amplObjective_, numberColumns, solution, true, currentObj); return currentObj; } // Scale objective void ClpAmplObjective::reallyScale(const double * columnScale) { abort(); } /* Given a zeroed array sets nonlinear columns to 1. Returns number of nonlinear columns */ int ClpAmplObjective::markNonlinear(char * which) { int iColumn; CbcAmplInfo * info = (CbcAmplInfo *) amplObjective_; ASL_pfgh* asl = info->asl_; int nonLinear = CoinMax(nlvc, nlvo); for (iColumn = 0; iColumn < nonLinear; iColumn++) { which[iColumn] = 1; } int numberNonLinearColumns = 0; int numberColumns = n_var;; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (which[iColumn]) numberNonLinearColumns++; } return numberNonLinearColumns; } // Say we have new primal solution - so may need to recompute void ClpAmplObjective::newXValues() { CbcAmplInfo * info = (CbcAmplInfo *) amplObjective_; info->conval_called_with_current_x_ = false; info->objval_called_with_current_x_ = false; info->jacval_called_with_current_x_ = false; } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpConstraintAmpl::ClpConstraintAmpl () : ClpConstraint() { type_ = 3; column_ = NULL; coefficient_ = NULL; numberCoefficients_ = 0; amplInfo_ = NULL; } //------------------------------------------------------------------- // Useful Constructor //------------------------------------------------------------------- ClpConstraintAmpl::ClpConstraintAmpl (int row, void * amplInfo) : ClpConstraint() { type_ = 3; rowNumber_ = row; amplInfo_ = amplInfo; CbcAmplInfo * info = (CbcAmplInfo *) amplInfo_; #ifndef NDEBUG ASL_pfgh* asl = info->asl_; #endif // warning: nlc is a macro that assumes we have a variable called asl assert (rowNumber_ < nlc); numberCoefficients_ = info->rowStart_[rowNumber_+1] - info->rowStart_[rowNumber_]; column_ = CoinCopyOfArray(info->column_ + info->rowStart_[rowNumber_], numberCoefficients_); coefficient_ = new double [numberCoefficients_];; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpConstraintAmpl::ClpConstraintAmpl (const ClpConstraintAmpl & rhs) : ClpConstraint(rhs) { numberCoefficients_ = rhs.numberCoefficients_; column_ = CoinCopyOfArray(rhs.column_, numberCoefficients_); coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberCoefficients_); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpConstraintAmpl::~ClpConstraintAmpl () { delete [] column_; delete [] coefficient_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpConstraintAmpl & ClpConstraintAmpl::operator=(const ClpConstraintAmpl & rhs) { if (this != &rhs) { delete [] column_; delete [] coefficient_; numberCoefficients_ = rhs.numberCoefficients_; column_ = CoinCopyOfArray(rhs.column_, numberCoefficients_); coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberCoefficients_); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpConstraint * ClpConstraintAmpl::clone() const { return new ClpConstraintAmpl(*this); } // Returns gradient int ClpConstraintAmpl::gradient(const ClpSimplex * model, const double * solution, double * gradient, double & functionValue, double & offset, bool useScaling, bool refresh) const { CbcAmplInfo * info = (CbcAmplInfo *) amplInfo_; ASL_pfgh* asl = info->asl_; int numberColumns = n_var;; // If not done then do all if (!info->jacval_called_with_current_x_) { bool getStuff = eval_g(amplInfo_, numberColumns, solution, true, info->constraintValues_); assert (getStuff); getStuff = eval_jac_g(amplInfo_, numberColumns, solution, false, info->gradient_); assert (getStuff); info->jacval_called_with_current_x_ = getStuff; } if (refresh || !lastGradient_) { functionValue_ = info->constraintValues_[rowNumber_]; offset_ = functionValue_; // sign?? if (!lastGradient_) lastGradient_ = new double[numberColumns]; CoinZeroN(lastGradient_, numberColumns); assert (!(model && model->rowScale() && useScaling)); int i; int start = info->rowStart_[rowNumber_]; assert (numberCoefficients_ == info->rowStart_[rowNumber_+1] - start); for (i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; double valueS = solution[iColumn]; double valueG = info->gradient_[start+i]; lastGradient_[iColumn] = valueG; offset_ -= valueS * valueG; } } functionValue = functionValue_; offset = offset_; memcpy(gradient, lastGradient_, numberColumns*sizeof(double)); return 0; } // Resize constraint void ClpConstraintAmpl::resize(int newNumberColumns) { abort(); } // Delete columns in constraint void ClpConstraintAmpl::deleteSome(int numberToDelete, const int * which) { if (numberToDelete) { abort(); } } // Scale constraint void ClpConstraintAmpl::reallyScale(const double * columnScale) { abort(); } /* Given a zeroed array sets nonlinear columns to 1. Returns number of nonlinear columns */ int ClpConstraintAmpl::markNonlinear(char * which) const { CbcAmplInfo * info = (CbcAmplInfo *) amplInfo_; ASL_pfgh* asl = info->asl_; int iColumn; int numberNon = 0; int nonLinear = CoinMax(nlvc, nlvo); for (iColumn = 0; iColumn < numberCoefficients_; iColumn++) { int jColumn = column_[iColumn]; if (jColumn < nonLinear) { which[jColumn] = 1; numberNon++; } } return numberNon; } /* Given a zeroed array sets possible nonzero coefficients to 1. Returns number of nonzeros */ int ClpConstraintAmpl::markNonzero(char * which) const { int iColumn; for (iColumn = 0; iColumn < numberCoefficients_; iColumn++) { which[column_[iColumn]] = 1; } return numberCoefficients_; } // Number of coefficients int ClpConstraintAmpl::numberCoefficients() const { return numberCoefficients_; } // Say we have new primal solution - so may need to recompute void ClpConstraintAmpl::newXValues() { CbcAmplInfo * info = (CbcAmplInfo *) amplInfo_; info->conval_called_with_current_x_ = false; info->objval_called_with_current_x_ = false; info->jacval_called_with_current_x_ = false; } /* Load nonlinear part of problem from AMPL info Returns 0 if linear 1 if quadratic objective 2 if quadratic constraints 3 if nonlinear objective 4 if nonlinear constraints -1 on failure */ int ClpSimplex::loadNonLinear(void * amplInfo, int & numberConstraints, ClpConstraint ** & constraints) { numberConstraints = 0; constraints = NULL; CbcAmplInfo * info = (CbcAmplInfo *) amplInfo; ASL_pfgh* asl = info->asl_; // For moment don't say quadratic int type = 0; if (nlo + nlc) { // nonlinear if (!nlc) { type = 3; delete objective_; objective_ = new ClpAmplObjective(amplInfo); } else { type = 4; numberConstraints = nlc; constraints = new ClpConstraint * [numberConstraints]; if (nlo) { delete objective_; objective_ = new ClpAmplObjective(amplInfo); } for (int i = 0; i < numberConstraints; i++) { constraints[i] = new ClpConstraintAmpl(i, amplInfo); } } } return type; } #else #include "ClpSimplex.hpp" #include "ClpConstraint.hpp" int ClpSimplex::loadNonLinear(void * , int & , ClpConstraint ** & ) { abort(); return 0; } #endif Cbc-2.8.12/src/CbcTreeLocal.hpp0000644000076600007660000002603211510742604014536 0ustar coincoin/* $Id: CbcTreeLocal.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcTreeLocal_H #define CbcTreeLocal_H //############################################################################# /* This implements (approximately) local branching as in the 2002 paper by Matteo Fischetti and Andrea Lodi. The very simple version of the algorithm for problems with 0-1 variables and continuous is as follows: Obtain a feasible solution (one can be passed in). Add a cut which limits search to a k neighborhood of this solution. (At most k 0-1 variables may change value) Do branch and bound on this problem. If finished search and proven optimal then we can reverse cut so any solutions must be at least k+1 away from solution and we can add a new cut limiting search to a k neighborhood of new solution repeat. If finished search and no new solution then the simplest version would reverse last cut and complete search. The version implemented here can use time and node limits and can widen search (increase effective k) .... and more */ #include "CbcTree.hpp" #include "CbcNode.hpp" #include "OsiRowCut.hpp" class CbcModel; class CbcTreeLocal : public CbcTree { public: // Default Constructor CbcTreeLocal (); /* Constructor with solution. If solution NULL no solution, otherwise must be integer range is initial upper bound (k) on difference from given solution. typeCuts - 0 means just 0-1 cuts and will need to refine 0-1 solution 1 uses weaker cuts on all integer variables maxDiversification is maximum number of range widenings to try timeLimit is seconds in subTree nodeLimit is nodes in subTree refine is whether to see if we can prove current solution is optimal when we fix all 0-1 (in case typeCuts==0 and there are general integer variables) if false then no refinement but reverse cuts weaker */ CbcTreeLocal (CbcModel * model, const double * solution , int range = 10, int typeCuts = 0, int maxDiversification = 0, int timeLimit = 1000000, int nodeLimit = 1000000, bool refine = true); // Copy constructor CbcTreeLocal ( const CbcTreeLocal & rhs); // = operator CbcTreeLocal & operator=(const CbcTreeLocal & rhs); virtual ~CbcTreeLocal(); /// Clone virtual CbcTree * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /*! \name Heap access and maintenance methods */ //@{ /// Return the top node of the heap virtual CbcNode * top() const; /// Add a node to the heap virtual void push(CbcNode * x); /// Remove the top node from the heap virtual void pop() ; //@} /*! \name Other stuff */ //@{ /// Create cut - return -1 if bad, 0 if okay and 1 if cut is everything int createCut(const double * solution, OsiRowCut & cut); /// Test if empty *** note may be overridden virtual bool empty() ; /// We may have got an intelligent tree so give it one more chance virtual void endSearch() ; /// Other side of last cut branch (if bias==rhs_ will be weakest possible) void reverseCut(int state, double bias = 0.0); /// Delete last cut branch void deleteCut(OsiRowCut & cut); /// Pass in solution (so can be used after heuristic) void passInSolution(const double * solution, double solutionValue); // range i.e. k inline int range() const { return range_; } // setrange i.e. k inline void setRange(int value) { range_ = value; } // Type of cuts - 0=just 0-1, 1=all inline int typeCuts() const { return typeCuts_; } // Type of cuts - 0=just 0-1, 1=all inline void setTypeCuts(int value) { typeCuts_ = value; } // maximum number of diversifications inline int maxDiversification() const { return maxDiversification_; } // maximum number of diversifications inline void setMaxDiversification(int value) { maxDiversification_ = value; } // time limit per subtree inline int timeLimit() const { return timeLimit_; } // time limit per subtree inline void setTimeLimit(int value) { timeLimit_ = value; } // node limit for subtree inline int nodeLimit() const { return nodeLimit_; } // node limit for subtree inline void setNodeLimit(int value) { nodeLimit_ = value; } // Whether to do refinement step inline bool refine() const { return refine_; } // Whether to do refinement step inline void setRefine(bool yesNo) { refine_ = yesNo; } //@} private: // Node for local cuts CbcNode * localNode_; // best solution double * bestSolution_; // saved solution double * savedSolution_; // solution number at start of pass int saveNumberSolutions_; /* Cut. If zero size then no solution yet. Otherwise is left hand branch */ OsiRowCut cut_; // This cut fixes all 0-1 variables OsiRowCut fixedCut_; // Model CbcModel * model_; // Original lower bounds double * originalLower_; // Original upper bounds double * originalUpper_; // range i.e. k int range_; // Type of cuts - 0=just 0-1, 1=all int typeCuts_; // maximum number of diversifications int maxDiversification_; // current diversification int diversification_; // Whether next will be strong diversification bool nextStrong_; // Current rhs double rhs_; // Save allowable gap double savedGap_; // Best solution double bestCutoff_; // time limit per subtree int timeLimit_; // time when subtree started int startTime_; // node limit for subtree int nodeLimit_; // node count when subtree started int startNode_; // -1 not started, 0 == stop on first solution, 1 don't stop on first, 2 refinement step int searchType_; // Whether to do refinement step bool refine_; }; class CbcTreeVariable : public CbcTree { public: // Default Constructor CbcTreeVariable (); /* Constructor with solution. If solution NULL no solution, otherwise must be integer range is initial upper bound (k) on difference from given solution. typeCuts - 0 means just 0-1 cuts and will need to refine 0-1 solution 1 uses weaker cuts on all integer variables maxDiversification is maximum number of range widenings to try timeLimit is seconds in subTree nodeLimit is nodes in subTree refine is whether to see if we can prove current solution is optimal when we fix all 0-1 (in case typeCuts==0 and there are general integer variables) if false then no refinement but reverse cuts weaker */ CbcTreeVariable (CbcModel * model, const double * solution , int range = 10, int typeCuts = 0, int maxDiversification = 0, int timeLimit = 1000000, int nodeLimit = 1000000, bool refine = true); // Copy constructor CbcTreeVariable ( const CbcTreeVariable & rhs); // = operator CbcTreeVariable & operator=(const CbcTreeVariable & rhs); virtual ~CbcTreeVariable(); /// Clone virtual CbcTree * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /*! \name Heap access and maintenance methods */ //@{ /// Return the top node of the heap virtual CbcNode * top() const; /// Add a node to the heap virtual void push(CbcNode * x); /// Remove the top node from the heap virtual void pop() ; //@} /*! \name Other stuff */ //@{ /// Create cut - return -1 if bad, 0 if okay and 1 if cut is everything int createCut(const double * solution, OsiRowCut & cut); /// Test if empty *** note may be overridden virtual bool empty() ; /// We may have got an intelligent tree so give it one more chance virtual void endSearch() ; /// Other side of last cut branch (if bias==rhs_ will be weakest possible) void reverseCut(int state, double bias = 0.0); /// Delete last cut branch void deleteCut(OsiRowCut & cut); /// Pass in solution (so can be used after heuristic) void passInSolution(const double * solution, double solutionValue); // range i.e. k inline int range() const { return range_; } // setrange i.e. k inline void setRange(int value) { range_ = value; } // Type of cuts - 0=just 0-1, 1=all inline int typeCuts() const { return typeCuts_; } // Type of cuts - 0=just 0-1, 1=all inline void setTypeCuts(int value) { typeCuts_ = value; } // maximum number of diversifications inline int maxDiversification() const { return maxDiversification_; } // maximum number of diversifications inline void setMaxDiversification(int value) { maxDiversification_ = value; } // time limit per subtree inline int timeLimit() const { return timeLimit_; } // time limit per subtree inline void setTimeLimit(int value) { timeLimit_ = value; } // node limit for subtree inline int nodeLimit() const { return nodeLimit_; } // node limit for subtree inline void setNodeLimit(int value) { nodeLimit_ = value; } // Whether to do refinement step inline bool refine() const { return refine_; } // Whether to do refinement step inline void setRefine(bool yesNo) { refine_ = yesNo; } //@} private: // Node for local cuts CbcNode * localNode_; // best solution double * bestSolution_; // saved solution double * savedSolution_; // solution number at start of pass int saveNumberSolutions_; /* Cut. If zero size then no solution yet. Otherwise is left hand branch */ OsiRowCut cut_; // This cut fixes all 0-1 variables OsiRowCut fixedCut_; // Model CbcModel * model_; // Original lower bounds double * originalLower_; // Original upper bounds double * originalUpper_; // range i.e. k int range_; // Type of cuts - 0=just 0-1, 1=all int typeCuts_; // maximum number of diversifications int maxDiversification_; // current diversification int diversification_; // Whether next will be strong diversification bool nextStrong_; // Current rhs double rhs_; // Save allowable gap double savedGap_; // Best solution double bestCutoff_; // time limit per subtree int timeLimit_; // time when subtree started int startTime_; // node limit for subtree int nodeLimit_; // node count when subtree started int startNode_; // -1 not started, 0 == stop on first solution, 1 don't stop on first, 2 refinement step int searchType_; // Whether to do refinement step bool refine_; }; #endif Cbc-2.8.12/src/Makefile.am0000644000076600007660000002305712376140747013616 0ustar coincoin# Copyright (C) 2006, 2007 International Business Machines and others. # All Rights Reserved. # This file is distributed under the Eclipse Public License. ## $Id: Makefile.am 2059 2014-08-23 16:31:35Z tkr $ # Author: Andreas Waechter IBM 2006-04-13 AUTOMAKE_OPTIONS = foreign ######################################################################## # libCbc # ######################################################################## # Name of the library compiled in this directory. We want it to be installed # in the 'lib' directory lib_LTLIBRARIES = libCbc.la libCbcSolver.la # List all source files for this library, including headers libCbc_la_SOURCES = \ CbcConfig.h \ CbcBranchActual.hpp \ CbcBranchAllDifferent.cpp CbcBranchAllDifferent.hpp \ CbcBranchBase.hpp \ CbcBranchCut.cpp CbcBranchCut.hpp \ CbcBranchDecision.cpp CbcBranchDecision.hpp \ CbcBranchDefaultDecision.cpp CbcBranchDefaultDecision.hpp \ CbcBranchDynamic.cpp CbcBranchDynamic.hpp \ CbcBranchingObject.cpp CbcBranchingObject.hpp \ CbcBranchLotsize.cpp CbcBranchLotsize.hpp \ CbcBranchToFixLots.cpp CbcBranchToFixLots.hpp \ CbcCompareActual.hpp \ CbcCompareBase.hpp \ CbcCompareDefault.cpp CbcCompareDefault.hpp \ CbcCompareDepth.cpp CbcCompareDepth.hpp \ CbcCompareEstimate.cpp CbcCompareEstimate.hpp \ CbcCompareObjective.cpp CbcCompareObjective.hpp \ CbcConsequence.cpp CbcConsequence.hpp \ CbcClique.cpp CbcClique.hpp \ CbcCompare.hpp \ CbcCountRowCut.cpp CbcCountRowCut.hpp \ CbcCutGenerator.cpp CbcCutGenerator.hpp \ CbcCutModifier.cpp CbcCutModifier.hpp \ CbcCutSubsetModifier.cpp CbcCutSubsetModifier.hpp \ CbcDummyBranchingObject.cpp CbcDummyBranchingObject.hpp \ CbcEventHandler.cpp CbcEventHandler.hpp \ CbcFathom.cpp CbcFathom.hpp \ CbcFathomDynamicProgramming.cpp CbcFathomDynamicProgramming.hpp \ CbcFeasibilityBase.hpp \ CbcFixVariable.cpp CbcFixVariable.hpp \ CbcFullNodeInfo.cpp CbcFullNodeInfo.hpp \ CbcFollowOn.cpp CbcFollowOn.hpp \ CbcGeneral.cpp CbcGeneral.hpp \ CbcGeneralDepth.cpp CbcGeneralDepth.hpp \ CbcHeuristic.cpp CbcHeuristic.hpp \ CbcHeuristicDINS.cpp CbcHeuristicDINS.hpp \ CbcHeuristicDive.cpp CbcHeuristicDive.hpp \ CbcHeuristicDiveCoefficient.cpp CbcHeuristicDiveCoefficient.hpp \ CbcHeuristicDiveFractional.cpp CbcHeuristicDiveFractional.hpp \ CbcHeuristicDiveGuided.cpp CbcHeuristicDiveGuided.hpp \ CbcHeuristicDiveLineSearch.cpp CbcHeuristicDiveLineSearch.hpp \ CbcHeuristicDivePseudoCost.cpp CbcHeuristicDivePseudoCost.hpp \ CbcHeuristicDiveVectorLength.cpp CbcHeuristicDiveLength.hpp \ CbcHeuristicFPump.cpp CbcHeuristicFPump.hpp \ CbcHeuristicGreedy.cpp CbcHeuristicGreedy.hpp \ CbcHeuristicLocal.cpp CbcHeuristicLocal.hpp \ CbcHeuristicPivotAndFix.cpp CbcHeuristicPivotAndFix.hpp \ CbcHeuristicRandRound.cpp CbcHeuristicRandRound.hpp \ CbcHeuristicRENS.cpp CbcHeuristicRENS.hpp \ CbcHeuristicRINS.cpp CbcHeuristicRINS.hpp \ CbcHeuristicVND.cpp CbcHeuristicVND.hpp \ CbcMessage.cpp CbcMessage.hpp \ CbcModel.cpp CbcModel.hpp \ CbcNode.cpp CbcNode.hpp \ CbcNodeInfo.cpp CbcNodeInfo.hpp \ CbcNWay.cpp CbcNWay.hpp \ CbcObject.cpp CbcObject.hpp \ CbcObjectUpdateData.cpp CbcObjectUpdateData.hpp \ CbcPartialNodeInfo.cpp CbcPartialNodeInfo.hpp \ CbcSimpleInteger.cpp CbcSimpleInteger.hpp \ CbcSimpleIntegerDynamicPseudoCost.cpp \ CbcSimpleIntegerDynamicPseudoCost.hpp \ CbcSimpleIntegerPseudoCost.cpp \ CbcSimpleIntegerPseudoCost.hpp \ CbcSOS.cpp CbcSOS.hpp \ CbcStatistics.cpp CbcStatistics.hpp \ CbcStrategy.cpp CbcStrategy.hpp \ CbcSubProblem.cpp CbcSubProblem.hpp \ CbcThread.cpp CbcThread.hpp \ CbcTree.cpp CbcTree.hpp \ CbcTreeLocal.cpp CbcTreeLocal.hpp libCbcSolver_la_SOURCES = \ Cbc_C_Interface.cpp Cbc_C_Interface.h \ CbcCbcParam.cpp \ Cbc_ampl.cpp Cbc_ampl.h \ CbcLinked.cpp CbcLinked.hpp CbcLinkedUtils.cpp \ unitTestClp.cpp CbcSolver.cpp \ CbcSolverHeuristics.cpp CbcSolverHeuristics.hpp \ CbcSolverAnalyze.cpp CbcSolverAnalyze.hpp \ CbcMipStartIO.cpp CbcMipStartIO.hpp \ CbcSolverExpandKnapsack.cpp CbcSolverExpandKnapsack.hpp # List all additionally required libraries if DEPENDENCY_LINKING libCbc_la_LIBADD = $(CBCLIB_LIBS) libCbcSolver_la_LIBADD = $(CBCLIB_LIBS) libCbc.la endif # This is for libtool libCbc_la_LDFLAGS = $(LT_LDFLAGS) libCbcSolver_la_LDFLAGS = $(LT_LDFLAGS) # Some common setup for cbc and cbc-generic. bin_PROGRAMS = AM_CPPFLAGS = $(COINDEPEND_CFLAGS) $(CLP_CFLAGS) $(CPX_CFLAGS) $(ASL_CFLAGS) ######################################################################## # cbc program # ######################################################################## if COIN_HAS_CLP # Name of the executable compiled in this directory. We want it to be # installed in the 'bin' directory bin_PROGRAMS += cbc # List all source files for this executable, including headers cbc_SOURCES = CoinSolve.cpp # Additional libraries cbc_LDADD = libCbcSolver.la libCbc.la $(CBCLIB_LIBS) $(ASL_LIBS) cbc_DEPENDENCIES = libCbcSolver.la libCbc.la $(CBCLIB_DEPENDENCIES) $(ASL_DEPENDENCIES) endif ######################################################################## # cbc-generic program # ######################################################################## if CBC_BUILD_CBC_GENERIC # Name of the executable compiled in this directory. We want it to be # installed in the 'bin' directory bin_PROGRAMS += cbc-generic # List all source files for this executable, including headers cbc_generic_SOURCES = \ CbcGenBaB.cpp \ CbcGenCbcParam.cpp CbcGenCbcParam.hpp CbcGenCbcParamUtils.cpp \ CbcGenCtlBlk.cpp CbcGenCtlBlk.hpp \ CbcGeneric.cpp \ CbcGenMessages.cpp CbcGenMessages.hpp \ CbcGenOsiParam.cpp CbcGenOsiParam.hpp CbcGenOsiParamUtils.cpp \ CbcGenParam.cpp CbcGenParam.hpp CbcGenParamUtils.cpp \ CbcGenSolution.cpp \ CbcGenSolvers.cpp cbc_generic_LDADD = libCbcSolver.la libCbc.la $(CBCGENERIC_LIBS) cbc_generic_DEPENDENCIES = libCbcSolver.la libCbc.la $(CBCGENERIC_DEPENDENCIES) # List all additionally required solver and Osi libraries # the linker flags for all available LP solvers should already be included in $CBCGENERIC_LIBS, # so just add compiler flags here (all we can think of) AM_CPPFLAGS += $(DYLP_CFLAGS) $(GLPK_CFLAGS) $(MSK_CFLAGS) $(SPX_CFLAGS) $(VOL_CFLAGS) $(XPR_CFLAGS) endif ######################################################################## # Additional flags # ######################################################################## # List additional defines AM_CPPFLAGS += -DCOIN_NO_CLP_MESSAGE -DUSE_CBCCONFIG # This line is necessary to allow VPATH compilation DEFAULT_INCLUDES = -I. -I`$(CYGPATH_W) $(srcdir)` -I$(top_builddir)/src ######################################################################## # Headers that need to be installed # ######################################################################## # Here list all the header files that are required by a user of the library, # and that therefore should be installed in 'include/coin' includecoindir = $(includedir)/coin includecoin_HEADERS = \ Cbc_C_Interface.h \ CbcBranchActual.hpp \ CbcBranchAllDifferent.hpp \ CbcBranchBase.hpp \ CbcBranchDynamic.hpp \ CbcBranchCut.hpp \ CbcBranchDecision.hpp \ CbcBranchDefaultDecision.hpp \ CbcBranchingObject.hpp \ CbcBranchLotsize.hpp \ CbcBranchToFixLots.hpp \ CbcCompareActual.hpp \ CbcCompareBase.hpp \ CbcCompareDefault.hpp \ CbcCompareDepth.hpp \ CbcCompareEstimate.hpp \ CbcCompareObjective.hpp \ CbcConsequence.hpp \ CbcClique.hpp \ CbcCompare.hpp \ CbcCountRowCut.hpp \ CbcCutGenerator.hpp \ CbcCutModifier.hpp \ CbcCutSubsetModifier.hpp \ CbcDummyBranchingObject.hpp \ CbcFathom.hpp \ CbcEventHandler.hpp \ CbcFathomDynamicProgramming.hpp \ CbcFeasibilityBase.hpp \ CbcFixVariable.hpp \ CbcFollowOn.hpp \ CbcFullNodeInfo.hpp \ CbcGeneral.hpp \ CbcGeneralDepth.hpp \ CbcHeuristic.hpp \ CbcHeuristicDINS.hpp \ CbcHeuristicDive.hpp \ CbcHeuristicDiveCoefficient.hpp \ CbcHeuristicDiveFractional.hpp \ CbcHeuristicDiveGuided.hpp \ CbcHeuristicDiveLineSearch.hpp \ CbcHeuristicDivePseudoCost.hpp \ CbcHeuristicDiveVectorLength.hpp \ CbcHeuristicFPump.hpp \ CbcHeuristicGreedy.hpp \ CbcHeuristicLocal.hpp \ CbcHeuristicPivotAndFix.hpp \ CbcHeuristicRandRound.hpp \ CbcHeuristicRENS.hpp \ CbcHeuristicRINS.hpp \ CbcHeuristicVND.hpp \ CbcMessage.hpp \ CbcModel.hpp \ CbcNode.hpp \ CbcNodeInfo.hpp \ CbcNWay.hpp \ CbcObject.hpp \ CbcObjectUpdateData.hpp \ CbcPartialNodeInfo.hpp \ CbcSimpleInteger.hpp \ CbcSimpleIntegerDynamicPseudoCost.hpp \ CbcSimpleIntegerPseudoCost.hpp \ CbcStrategy.hpp \ CbcSolver.hpp \ CbcMipStartIO.hpp \ CbcSOS.hpp \ CbcSubProblem.hpp \ CbcTree.hpp \ CbcLinked.hpp \ CbcTreeLocal.hpp \ ClpConstraintAmpl.hpp \ ClpAmplObjective.hpp ######################################################################## # Installing manifest (MSVC++) # ######################################################################## if COIN_CXX_IS_CL install-exec-hook: test -s cbc.exe.manifest && \ mt -manifest cbc.exe.manifest -outputresource:cbc.exe;\ cp cbc.exe $(bindir)/cbc.exe endif ####################################################################### # Create the Config.h file that has all public defines and install it # ####################################################################### install-exec-local: $(install_sh_DATA) config_cbc.h $(DESTDIR)$(includecoindir)/CbcConfig.h uninstall-local: rm -f $(DESTDIR)$(includecoindir)/CbcConfig.h Cbc-2.8.12/src/CbcThread.hpp0000644000076600007660000002735512314276652014114 0ustar coincoin/* $Id: CbcThread.hpp 2023 2014-03-25 12:59:22Z forrest $ */ // Copyright (C) 2009, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcThread_H #define CbcThread_H #include "CbcModel.hpp" #include "CbcNode.hpp" class OsiObject; class OsiCuts; #ifdef CBC_THREAD class CbcThread; // Use pthreads #define CBC_PTHREAD #ifdef CBC_PTHREAD #include typedef struct { pthread_t thr; long status; } Coin_pthread_t; #endif //#define THREAD_DEBUG 1 /** A class to encapsulate specific thread stuff To use another api with same style - you just need to implement these methods. At present just pthreads */ class CbcSpecificThread { public: // Default Constructor CbcSpecificThread (); // Useful Constructor CbcSpecificThread (CbcSpecificThread * master, pthread_mutex_t * masterMutex); virtual ~CbcSpecificThread(); // Useful stuff void setUsefulStuff (CbcSpecificThread * master, void *& masterMutex); /** Locks a thread if parallel so that stuff like cut pool can be updated and/or used. */ void lockThread(); /** Unlocks a thread if parallel to say cut pool stuff not needed */ void unlockThread(); /// Locks a thread for testing whether to start etc void lockThread2(bool doAnyway = false); /// Unlocks a thread for testing whether to start etc void unlockThread2(bool doAnyway = false); /// Signal void signal(); /// Timed wait in nanoseconds - if negative then seconds void timedWait(int time); /// Actually starts a thread void startThread(void * (*routine ) (void *), CbcThread * thread); /// Exits thread (called from master) - return code should be zero int exit(); /// Exits thread void exitThread(); /// Get status int status() const; /// Set status void setStatus(int value); //} public: // private: CbcSpecificThread * basePointer_; // for getting main mutex and threadid of base #ifdef CBC_PTHREAD pthread_mutex_t *masterMutex_; // for synchronizing pthread_mutex_t mutex2_; // for waking up threads pthread_cond_t condition2_; // for waking up thread Coin_pthread_t threadId_; #endif bool locked_; // For mutex2 }; /** A class to encapsulate thread stuff */ class CbcThread { private: void gutsOfDelete(); void gutsOfCopy(const CbcThread & rhs); public: // Default Constructor CbcThread (); virtual ~CbcThread(); /// Fills in useful stuff void setUsefulStuff (CbcModel * model, int deterministic, CbcModel * baseModel, CbcThread * master, void *& masterMutex); /** Locks a thread if parallel so that stuff like cut pool can be updated and/or used. */ void lockThread(); /** Unlocks a thread if parallel to say cut pool stuff not needed */ void unlockThread(); /// Returns true if locked inline bool isLocked() const { return locked_; } /** Wait for child to have return code NOT == to currentCode type - 0 timed wait 1 wait returns true if return code changed */ bool wait(int type, int currentCode); /// Just wait for so many nanoseconds void waitNano(int time); /// Signal child to carry on void signal(); /// Lock from master with mutex2 and signal before lock void lockFromMaster(); /// Unlock from master with mutex2 and signal after unlock void unlockFromMaster(); /// Lock from thread with mutex2 and signal before lock void lockFromThread(); /// Unlock from thread with mutex2 and signal after unlock void unlockFromThread(); /// Exits thread (called from master) - return code should be zero int exit(); /// Exits thread void exitThread(); /// Waits until returnCode_ goes to zero void waitThread(); /// Get status inline int status() const { return threadStuff_.status(); } /// Set status inline void setStatus(int value) { threadStuff_.setStatus( value); } /// Get return code inline int returnCode() const { return returnCode_; } /// Set return code inline void setReturnCode(int value) { returnCode_ = value; } /// Get base model inline CbcModel * baseModel() const { return baseModel_; } /// Get this model inline CbcModel * thisModel() const { return thisModel_; } /// Get node inline CbcNode * node() const { return node_; } /// Set node inline void setNode(CbcNode * node) { node_ = node; } /// Get created node inline CbcNode * createdNode() const { return createdNode_; } /// Set created node inline void setCreatedNode(CbcNode * node) { createdNode_ = node; } /// Get dantzig state inline int dantzigState() const { return dantzigState_; } /// Set dantzig state inline void setDantzigState(int value) { dantzigState_ = value; } /// Get time in thread inline double timeInThread() const { return timeInThread_; } /// Increment time in thread inline void incrementTimeInThread(double value) { timeInThread_ += value; } /// Get time waiting to start inline double timeWaitingToStart() const { return timeWaitingToStart_; } /// Increment time waiting to start inline void incrementTimeWaitingToStart(double value) { timeWaitingToStart_ += value; } /// Get time locked inline double timeLocked() const { return timeLocked_; } /// Increment time locked inline void incrementTimeLocked(double value) { timeLocked_ += value; } /// Get time waiting to lock inline double timeWaitingToLock() const { return timeWaitingToLock_; } /// Increment time waiting to lock inline void incrementTimeWaitingToLock(double value) { timeWaitingToLock_ += value; } /// Get if deterministic inline int deterministic() const { return deterministic_; } /// Get maxDeleteNode inline int maxDeleteNode() const { return maxDeleteNode_; } /// Set maxDeleteNode inline void setMaxDeleteNode(int value) { maxDeleteNode_ = value; } /// Get nDeleteNode (may be fake i.e. defaultParallelIterations_) inline int nDeleteNode() const { return nDeleteNode_; } /// Set nDeleteNode (may be fake i.e. defaultParallelIterations_) inline void setNDeleteNode(int value) { nDeleteNode_ = value; } /// Clear delNode inline void clearDelNode() { delete delNode_; delNode_ = NULL; } /// Set fake delNode to pass across OsiCuts inline void fakeDelNode(CbcNode ** delNode) { delNode_ = delNode; } /// Get delNode inline CbcNode ** delNode() const { return delNode_; } /// Set delNode inline void setDelNode(CbcNode ** delNode) { delNode_ = delNode; } /// Get number times locked inline int numberTimesLocked() const { return numberTimesLocked_; } /// Get number times unlocked inline int numberTimesUnlocked() const { return numberTimesUnlocked_; } /// Get number of nodes this time inline int nodesThisTime() const { return nodesThisTime_; } /// Set number of nodes this time inline void setNodesThisTime(int value) { nodesThisTime_ = value; } /// Get number of iterations this time inline int iterationsThisTime() const { return iterationsThisTime_; } /// Set number of iterations this time inline void setIterationsThisTime(int value) { iterationsThisTime_ = value; } /// Get save stuff array inline int * saveStuff() { return saveStuff_; } /// Say if locked inline bool locked() const { return locked_; } public: // private: CbcSpecificThread threadStuff_; CbcModel * baseModel_; CbcModel * thisModel_; CbcNode * node_; // filled in every time CbcNode * createdNode_; // filled in every time on return CbcThread * master_; // points back to master thread int returnCode_; // -1 available, 0 busy, 1 finished , 2?? double timeLocked_; double timeWaitingToLock_; double timeWaitingToStart_; double timeInThread_; double timeWhenLocked_; // time when thread got lock (in seconds) int numberTimesLocked_; int numberTimesUnlocked_; int numberTimesWaitingToStart_; int saveStuff_[2]; int dantzigState_; // 0 unset, -1 waiting to be set, 1 set bool locked_; int nDeleteNode_; CbcNode ** delNode_; int maxDeleteNode_; int nodesThisTime_; int iterationsThisTime_; int deterministic_; #ifdef THREAD_DEBUG public: int threadNumber_; int lockCount_; #endif }; /** Base model */ class CbcBaseModel { public: // Default Constructor CbcBaseModel (); /** Constructor with model type -1 cuts 0 opportunistic 1 deterministic */ /** Constructor with model type -1 cuts 0 opportunistic 1 deterministic */ CbcBaseModel (CbcModel & model, int type); virtual ~CbcBaseModel(); /** Stop all threads -1 just check all in good state 0 actually stop */ void stopThreads(int type); /** Wait for threads in tree type 0 - tree looks empty - see if any nodes outstanding 1 - tree not empty 2 - finish and do statistics returns non-zero if keep going */ int waitForThreadsInTree(int type); /** Wait for threads n parallel cuts type 0 - parallel cuts 1 - finishing parallel cuts */ void waitForThreadsInCuts(int type, OsiCuts * eachCuts, int whichGenerator); /// Split model and do work in deterministic parallel void deterministicParallel(); /** Locks a thread if parallel so that stuff like cut pool can be updated and/or used. */ inline void lockThread() { children_[numberThreads_].lockThread(); } /** Unlocks a thread if parallel to say cut pool stuff not needed */ inline void unlockThread() { children_[numberThreads_].unlockThread(); } /// Returns true if locked inline bool isLocked() const { return children_[numberThreads_].locked(); } /// Returns pointer to master thread CbcThread * masterThread() const; /// Returns pointer to a thread model inline CbcModel * model(int i) const { return threadModel_[i]; } /// Returns pointer to a child thread inline CbcThread * child(int thread) const { return children_+thread;} /// Returns number of children inline int numberThreads() const { return numberThreads_;} /// Sets Dantzig state in children void setDantzigState(); private: /// Number of children int numberThreads_; /// Child models (with base model at end) CbcThread * children_; /** type -1 cuts 0 opportunistic 1 deterministic */ int type_; int * threadCount_; CbcModel ** threadModel_; int numberObjects_; OsiObject ** saveObjects_; int threadStats_[6]; int defaultParallelIterations_; int defaultParallelNodes_; }; #else // Dummy threads /** A class to encapsulate thread stuff */ class CbcThread { public: // Default Constructor CbcThread () {} virtual ~CbcThread() {} }; /** Base model */ class CbcBaseModel { public: // Default Constructor (not declared here so that CbcThread.cpp not empty) CbcBaseModel (); virtual ~CbcBaseModel() {} }; #endif #endif Cbc-2.8.12/src/CbcDummyBranchingObject.hpp0000644000076600007660000000531612131315050016713 0ustar coincoin// $Id: CbcDummyBranchingObject.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #ifndef CbcDummyBranchingObject_H #define CbcDummyBranchingObject_H #include "CbcBranchBase.hpp" /** Dummy branching object This object specifies a one-way dummy branch. This is so one can carry on branching even when it looks feasible */ class CbcDummyBranchingObject : public CbcBranchingObject { public: /// Default constructor CbcDummyBranchingObject (CbcModel * model = NULL); /// Copy constructor CbcDummyBranchingObject ( const CbcDummyBranchingObject &); /// Assignment operator CbcDummyBranchingObject & operator= (const CbcDummyBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; /// Destructor virtual ~CbcDummyBranchingObject (); using CbcBranchingObject::branch ; /** \brief Dummy branch */ virtual double branch(); #ifdef JJF_ZERO // No need to override. Default works fine. /** Reset every information so that the branching object appears to point to the previous child. This method does not need to modify anything in any solver. */ virtual void previousBranch(); #endif using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return DummyBranchObj; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const; /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); }; #endif Cbc-2.8.12/src/CbcGenCbcParamUtils.cpp0000644000076600007660000003526412131315050016000 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenCbcParamUtils.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include "CoinFinite.hpp" #include "CoinParam.hpp" #include "CbcModel.hpp" #include "CbcGenCtlBlk.hpp" #include "CbcGenParam.hpp" #include "CbcGenCbcParam.hpp" /*! \file CbcGenParamUtils \brief Implementation functions for CbcGenParam parameters. */ namespace { char svnid[] = "$Id: CbcGenCbcParamUtils.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } namespace CbcCbcParamUtils { /* Function to set up cbc (CbcModel) parameters. */ void addCbcCbcParams (int &numberParameters, CoinParamVec ¶meters, CbcModel *model) { CbcCbcParam *param ; param = new CbcCbcParam(CbcCbcParam::ALLOWABLEGAP, "allow!ableGap", "Stop when gap between best possible and incumbent is less than this", 0.0, 1.0e20) ; param->setDblVal(0.0) ; param->setPushFunc(pushCbcCbcDbl) ; param->setObj(model) ; param->setLongHelp( "If the gap between best solution and best possible solution is less than this then the search will be terminated. Also see ratioGap." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::CUTOFF, "cuto!ff", "All solutions must be better than this", -1.0e60, 1.0e60) ; param->setDblVal(1.0e50) ; param->setPushFunc(pushCbcCbcDbl) ; param->setObj(model) ; param->setLongHelp( "All solutions must be better than this value (in a minimization sense). This is also set by cbc whenever it obtains a solution and is set to the value of the objective for the solution minus the cutoff increment." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::DIRECTION, "direction", "Minimize or maximize", "min!imize", 0) ; param->appendKwd("max!imize") ; param->appendKwd("zero") ; param->setObj(model) ; param->setLongHelp( "The default is minimize - use 'direction maximize' for maximization.\nYou can also use the parameters 'maximize' or 'minimize'." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::INCREMENT, "inc!rement", "A new solution must be at least this much better than the incumbent", -1.0e20, 1.0e20, model->getDblParam(CbcModel::CbcCutoffIncrement)) ; param->setPushFunc(pushCbcCbcDbl) ; param->setObj(model) ; param->setLongHelp( "Whenever a solution is found the bound on future solutions is set to the objective of the solution (in a minimization sense) plus the specified increment. If this option is not specified, the code will try and work out an increment. E.g., if all objective coefficients are multiples of 0.01 and only integer variables have entries in objective then the increment can be set to 0.01. Be careful if you set this negative!" ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::INFEASIBILITYWEIGHT, "inf!easibilityWeight", "Each integer infeasibility is expected to cost this much", 0.0, 1.0e20, model->getDblParam(CbcModel::CbcInfeasibilityWeight)) ; param->setPushFunc(pushCbcCbcDbl) ; param->setObj(model) ; param->setLongHelp( "A primitive way of deciding which node to explore next. Satisfying each integer infeasibility is expected to cost this much." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::INTEGERTOLERANCE, "integerT!olerance", "For an optimal solution, no integer variable may be farther than this from an integer value", 1.0e-20, 0.5, model->getDblParam(CbcModel::CbcIntegerTolerance)) ; param->setPushFunc(pushCbcCbcDbl) ; param->setObj(model) ; param->setLongHelp( "When checking a solution for feasibility, if the difference between the value of a variable and the nearest integer is less than the integer tolerance, the value is considered to be integral. Beware of setting this smaller than the primal tolerance." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::LOGLEVEL, "bclog!Level", "Level of detail in Coin branch and Cut output", -1, 63, model->messageHandler()->logLevel()) ; param->setPushFunc(pushCbcCbcInt) ; param->setObj(model) ; param->setLongHelp( "If set to 0 then there should be no output in normal circumstances. A value of 1 is probably the best value for most uses, while 2 and 3 give more information." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::MAXIMIZE, "max!imize", "Set optimization direction to maximize") ; param->setObj(model) ; param->setLongHelp( "The default is minimize - use 'maximize' for maximization.\n A synonym for 'direction maximize'." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::MAXNODES, "maxN!odes", "Maximum number of nodes to evaluate", 1, 2147483647) ; param->setObj(model) ; param->setLongHelp( "This is a repeatable way to limit search. Normally using time is easier but then the results may not be repeatable." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::MINIMIZE, "min!imize", "Set optimization direction to minimize") ; param->setObj(model) ; param->setLongHelp( "The default is minimize - use 'maximize' for maximization.\nThis should only be necessary if you have previously set maximization. A synonym for 'direction minimize'." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::MIPOPTIONS, "mipO!ptions", "Dubious options for mip", 0, COIN_INT_MAX, 0, false) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::MOREMIPOPTIONS, "more!MipOptions", "More dubious options for mip", -1, COIN_INT_MAX, 0, false) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::NUMBERMINI, "miniT!ree", "Size of fast mini tree", 0, COIN_INT_MAX, 0, false) ; param->setObj(model) ; param->setLongHelp( "The idea is that I can do a small tree fast. This is a first try and will hopefully become more sophisticated." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::NUMBERANALYZE, "numberA!nalyze", "Number of analysis iterations", -COIN_INT_MAX, COIN_INT_MAX, false) ; param->setObj(model) ; param->setLongHelp( "This says how many iterations to spend at the root node analyzing the problem. This is a first try and will hopefully become more sophisticated." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::CUTPASS, "passC!uts", "Number of cut passes at root node", -999999, 999999, model->getMaximumCutPassesAtRoot()) ; param->setObj(model) ; param->setLongHelp( "The default is 100 passes if less than 500 columns, 100 passes (but stop if the drop is small) if less than 5000 columns, 20 otherwise." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::GAPRATIO, "ratio!Gap", "Stop when the gap between the best possible solution and the incumbent is less than this fraction of the larger of the two", 0.0, 1.0e20, model->getDblParam(CbcModel::CbcAllowableFractionGap)) ; param->setPushFunc(pushCbcCbcDbl) ; param->setObj(model) ; param->setLongHelp( "If the gap between the best solution and the best possible solution is less than this fraction of the objective value at the root node then the search will terminate. See 'allowableGap' for a way of using absolute value rather than fraction." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::TIMELIMIT_BAB, "sec!onds", "Maximum seconds for branch and cut", -1.0, 1.0e12) ; param->setPushFunc(pushCbcCbcDbl) ; param->setObj(model) ; param->setLongHelp( "After this many seconds the program will act as if maximum nodes had been reached." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::STRONGBRANCHING, "strong!Branching", "Number of variables to look at in strong branching", 0, 999999, model->numberStrong()) ; param->setObj(model) ; param->setLongHelp( "In order to decide which variable to branch on, the code will choose up to this number of unsatisfied variables and try mini up and down branches. The most effective one is chosen. If a variable is branched on many times then the previous average up and down costs may be used - see number before trust." ) ; parameters.push_back(param) ; param = new CbcCbcParam(CbcCbcParam::NUMBERBEFORE, "trust!PseudoCosts", "Number of branches before we trust pseudocosts", -1, 2000000, model->numberBeforeTrust()) ; param->setObj(model) ; param->setPushFunc(pushCbcCbcInt) ; param->setLongHelp( "Using strong branching computes pseudo-costs. After this many times for a variable we just trust the pseudo costs and do not do any more strong branching." ) ; parameters.push_back(param) ; numberParameters = parameters.size() ; assert (numberParameters <= parameters.capacity()) ; } void loadCbcParamObj (const CoinParamVec paramVec, int first, int last, CbcModel *obj) { int i ; /* Load the CbcModel object into the parameters */ for (i = first ; i <= last ; i++) { CbcCbcParam *cbcParam = dynamic_cast(paramVec[i]) ; assert (cbcParam != 0) ; cbcParam->setObj(obj) ; } return ; } /* Set CbcModel defaults appropriate for cbc-generic. */ void setCbcModelDefaults (CbcModel *model) { model->setIntParam(CbcModel::CbcMaxNumNode, (COIN_INT_MAX / 2)) ; model->setIntParam(CbcModel::CbcMaxNumSol, 999999) ; model->setIntParam(CbcModel::CbcFathomDiscipline, 0) ; model->setDblParam(CbcModel::CbcIntegerTolerance, 1.0e-6) ; model->setDblParam(CbcModel::CbcInfeasibilityWeight, 0.0) ; model->setDblParam(CbcModel::CbcCutoffIncrement, 1.0e-5) ; model->setDblParam(CbcModel::CbcAllowableGap, 1.0e-10) ; model->setDblParam(CbcModel::CbcAllowableFractionGap, 0.0) ; // One year is 60x60x24x365 = 31,536,000 seconds. model->setDblParam(CbcModel::CbcMaximumSeconds, 3.0e7) ; model->setDblParam(CbcModel::CbcCurrentCutoff, 1.0e100) ; model->setDblParam(CbcModel::CbcOptimizationDirection, 1.0) ; model->setDblParam(CbcModel::CbcCurrentObjectiveValue, 1.0e100) ; model->setDblParam(CbcModel::CbcCurrentMinimizationObjectiveValue, 1.0e100) ; model->setDblParam(CbcModel::CbcStartSeconds, 0.0) ; model->setNumberBeforeTrust(5) ; model->setNumberStrong(5) ; return ; } /* Function to push a double parameter. */ int pushCbcCbcDbl (CoinParam *param) { assert (param != 0) ; CbcCbcParam *cbcParam = dynamic_cast(param) ; assert (cbcParam != 0) ; CbcModel *model = cbcParam->obj() ; double val = cbcParam->dblVal() ; CbcCbcParam::CbcCbcParamCode code = cbcParam->paramCode() ; assert (model != 0) ; int retval = 0 ; /* Translate the parameter code from CbcCbcParamCode into the correct key for CbcDblParam. */ CbcModel::CbcDblParam key ; switch (code) { case CbcCbcParam::INTEGERTOLERANCE: { key = CbcModel::CbcIntegerTolerance ; break ; } case CbcCbcParam::INFEASIBILITYWEIGHT: { key = CbcModel::CbcInfeasibilityWeight ; break ; } case CbcCbcParam::INCREMENT: { key = CbcModel::CbcCutoffIncrement ; break ; } case CbcCbcParam::ALLOWABLEGAP: { key = CbcModel::CbcAllowableGap ; break ; } case CbcCbcParam::GAPRATIO: { key = CbcModel::CbcAllowableFractionGap ; break ; } case CbcCbcParam::TIMELIMIT_BAB: { key = CbcModel::CbcMaximumSeconds ; break ; } case CbcCbcParam::CUTOFF: { key = CbcModel::CbcCurrentCutoff ; break ; } default: { std::cerr << "pushCbcCbcDbl: no equivalent CbcDblParam for " << "parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } bool result = model->setDblParam(key, val) ; if (result == false) { retval = -1 ; } return (retval) ; } /* Function to push an integer parameter. */ int pushCbcCbcInt (CoinParam *param) { assert (param != 0) ; CbcCbcParam *cbcParam = dynamic_cast(param) ; assert (cbcParam != 0) ; CbcModel *model = cbcParam->obj() ; int val = cbcParam->intVal() ; CbcCbcParam::CbcCbcParamCode code = cbcParam->paramCode() ; assert (model != 0) ; int retval = 0 ; /* Translate the parameter code from CbcCbcParamCode into the correct key for CbcIntParam, or call the appropriate method directly. */ CbcModel::CbcIntParam key = CbcModel::CbcLastIntParam ; switch (code) { case CbcCbcParam::CUTPASS: { model->setMaximumCutPassesAtRoot(val) ; break ; } case CbcCbcParam::LOGLEVEL: { CoinMessageHandler *hndl = model->messageHandler() ; assert (hndl != 0) ; hndl->setLogLevel(val) ; break ; } case CbcCbcParam::NUMBERBEFORE: { model->setNumberBeforeTrust(val) ; break ; } default: { std::cerr << "pushCbcCbcInt: no equivalent CbcIntParam for " << "parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } if (key != CbcModel::CbcLastIntParam) { bool result = model->setIntParam(key, val) ; if (result == false) { retval = -1 ; } } return (retval) ; } } // end namespace CbcCbcParamUtils Cbc-2.8.12/src/CbcSubProblem.cpp0000644000076600007660000002454312131315050014725 0ustar coincoin// $Id: CbcSubProblem.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #include #include #include #include //#define CBC_DEBUG #include "CoinPragma.hpp" #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcSubProblem.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #endif // Default Constructor CbcSubProblem::CbcSubProblem() : objectiveValue_(0.0), sumInfeasibilities_(0.0), branchValue_(0.0), djValue_(0.0), variables_(NULL), newBounds_(NULL), status_(NULL), depth_(0), numberChangedBounds_(0), numberInfeasibilities_(0), problemStatus_(0), branchVariable_(0) { } // Useful constructor CbcSubProblem::CbcSubProblem (const OsiSolverInterface * solver, const double * lastLower, const double * lastUpper, const unsigned char * status, int depth) : objectiveValue_(0.0), sumInfeasibilities_(0.0), branchValue_(0.0), djValue_(0.0), variables_(NULL), newBounds_(NULL), status_(NULL), depth_(depth), numberChangedBounds_(0), numberInfeasibilities_(0), problemStatus_(0), branchVariable_(0) { const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); numberChangedBounds_ = 0; int numberColumns = solver->getNumCols(); int i; for (i = 0; i < numberColumns; i++) { if (lower[i] != lastLower[i]) numberChangedBounds_++; if (upper[i] != lastUpper[i]) numberChangedBounds_++; } if (numberChangedBounds_) { newBounds_ = new double [numberChangedBounds_] ; variables_ = new int [numberChangedBounds_] ; numberChangedBounds_ = 0; for (i = 0; i < numberColumns; i++) { if (lower[i] != lastLower[i]) { variables_[numberChangedBounds_] = i; newBounds_[numberChangedBounds_++] = lower[i]; } if (upper[i] != lastUpper[i]) { variables_[numberChangedBounds_] = i | 0x80000000; newBounds_[numberChangedBounds_++] = upper[i]; } #ifdef CBC_DEBUG if (lower[i] != lastLower[i]) { std::cout << "lower on " << i << " changed from " << lastLower[i] << " to " << lower[i] << std::endl ; } if (upper[i] != lastUpper[i]) { std::cout << "upper on " << i << " changed from " << lastUpper[i] << " to " << upper[i] << std::endl ; } #endif } #ifdef CBC_DEBUG std::cout << numberChangedBounds_ << " changed bounds." << std::endl ; #endif } const OsiClpSolverInterface * clpSolver = dynamic_cast (solver); assert (clpSolver); // Do difference // Current basis status_ = clpSolver->getBasis(status); assert (status_->fullBasis()); //status_->print(); } // Copy constructor CbcSubProblem::CbcSubProblem ( const CbcSubProblem & rhs) : objectiveValue_(rhs.objectiveValue_), sumInfeasibilities_(rhs.sumInfeasibilities_), branchValue_(rhs.branchValue_), djValue_(rhs.djValue_), variables_(NULL), newBounds_(NULL), status_(NULL), depth_(rhs.depth_), numberChangedBounds_(rhs.numberChangedBounds_), numberInfeasibilities_(rhs.numberInfeasibilities_), problemStatus_(rhs.problemStatus_), branchVariable_(rhs.branchVariable_) { if (numberChangedBounds_) { variables_ = CoinCopyOfArray(rhs.variables_, numberChangedBounds_); newBounds_ = CoinCopyOfArray(rhs.newBounds_, numberChangedBounds_); } if (rhs.status_) { status_ = new CoinWarmStartBasis(*rhs.status_); } } // Assignment operator CbcSubProblem & CbcSubProblem::operator=( const CbcSubProblem & rhs) { if (this != &rhs) { delete [] variables_; delete [] newBounds_; delete status_; objectiveValue_ = rhs.objectiveValue_; sumInfeasibilities_ = rhs.sumInfeasibilities_; branchValue_ = rhs.branchValue_; djValue_ = rhs.djValue_; depth_ = rhs.depth_; numberChangedBounds_ = rhs.numberChangedBounds_; numberInfeasibilities_ = rhs.numberInfeasibilities_; problemStatus_ = rhs.problemStatus_; branchVariable_ = rhs.branchVariable_; if (numberChangedBounds_) { variables_ = CoinCopyOfArray(rhs.variables_, numberChangedBounds_); newBounds_ = CoinCopyOfArray(rhs.newBounds_, numberChangedBounds_); } else { variables_ = NULL; newBounds_ = NULL; } if (rhs.status_) { status_ = new CoinWarmStartBasis(*rhs.status_); } else { status_ = NULL; } } return *this; } // Take over void CbcSubProblem::takeOver( CbcSubProblem & rhs, bool cleanUp) { if (this != &rhs) { delete [] variables_; delete [] newBounds_; delete status_; objectiveValue_ = rhs.objectiveValue_; sumInfeasibilities_ = rhs.sumInfeasibilities_; branchValue_ = rhs.branchValue_; djValue_ = rhs.djValue_; depth_ = rhs.depth_; numberChangedBounds_ = rhs.numberChangedBounds_; numberInfeasibilities_ = rhs.numberInfeasibilities_; problemStatus_ = rhs.problemStatus_; branchVariable_ = rhs.branchVariable_; variables_ = rhs.variables_; newBounds_ = rhs.newBounds_; rhs.variables_ = NULL; rhs.newBounds_ = NULL; status_ = rhs.status_; rhs.status_ = NULL; if (cleanUp) { delete [] variables_; delete [] newBounds_; variables_ = new int [1]; newBounds_ = new double [1]; // swap way and make only fix numberChangedBounds_=1; if ((problemStatus_&1)==0) { // last way was down newBounds_[0] = ceil(branchValue_); variables_[0] = branchVariable_; } else { // last way was up newBounds_[0] = floor(branchValue_); variables_[0] = branchVariable_ | 0x80000000; } } } } // Destructor CbcSubProblem::~CbcSubProblem () { delete [] variables_; delete [] newBounds_; delete status_; } // Apply subproblem void CbcSubProblem::apply(OsiSolverInterface * solver, int what) const { int i; if ((what&1) != 0) { printf("CbcSubapply depth %d column %d way %d bvalue %g obj %g\n", this->depth_,this->branchVariable_,this->problemStatus_, this->branchValue_,this->objectiveValue_); printf("current bounds %g <= %g <= %g\n",solver->getColLower()[branchVariable_],branchValue_,solver->getColUpper()[branchVariable_]); #ifndef NDEBUG int nSame = 0; #endif for (i = 0; i < numberChangedBounds_; i++) { int variable = variables_[i]; int k = variable & 0x3fffffff; if ((variable&0x80000000) == 0) { // lower bound changing //#define CBC_PRINT2 #ifdef CBC_PRINT2 if (solver->getColLower()[k] != newBounds_[i]) printf("lower change for column %d - from %g to %g\n", k, solver->getColLower()[k], newBounds_[i]); #endif #ifndef NDEBUG if ((variable&0x40000000) == 0 && true) { double oldValue = solver->getColLower()[k]; assert (newBounds_[i] > oldValue - 1.0e-8); if (newBounds_[i] < oldValue + 1.0e-8) { #ifdef CBC_PRINT2 printf("bad null lower change for column %d - bound %g\n", k, oldValue); #endif if (newBounds_[i] == oldValue) nSame++; } } #endif solver->setColLower(k, newBounds_[i]); } else { // upper bound changing #ifdef CBC_PRINT2 if (solver->getColUpper()[k] != newBounds_[i]) printf("upper change for column %d - from %g to %g\n", k, solver->getColUpper()[k], newBounds_[i]); #endif #ifndef NDEBUG if ((variable&0x40000000) == 0 && true) { double oldValue = solver->getColUpper()[k]; assert (newBounds_[i] < oldValue + 1.0e-8); if (newBounds_[i] > oldValue - 1.0e-8) { #ifdef CBC_PRINT2 printf("bad null upper change for column %d - bound %g\n", k, oldValue); #endif if (newBounds_[i] == oldValue) nSame++; } } #endif solver->setColUpper(k, newBounds_[i]); } } #ifndef NDEBUG #ifdef CBC_PRINT2 if (nSame && (nSame < numberChangedBounds_ || (what&3) != 3)) printf("%d changes out of %d redundant %d\n", nSame, numberChangedBounds_, what); else if (numberChangedBounds_ && what == 7 && !nSame) printf("%d good changes %d\n", numberChangedBounds_, what); #endif #endif printf("new bounds %g <= %g <= %g\n",solver->getColLower()[branchVariable_],branchValue_,solver->getColUpper()[branchVariable_]); } #ifdef JJF_ZERO if ((what&2) != 0) { OsiClpSolverInterface * clpSolver = dynamic_cast (solver); assert (clpSolver); //assert (clpSolver->getNumRows()==numberRows_); //clpSolver->setBasis(*status_); // Current basis CoinWarmStartBasis * basis = clpSolver->getPointerToWarmStart(); printf("BBBB\n"); basis->print(); assert (basis->fullBasis()); basis->applyDiff(status_); printf("diff applied %x\n", status_); printf("CCCC\n"); basis->print(); assert (basis->fullBasis()); #ifndef NDEBUG if (!basis->fullBasis()) printf("Debug this basis!!\n"); #endif clpSolver->setBasis(*basis); } #endif if ((what&8) != 0) { OsiClpSolverInterface * clpSolver = dynamic_cast (solver); assert (clpSolver); clpSolver->setBasis(*status_); if ((what&16)==0) { delete status_; status_ = NULL; } } } Cbc-2.8.12/src/CbcSolverHeuristics.cpp0000644000076600007660000023015512131315050016166 0ustar coincoin/* $Id: CbcSolverHeuristics.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /*! \file CbcSolverHeuristics.cpp \brief Second level routines for the cbc stand-alone solver. */ #include "CbcConfig.h" #include "CoinPragma.hpp" #include "CoinTime.hpp" #include "OsiClpSolverInterface.hpp" #include "ClpPresolve.hpp" #include "CbcOrClpParam.hpp" #include "CbcModel.hpp" #include "CbcHeuristicLocal.hpp" #include "CbcHeuristicPivotAndFix.hpp" //#include "CbcHeuristicPivotAndComplement.hpp" #include "CbcHeuristicRandRound.hpp" #include "CbcHeuristicGreedy.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcHeuristicRINS.hpp" #include "CbcHeuristicDiveCoefficient.hpp" #include "CbcHeuristicDiveFractional.hpp" #include "CbcHeuristicDiveGuided.hpp" #include "CbcHeuristicDiveVectorLength.hpp" #include "CbcHeuristicDivePseudoCost.hpp" #include "CbcHeuristicDiveLineSearch.hpp" #include "CbcStrategy.hpp" #include "OsiAuxInfo.hpp" #include "ClpSimplexOther.hpp" // Crunch down model void crunchIt(ClpSimplex * model) { #ifdef JJF_ZERO model->dual(); #else int numberColumns = model->numberColumns(); int numberRows = model->numberRows(); // Use dual region double * rhs = model->dualRowSolution(); int * whichRow = new int[3*numberRows]; int * whichColumn = new int[2*numberColumns]; int nBound; ClpSimplex * small = static_cast (model)->crunch(rhs, whichRow, whichColumn, nBound, false, false); if (small) { small->dual(); if (small->problemStatus() == 0) { model->setProblemStatus(0); static_cast (model)->afterCrunch(*small, whichRow, whichColumn, nBound); } else if (small->problemStatus() != 3) { model->setProblemStatus(1); } else { if (small->problemStatus() == 3) { // may be problems small->computeObjectiveValue(); model->setObjectiveValue(small->objectiveValue()); model->setProblemStatus(3); } else { model->setProblemStatus(3); } } delete small; } else { model->setProblemStatus(1); } delete [] whichRow; delete [] whichColumn; #endif } /* On input doAction - 0 just fix in original and return NULL 1 return fixed non-presolved solver 2 as one but use presolve Inside this 3 use presolve and fix ones with large cost ? do heuristics and set best solution ? do BAB and just set best solution 10+ then use lastSolution and relax a few -2 cleanup afterwards if using 2 On output - number fixed */ OsiClpSolverInterface * fixVubs(CbcModel & model, int skipZero2, int & doAction, CoinMessageHandler * /*generalMessageHandler*/, const double * lastSolution, double dextra[6], int extra[5]) { if (doAction == 11 && !lastSolution) lastSolution = model.bestSolution(); assert (((doAction >= 0 && doAction <= 3) && !lastSolution) || (doAction == 11 && lastSolution)); double fractionIntFixed = dextra[3]; double fractionFixed = dextra[4]; double fixAbove = dextra[2]; double fixAboveValue = (dextra[5] > 0.0) ? dextra[5] : 1.0; #ifdef COIN_DETAIL double time1 = CoinCpuTime(); #endif int leaveIntFree = extra[1]; OsiSolverInterface * originalSolver = model.solver(); OsiClpSolverInterface * originalClpSolver = dynamic_cast< OsiClpSolverInterface*> (originalSolver); ClpSimplex * originalLpSolver = originalClpSolver->getModelPtr(); int * originalColumns = NULL; OsiClpSolverInterface * clpSolver; ClpSimplex * lpSolver; ClpPresolve pinfo; assert(originalSolver->getObjSense() > 0); if (doAction == 2 || doAction == 3) { double * saveLB = NULL; double * saveUB = NULL; int numberColumns = originalLpSolver->numberColumns(); if (fixAbove > 0.0) { #ifdef COIN_DETAIL double time1 = CoinCpuTime(); #endif originalClpSolver->initialSolve(); COIN_DETAIL_PRINT(printf("first solve took %g seconds\n", CoinCpuTime() - time1)); double * columnLower = originalLpSolver->columnLower() ; double * columnUpper = originalLpSolver->columnUpper() ; const double * solution = originalLpSolver->primalColumnSolution(); saveLB = CoinCopyOfArray(columnLower, numberColumns); saveUB = CoinCopyOfArray(columnUpper, numberColumns); const double * objective = originalLpSolver->getObjCoefficients() ; int iColumn; int nFix = 0; int nArt = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (objective[iColumn] > fixAbove) { if (solution[iColumn] < columnLower[iColumn] + 1.0e-8) { columnUpper[iColumn] = columnLower[iColumn]; nFix++; } else { nArt++; } } else if (objective[iColumn] < -fixAbove) { if (solution[iColumn] > columnUpper[iColumn] - 1.0e-8) { columnLower[iColumn] = columnUpper[iColumn]; nFix++; } else { nArt++; } } } COIN_DETAIL_PRINT(printf("%d artificials fixed, %d left as in solution\n", nFix, nArt)); lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10); if (!lpSolver || doAction == 2) { // take off fixing in original memcpy(columnLower, saveLB, numberColumns*sizeof(double)); memcpy(columnUpper, saveUB, numberColumns*sizeof(double)); } delete [] saveLB; delete [] saveUB; if (!lpSolver) { // try again pinfo.destroyPresolve(); lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10); assert (lpSolver); } } else { lpSolver = pinfo.presolvedModel(*originalLpSolver, 1.0e-8, true, 10); assert (lpSolver); } clpSolver = new OsiClpSolverInterface(lpSolver, true); assert(lpSolver == clpSolver->getModelPtr()); numberColumns = lpSolver->numberColumns(); originalColumns = CoinCopyOfArray(pinfo.originalColumns(), numberColumns); doAction = 1; } else { OsiSolverInterface * solver = originalSolver->clone(); clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver); lpSolver = clpSolver->getModelPtr(); } // Tighten bounds lpSolver->tightenPrimalBounds(0.0, 11, true); int numberColumns = clpSolver->getNumCols() ; double * saveColumnLower = CoinCopyOfArray(lpSolver->columnLower(), numberColumns); double * saveColumnUpper = CoinCopyOfArray(lpSolver->columnUpper(), numberColumns); //char generalPrint[200]; const double *objective = lpSolver->getObjCoefficients() ; double *columnLower = lpSolver->columnLower() ; double *columnUpper = lpSolver->columnUpper() ; int numberRows = clpSolver->getNumRows(); int iRow, iColumn; // Row copy CoinPackedMatrix matrixByRow(*clpSolver->getMatrixByRow()); const double * elementByRow = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); // Column copy CoinPackedMatrix matrixByCol(*clpSolver->getMatrixByCol()); //const double * element = matrixByCol.getElements(); const int * row = matrixByCol.getIndices(); const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); const int * columnLength = matrixByCol.getVectorLengths(); const double * rowLower = clpSolver->getRowLower(); const double * rowUpper = clpSolver->getRowUpper(); // Get maximum size of VUB tree // otherColumn is one fixed to 0 if this one zero int nEl = matrixByCol.getNumElements(); CoinBigIndex * fixColumn = new CoinBigIndex [numberColumns+1]; int * otherColumn = new int [nEl]; int * fix = new int[numberColumns]; char * mark = new char [numberColumns]; memset(mark, 0, numberColumns); int numberInteger = 0; int numberOther = 0; fixColumn[0] = 0; double large = lpSolver->largeValue(); // treat bounds > this as infinite #ifndef NDEBUG double large2 = 1.0e10 * large; #endif double tolerance = lpSolver->primalTolerance(); int * check = new int[numberRows]; for (iRow = 0; iRow < numberRows; iRow++) { check[iRow] = -2; // don't check if (rowLower[iRow] < -1.0e6 && rowUpper[iRow] > 1.0e6) continue;// unlikely // possible row int numberPositive = 0; int iPositive = -1; int numberNegative = 0; int iNegative = -1; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; CoinBigIndex j; int kColumn; for (j = rStart; j < rEnd; ++j) { double value = elementByRow[j]; kColumn = column[j]; if (columnUpper[kColumn] > columnLower[kColumn]) { if (value > 0.0) { numberPositive++; iPositive = kColumn; } else { numberNegative++; iNegative = kColumn; } } } if (numberPositive == 1 && numberNegative == 1) check[iRow] = -1; // try both if (numberPositive == 1 && rowLower[iRow] > -1.0e20) check[iRow] = iPositive; else if (numberNegative == 1 && rowUpper[iRow] < 1.0e20) check[iRow] = iNegative; } for (iColumn = 0; iColumn < numberColumns; iColumn++) { fix[iColumn] = -1; if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) { if (clpSolver->isInteger(iColumn)) numberInteger++; if (columnLower[iColumn] == 0.0) { bool infeasible = false; fix[iColumn] = 0; // fake upper bound double saveUpper = columnUpper[iColumn]; columnUpper[iColumn] = 0.0; for (CoinBigIndex i = columnStart[iColumn]; i < columnStart[iColumn] + columnLength[iColumn]; i++) { iRow = row[i]; if (check[iRow] != -1 && check[iRow] != iColumn) continue; // unlikely // possible row int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; double newBound; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; CoinBigIndex j; int kColumn; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value = elementByRow[j]; kColumn = column[j]; if (value > 0.0) { if (columnUpper[kColumn] >= large) { ++infiniteUpper; } else { maximumUp += columnUpper[kColumn] * value; } if (columnLower[kColumn] <= -large) { ++infiniteLower; } else { maximumDown += columnLower[kColumn] * value; } } else if (value < 0.0) { if (columnUpper[kColumn] >= large) { ++infiniteLower; } else { maximumDown += columnUpper[kColumn] * value; } if (columnLower[kColumn] <= -large) { ++infiniteUpper; } else { maximumUp += columnLower[kColumn] * value; } } } // Build in a margin of error maximumUp += 1.0e-8 * fabs(maximumUp); maximumDown -= 1.0e-8 * fabs(maximumDown); double maxUp = maximumUp + infiniteUpper * 1.0e31; double maxDown = maximumDown - infiniteLower * 1.0e31; if (maxUp <= rowUpper[iRow] + tolerance && maxDown >= rowLower[iRow] - tolerance) { //printf("Redundant row in vubs %d\n",iRow); } else { if (maxUp < rowLower[iRow] - 100.0*tolerance || maxDown > rowUpper[iRow] + 100.0*tolerance) { infeasible = true; break; } double lower = rowLower[iRow]; double upper = rowUpper[iRow]; for (j = rStart; j < rEnd; ++j) { double value = elementByRow[j]; kColumn = column[j]; double nowLower = columnLower[kColumn]; double nowUpper = columnUpper[kColumn]; if (value > 0.0) { // positive value if (lower > -large) { if (!infiniteUpper) { assert(nowUpper < large2); newBound = nowUpper + (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp) > 1.0e8) newBound -= 1.0e-12 * fabs(maximumUp); } else if (infiniteUpper == 1 && nowUpper > large) { newBound = (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp) > 1.0e8) newBound -= 1.0e-12 * fabs(maximumUp); } else { newBound = -COIN_DBL_MAX; } if (newBound > nowLower + 1.0e-12 && newBound > -large) { // Tighten the lower bound // check infeasible (relaxed) if (nowUpper < newBound) { if (nowUpper - newBound < -100.0*tolerance) { infeasible = true; break; } } } } if (upper < large) { if (!infiniteLower) { assert(nowLower > - large2); newBound = nowLower + (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown) > 1.0e8) newBound += 1.0e-12 * fabs(maximumDown); } else if (infiniteLower == 1 && nowLower < -large) { newBound = (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown) > 1.0e8) newBound += 1.0e-12 * fabs(maximumDown); } else { newBound = COIN_DBL_MAX; } if (newBound < nowUpper - 1.0e-12 && newBound < large) { // Tighten the upper bound // check infeasible (relaxed) if (nowLower > newBound) { if (newBound - nowLower < -100.0*tolerance) { infeasible = true; break; } else { newBound = nowLower; } } if (!newBound || (clpSolver->isInteger(kColumn) && newBound < 0.999)) { // fix to zero if (!mark[kColumn]) { otherColumn[numberOther++] = kColumn; mark[kColumn] = 1; if (check[iRow] == -1) check[iRow] = iColumn; else assert(check[iRow] == iColumn); } } } } } else { // negative value if (lower > -large) { if (!infiniteUpper) { assert(nowLower < large2); newBound = nowLower + (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp) > 1.0e8) newBound += 1.0e-12 * fabs(maximumUp); } else if (infiniteUpper == 1 && nowLower < -large) { newBound = (lower - maximumUp) / value; // relax if original was large if (fabs(maximumUp) > 1.0e8) newBound += 1.0e-12 * fabs(maximumUp); } else { newBound = COIN_DBL_MAX; } if (newBound < nowUpper - 1.0e-12 && newBound < large) { // Tighten the upper bound // check infeasible (relaxed) if (nowLower > newBound) { if (newBound - nowLower < -100.0*tolerance) { infeasible = true; break; } else { newBound = nowLower; } } if (!newBound || (clpSolver->isInteger(kColumn) && newBound < 0.999)) { // fix to zero if (!mark[kColumn]) { otherColumn[numberOther++] = kColumn; mark[kColumn] = 1; if (check[iRow] == -1) check[iRow] = iColumn; else assert(check[iRow] == iColumn); } } } } if (upper < large) { if (!infiniteLower) { assert(nowUpper < large2); newBound = nowUpper + (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown) > 1.0e8) newBound -= 1.0e-12 * fabs(maximumDown); } else if (infiniteLower == 1 && nowUpper > large) { newBound = (upper - maximumDown) / value; // relax if original was large if (fabs(maximumDown) > 1.0e8) newBound -= 1.0e-12 * fabs(maximumDown); } else { newBound = -COIN_DBL_MAX; } if (newBound > nowLower + 1.0e-12 && newBound > -large) { // Tighten the lower bound // check infeasible (relaxed) if (nowUpper < newBound) { if (nowUpper - newBound < -100.0*tolerance) { infeasible = true; break; } } } } } } } } for (int i = fixColumn[iColumn]; i < numberOther; i++) mark[otherColumn[i]] = 0; // reset bound unless infeasible if (!infeasible || !clpSolver->isInteger(iColumn)) columnUpper[iColumn] = saveUpper; else if (clpSolver->isInteger(iColumn)) columnLower[iColumn] = 1.0; } } fixColumn[iColumn+1] = numberOther; } delete [] check; delete [] mark; // Now do reverse way int * counts = new int [numberColumns]; CoinZeroN(counts, numberColumns); for (iColumn = 0; iColumn < numberColumns; iColumn++) { for (int i = fixColumn[iColumn]; i < fixColumn[iColumn+1]; i++) counts[otherColumn[i]]++; } numberOther = 0; CoinBigIndex * fixColumn2 = new CoinBigIndex [numberColumns+1]; int * otherColumn2 = new int [fixColumn[numberColumns]]; fixColumn2[0] = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { numberOther += counts[iColumn]; counts[iColumn] = 0; fixColumn2[iColumn+1] = numberOther; } // Create other way for ( iColumn = 0; iColumn < numberColumns; iColumn++) { for (int i = fixColumn[iColumn]; i < fixColumn[iColumn+1]; i++) { int jColumn = otherColumn[i]; CoinBigIndex put = fixColumn2[jColumn] + counts[jColumn]; counts[jColumn]++; otherColumn2[put] = iColumn; } } // get top layer i.e. those which are not fixed by any other int kLayer = 0; while (true) { int numberLayered = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (fix[iColumn] == kLayer) { for (int i = fixColumn2[iColumn]; i < fixColumn2[iColumn+1]; i++) { int jColumn = otherColumn2[i]; if (fix[jColumn] == kLayer) { fix[iColumn] = kLayer + 100; } } } if (fix[iColumn] == kLayer) { numberLayered++; } } if (numberLayered) { kLayer += 100; } else { break; } } for (int iPass = 0; iPass < 2; iPass++) { for (int jLayer = 0; jLayer < kLayer; jLayer++) { int check[] = { -1, 0, 1, 2, 3, 4, 5, 10, 50, 100, 500, 1000, 5000, 10000, COIN_INT_MAX}; int nCheck = static_cast (sizeof(check) / sizeof(int)); int countsI[20]; int countsC[20]; assert (nCheck <= 20); memset(countsI, 0, nCheck*sizeof(int)); memset(countsC, 0, nCheck*sizeof(int)); check[nCheck-1] = numberColumns; int numberLayered = 0; int numberInteger = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (fix[iColumn] == jLayer) { numberLayered++; int nFix = fixColumn[iColumn+1] - fixColumn[iColumn]; if (iPass) { // just integers nFix = 0; for (int i = fixColumn[iColumn]; i < fixColumn[iColumn+1]; i++) { int jColumn = otherColumn[i]; if (clpSolver->isInteger(jColumn)) nFix++; } } int iFix; for (iFix = 0; iFix < nCheck; iFix++) { if (nFix <= check[iFix]) break; } assert (iFix < nCheck); if (clpSolver->isInteger(iColumn)) { numberInteger++; countsI[iFix]++; } else { countsC[iFix]++; } } } #ifdef COIN_DETAIL if (numberLayered) { printf("%d (%d integer) at priority %d\n", numberLayered, numberInteger, 1 + (jLayer / 100)); char buffer[50]; for (int i = 1; i < nCheck; i++) { if (countsI[i] || countsC[i]) { if (i == 1) sprintf(buffer, " == zero "); else if (i < nCheck - 1) sprintf(buffer, "> %6d and <= %6d ", check[i-1], check[i]); else sprintf(buffer, "> %6d ", check[i-1]); printf("%s %8d integers and %8d continuous\n", buffer, countsI[i], countsC[i]); } } } #endif } } delete [] counts; // Now do fixing { // switch off presolve and up weight ClpSolve solveOptions; //solveOptions.setPresolveType(ClpSolve::presolveOff,0); solveOptions.setSolveType(ClpSolve::usePrimalorSprint); //solveOptions.setSpecialOption(1,3,30); // sprint int numberColumns = lpSolver->numberColumns(); int iColumn; bool allSlack = true; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (lpSolver->getColumnStatus(iColumn) == ClpSimplex::basic) { allSlack = false; break; } } if (allSlack) solveOptions.setSpecialOption(1, 2, 50); // idiot lpSolver->setInfeasibilityCost(1.0e11); lpSolver->defaultFactorizationFrequency(); if (doAction != 11) lpSolver->initialSolve(solveOptions); double * columnLower = lpSolver->columnLower(); double * columnUpper = lpSolver->columnUpper(); double * fullSolution = lpSolver->primalColumnSolution(); const double * dj = lpSolver->dualColumnSolution(); int iPass = 0; #define MAXPROB 2 ClpSimplex models[MAXPROB]; int kPass = -1; int kLayer = 0; int skipZero = 0; if (skipZero2 == -1) skipZero2 = 40; //-1; /* 0 fixed to 0 by choice 1 lb of 1 by choice 2 fixed to 0 by another 3 as 2 but this go -1 free */ char * state = new char [numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) state[iColumn] = -1; while (true) { double largest = -0.1; double smallest = 1.1; int iLargest = -1; int iSmallest = -1; int atZero = 0; int atOne = 0; int toZero = 0; int toOne = 0; int numberFree = 0; int numberGreater = 0; columnLower = lpSolver->columnLower(); columnUpper = lpSolver->columnUpper(); fullSolution = lpSolver->primalColumnSolution(); if (doAction == 11) { { double * columnLower = lpSolver->columnLower(); double * columnUpper = lpSolver->columnUpper(); // lpSolver->dual(); memcpy(columnLower, saveColumnLower, numberColumns*sizeof(double)); memcpy(columnUpper, saveColumnUpper, numberColumns*sizeof(double)); // lpSolver->dual(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) { if (clpSolver->isInteger(iColumn)) { double value = lastSolution[iColumn]; int iValue = static_cast (value + 0.5); assert (fabs(value - static_cast (iValue)) < 1.0e-3); assert (iValue >= columnLower[iColumn] && iValue <= columnUpper[iColumn]); columnLower[iColumn] = iValue; columnUpper[iColumn] = iValue; } } } lpSolver->initialSolve(solveOptions); memcpy(columnLower, saveColumnLower, numberColumns*sizeof(double)); memcpy(columnUpper, saveColumnUpper, numberColumns*sizeof(double)); } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-8) { if (clpSolver->isInteger(iColumn)) { double value = lastSolution[iColumn]; int iValue = static_cast (value + 0.5); assert (fabs(value - static_cast (iValue)) < 1.0e-3); assert (iValue >= columnLower[iColumn] && iValue <= columnUpper[iColumn]); if (!fix[iColumn]) { if (iValue == 0) { state[iColumn] = 0; assert (!columnLower[iColumn]); columnUpper[iColumn] = 0.0; } else if (iValue == 1) { state[iColumn] = 1; columnLower[iColumn] = 1.0; } else { // leave fixed columnLower[iColumn] = iValue; columnUpper[iColumn] = iValue; } } else if (iValue == 0) { state[iColumn] = 10; columnUpper[iColumn] = 0.0; } else { // leave fixed columnLower[iColumn] = iValue; columnUpper[iColumn] = iValue; } } } } int jLayer = 0; int nFixed = -1; int nTotalFixed = 0; while (nFixed) { nFixed = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) { for (int i = fixColumn[iColumn]; i < fixColumn[iColumn+1]; i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn]) { bool canFix = true; for (int k = fixColumn2[jColumn]; k < fixColumn2[jColumn+1]; k++) { int kColumn = otherColumn2[k]; if (state[kColumn] == 1) { canFix = false; break; } } if (canFix) { columnUpper[jColumn] = 0.0; nFixed++; } } } } } nTotalFixed += nFixed; jLayer += 100; } COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities\n", nTotalFixed)); break; } for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (!clpSolver->isInteger(iColumn) || fix[iColumn] > kLayer) continue; // skip if fixes nothing if (fixColumn[iColumn+1] - fixColumn[iColumn] <= skipZero2) continue; double value = fullSolution[iColumn]; if (value > 1.00001) { numberGreater++; continue; } double lower = columnLower[iColumn]; double upper = columnUpper[iColumn]; if (lower == upper) { if (lower) atOne++; else atZero++; continue; } if (value < 1.0e-7) { toZero++; columnUpper[iColumn] = 0.0; state[iColumn] = 10; continue; } if (value > 1.0 - 1.0e-7) { toOne++; columnLower[iColumn] = 1.0; state[iColumn] = 1; continue; } numberFree++; // skip if fixes nothing if (fixColumn[iColumn+1] - fixColumn[iColumn] <= skipZero) continue; if (value < smallest) { smallest = value; iSmallest = iColumn; } if (value > largest) { largest = value; iLargest = iColumn; } } if (toZero || toOne) COIN_DETAIL_PRINT(printf("%d at 0 fixed and %d at one fixed\n", toZero, toOne)); COIN_DETAIL_PRINT(printf("%d variables free, %d fixed to 0, %d to 1 - smallest %g, largest %g\n", numberFree, atZero, atOne, smallest, largest)); if (numberGreater && !iPass) COIN_DETAIL_PRINT(printf("%d variables have value > 1.0\n", numberGreater)); //skipZero2=0; // leave 0 fixing int jLayer = 0; int nFixed = -1; int nTotalFixed = 0; while (nFixed) { nFixed = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) { for (int i = fixColumn[iColumn]; i < fixColumn[iColumn+1]; i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn]) { bool canFix = true; for (int k = fixColumn2[jColumn]; k < fixColumn2[jColumn+1]; k++) { int kColumn = otherColumn2[k]; if (state[kColumn] == 1) { canFix = false; break; } } if (canFix) { columnUpper[jColumn] = 0.0; nFixed++; } } } } } nTotalFixed += nFixed; jLayer += 100; } COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities\n", nTotalFixed)); if (iLargest < 0 || numberFree <= leaveIntFree) break; double movement; int way; if (smallest <= 1.0 - largest && smallest < 0.2 && largest < fixAboveValue) { columnUpper[iSmallest] = 0.0; state[iSmallest] = 0; movement = smallest; way = -1; } else { columnLower[iLargest] = 1.0; state[iLargest] = 1; movement = 1.0 - largest; way = 1; } double saveObj = lpSolver->objectiveValue(); iPass++; kPass = iPass % MAXPROB; models[kPass] = *lpSolver; if (way == -1) { // fix others for (int i = fixColumn[iSmallest]; i < fixColumn[iSmallest+1]; i++) { int jColumn = otherColumn[i]; if (state[jColumn] == -1) { columnUpper[jColumn] = 0.0; state[jColumn] = 3; } } } double maxCostUp = COIN_DBL_MAX; objective = lpSolver->getObjCoefficients() ; if (way == -1) maxCostUp = (1.0 - movement) * objective[iSmallest]; lpSolver->setDualObjectiveLimit(saveObj + maxCostUp); crunchIt(lpSolver); double moveObj = lpSolver->objectiveValue() - saveObj; COIN_DETAIL_PRINT(printf("movement %s was %g costing %g\n", (way == -1) ? "down" : "up", movement, moveObj)); if (way == -1 && (moveObj >= maxCostUp || lpSolver->status())) { // go up columnLower = models[kPass].columnLower(); columnUpper = models[kPass].columnUpper(); columnLower[iSmallest] = 1.0; columnUpper[iSmallest] = saveColumnUpper[iSmallest]; *lpSolver = models[kPass]; columnLower = lpSolver->columnLower(); columnUpper = lpSolver->columnUpper(); fullSolution = lpSolver->primalColumnSolution(); dj = lpSolver->dualColumnSolution(); columnLower[iSmallest] = 1.0; columnUpper[iSmallest] = saveColumnUpper[iSmallest]; state[iSmallest] = 1; // unfix others for (int i = fixColumn[iSmallest]; i < fixColumn[iSmallest+1]; i++) { int jColumn = otherColumn[i]; if (state[jColumn] == 3) { columnUpper[jColumn] = saveColumnUpper[jColumn]; state[jColumn] = -1; } } crunchIt(lpSolver); } models[kPass] = *lpSolver; } lpSolver->dual(); COIN_DETAIL_PRINT(printf("Fixing took %g seconds\n", CoinCpuTime() - time1)); columnLower = lpSolver->columnLower(); columnUpper = lpSolver->columnUpper(); fullSolution = lpSolver->primalColumnSolution(); dj = lpSolver->dualColumnSolution(); int * sort = new int[numberColumns]; double * dsort = new double[numberColumns]; int chunk = 20; int iRelax = 0; //double fractionFixed=6.0/8.0; // relax while lots fixed while (true) { if (skipZero2 > 10 && doAction < 10) break; iRelax++; int n = 0; double sum0 = 0.0; double sum00 = 0.0; double sum1 = 0.0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (!clpSolver->isInteger(iColumn) || fix[iColumn] > kLayer) continue; // skip if fixes nothing if (fixColumn[iColumn+1] - fixColumn[iColumn] == 0 && doAction < 10) continue; double djValue = dj[iColumn]; if (state[iColumn] == 1) { assert (columnLower[iColumn]); assert (fullSolution[iColumn] > 0.1); if (djValue > 0.0) { //printf("YY dj of %d at %g is %g\n",iColumn,value,djValue); sum1 += djValue; sort[n] = iColumn; dsort[n++] = -djValue; } else { //printf("dj of %d at %g is %g\n",iColumn,value,djValue); } } else if (state[iColumn] == 0 || state[iColumn] == 10) { assert (fullSolution[iColumn] < 0.1); assert (!columnUpper[iColumn]); double otherValue = 0.0; int nn = 0; for (int i = fixColumn[iColumn]; i < fixColumn[iColumn+1]; i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn] == 0.0) { if (dj[jColumn] < -1.0e-5) { nn++; otherValue += dj[jColumn]; // really need to look at rest } } } if (djValue < -1.0e-2 || otherValue < -1.0e-2) { //printf("XX dj of %d at %g is %g - %d out of %d contribute %g\n",iColumn,value,djValue, // nn,fixColumn[iColumn+1]-fixColumn[iColumn],otherValue); if (djValue < 1.0e-8) { sum0 -= djValue; sum00 -= otherValue; sort[n] = iColumn; if (djValue < -1.0e-2) dsort[n++] = djValue + otherValue; else dsort[n++] = djValue + 0.001 * otherValue; } } else { //printf("dj of %d at %g is %g - no contribution from %d\n",iColumn,value,djValue, // fixColumn[iColumn+1]-fixColumn[iColumn]); } } } CoinSort_2(dsort, dsort + n, sort); double * originalColumnLower = saveColumnLower; double * originalColumnUpper = saveColumnUpper; double * lo = CoinCopyOfArray(columnLower, numberColumns); double * up = CoinCopyOfArray(columnUpper, numberColumns); for (int k = 0; k < CoinMin(chunk, n); k++) { iColumn = sort[k]; state[iColumn] = -2; } memcpy(columnLower, originalColumnLower, numberColumns*sizeof(double)); memcpy(columnUpper, originalColumnUpper, numberColumns*sizeof(double)); int nFixed = 0; int nFixed0 = 0; int nFixed1 = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (state[iColumn] == 0 || state[iColumn] == 10) { columnUpper[iColumn] = 0.0; assert (lo[iColumn] == 0.0); nFixed++; nFixed0++; for (int i = fixColumn[iColumn]; i < fixColumn[iColumn+1]; i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn]) { bool canFix = true; for (int k = fixColumn2[jColumn]; k < fixColumn2[jColumn+1]; k++) { int kColumn = otherColumn2[k]; if (state[kColumn] == 1 || state[kColumn] == -2) { canFix = false; break; } } if (canFix) { columnUpper[jColumn] = 0.0; assert (lo[jColumn] == 0.0); nFixed++; } } } } else if (state[iColumn] == 1) { columnLower[iColumn] = 1.0; nFixed1++; } } COIN_DETAIL_PRINT(printf("%d fixed %d orig 0 %d 1\n", nFixed, nFixed0, nFixed1)); int jLayer = 0; nFixed = -1; int nTotalFixed = 0; while (nFixed) { nFixed = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && fix[iColumn] == jLayer) { for (int i = fixColumn[iColumn]; i < fixColumn[iColumn+1]; i++) { int jColumn = otherColumn[i]; if (columnUpper[jColumn]) { bool canFix = true; for (int k = fixColumn2[jColumn]; k < fixColumn2[jColumn+1]; k++) { int kColumn = otherColumn2[k]; if (state[kColumn] == 1 || state[kColumn] == -2) { canFix = false; break; } } if (canFix) { columnUpper[jColumn] = 0.0; assert (lo[jColumn] == 0.0); nFixed++; } } } } } nTotalFixed += nFixed; jLayer += 100; } nFixed = 0; int nFixedI = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLower[iColumn] == columnUpper[iColumn]) { if (clpSolver->isInteger(iColumn)) nFixedI++; nFixed++; } } COIN_DETAIL_PRINT(printf("This fixes %d variables in lower priorities - total %d (%d integer) - all target %d, int target %d\n", nTotalFixed, nFixed, nFixedI, static_cast(fractionFixed*numberColumns), static_cast (fractionIntFixed*numberInteger))); int nBad = 0; int nRelax = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (lo[iColumn] < columnLower[iColumn] || up[iColumn] > columnUpper[iColumn]) { COIN_DETAIL_PRINT(printf("bad %d old %g %g, new %g %g\n", iColumn, lo[iColumn], up[iColumn], columnLower[iColumn], columnUpper[iColumn])); nBad++; } if (lo[iColumn] > columnLower[iColumn] || up[iColumn] < columnUpper[iColumn]) { nRelax++; } } COIN_DETAIL_PRINT(printf("%d relaxed\n", nRelax)); if (iRelax > 20 && nRelax == chunk) nRelax = 0; if (iRelax > 50) nRelax = 0; assert (!nBad); delete [] lo; delete [] up; lpSolver->primal(1); if (nFixed < fractionFixed*numberColumns || nFixedI < fractionIntFixed*numberInteger || !nRelax) break; } delete [] state; delete [] sort; delete [] dsort; } delete [] fix; delete [] fixColumn; delete [] otherColumn; delete [] otherColumn2; delete [] fixColumn2; // See if was presolved if (originalColumns) { columnLower = lpSolver->columnLower(); columnUpper = lpSolver->columnUpper(); for ( iColumn = 0; iColumn < numberColumns; iColumn++) { saveColumnLower[iColumn] = columnLower[iColumn]; saveColumnUpper[iColumn] = columnUpper[iColumn]; } pinfo.postsolve(true); columnLower = originalLpSolver->columnLower(); columnUpper = originalLpSolver->columnUpper(); double * newColumnLower = lpSolver->columnLower(); double * newColumnUpper = lpSolver->columnUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = originalColumns[iColumn]; columnLower[jColumn] = CoinMax(columnLower[jColumn], newColumnLower[iColumn]); columnUpper[jColumn] = CoinMin(columnUpper[jColumn], newColumnUpper[iColumn]); } numberColumns = originalLpSolver->numberColumns(); delete [] originalColumns; } delete [] saveColumnLower; delete [] saveColumnUpper; if (!originalColumns) { // Basis memcpy(originalLpSolver->statusArray(), lpSolver->statusArray(), numberRows + numberColumns); memcpy(originalLpSolver->primalColumnSolution(), lpSolver->primalColumnSolution(), numberColumns*sizeof(double)); memcpy(originalLpSolver->primalRowSolution(), lpSolver->primalRowSolution(), numberRows*sizeof(double)); // Fix in solver columnLower = lpSolver->columnLower(); columnUpper = lpSolver->columnUpper(); } double * originalColumnLower = originalLpSolver->columnLower(); double * originalColumnUpper = originalLpSolver->columnUpper(); // number fixed doAction = 0; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { originalColumnLower[iColumn] = columnLower[iColumn]; originalColumnUpper[iColumn] = columnUpper[iColumn]; if (columnLower[iColumn] == columnUpper[iColumn]) doAction++; } COIN_DETAIL_PRINT(printf("%d fixed by vub preprocessing\n", doAction)); if (originalColumns) { originalLpSolver->initialSolve(); } delete clpSolver; return NULL; } int doHeuristics(CbcModel * model, int type, CbcOrClpParam* parameters_, int numberParameters_,int noPrinting_,int initialPumpTune) { #ifdef JJF_ZERO //NEW_STYLE_SOLVER==0 CbcOrClpParam * parameters_ = parameters; int numberParameters_ = numberParameters; bool noPrinting_ = noPrinting_; #endif char generalPrint[10000]; CoinMessages generalMessages = model->messages(); CoinMessageHandler * generalMessageHandler = model->messageHandler(); //generalMessageHandler->setPrefix(false); bool anyToDo = false; int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_)].intValue(); int useFpump = parameters_[whichParam(CBC_PARAM_STR_FPUMP, numberParameters_, parameters_)].currentOptionAsInteger(); int useRounding = parameters_[whichParam(CBC_PARAM_STR_ROUNDING, numberParameters_, parameters_)].currentOptionAsInteger(); int useGreedy = parameters_[whichParam(CBC_PARAM_STR_GREEDY, numberParameters_, parameters_)].currentOptionAsInteger(); int useCombine = parameters_[whichParam(CBC_PARAM_STR_COMBINE, numberParameters_, parameters_)].currentOptionAsInteger(); int useProximity = parameters_[whichParam(CBC_PARAM_STR_PROXIMITY, numberParameters_, parameters_)].currentOptionAsInteger(); int useCrossover = parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, numberParameters_, parameters_)].currentOptionAsInteger(); //int usePivotC = parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, numberParameters_, parameters_)].currentOptionAsInteger(); int usePivotF = parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, numberParameters_, parameters_)].currentOptionAsInteger(); int useRand = parameters_[whichParam(CBC_PARAM_STR_RANDROUND, numberParameters_, parameters_)].currentOptionAsInteger(); int useRINS = parameters_[whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_)].currentOptionAsInteger(); int useRENS = parameters_[whichParam(CBC_PARAM_STR_RENS, numberParameters_, parameters_)].currentOptionAsInteger(); int useDINS = parameters_[whichParam(CBC_PARAM_STR_DINS, numberParameters_, parameters_)].currentOptionAsInteger(); int useDIVING2 = parameters_[whichParam(CBC_PARAM_STR_DIVINGS, numberParameters_, parameters_)].currentOptionAsInteger(); int useNaive = parameters_[whichParam(CBC_PARAM_STR_NAIVE, numberParameters_, parameters_)].currentOptionAsInteger(); int kType = (type < 10) ? type : 1; assert (kType == 1 || kType == 2); // FPump done first as it only works if no solution if (useFpump >= kType && useFpump <= kType + 1) { anyToDo = true; CbcHeuristicFPump heuristic4(*model); double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_SMALLBAB, numberParameters_, parameters_)].doubleValue(); heuristic4.setFractionSmall(dextra3); double dextra1 = parameters_[whichParam(CBC_PARAM_DBL_ARTIFICIALCOST, numberParameters_, parameters_)].doubleValue(); if (dextra1) heuristic4.setArtificialCost(dextra1); heuristic4.setMaximumPasses(parameters_[whichParam(CBC_PARAM_INT_FPUMPITS, numberParameters_, parameters_)].intValue()); if (parameters_[whichParam(CBC_PARAM_INT_FPUMPITS, numberParameters_, parameters_)].intValue() == 21) heuristic4.setIterationRatio(1.0); int pumpTune = parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_)].intValue(); int pumpTune2 = parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE2, numberParameters_, parameters_)].intValue(); if (pumpTune > 0) { bool printStuff = (pumpTune != initialPumpTune || logLevel > 1 || pumpTune2 > 0) && !noPrinting_; if (printStuff) { generalMessageHandler->message(CBC_GENERAL, generalMessages) << "Options for feasibility pump - " << CoinMessageEol; } /* >=10000000 for using obj >=1000000 use as accumulate switch >=1000 use index+1 as number of large loops >=100 use dextra1 as cutoff %100 == 10,20 etc for experimentation 1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds 4 and static continuous, 5 as 3 but no internal integers 6 as 3 but all slack basis! */ double value = model->solver()->getObjSense() * model->solver()->getObjValue(); int w = pumpTune / 10; int i = w % 10; w /= 10; int c = w % 10; w /= 10; int r = w; int accumulate = r / 1000; r -= 1000 * accumulate; if (accumulate >= 10) { int which = accumulate / 10; accumulate -= 10 * which; which--; // weights and factors double weight[] = {0.01, 0.01, 0.1, 0.1, 0.5, 0.5, 1.0, 1.0, 5.0, 5.0}; double factor[] = {0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5}; heuristic4.setInitialWeight(weight[which]); heuristic4.setWeightFactor(factor[which]); if (printStuff) { sprintf(generalPrint, "Initial weight for objective %g, decay factor %g", weight[which], factor[which]); generalMessageHandler->message(CBC_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } // fake cutoff if (c) { double cutoff; model->solver()->getDblParam(OsiDualObjectiveLimit, cutoff); cutoff = CoinMin(cutoff, value + 0.05 * fabs(value) * c); double fakeCutoff = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, numberParameters_, parameters_)].doubleValue(); if (fakeCutoff) cutoff = fakeCutoff; heuristic4.setFakeCutoff(cutoff); if (printStuff) { sprintf(generalPrint, "Fake cutoff of %g", cutoff); generalMessageHandler->message(CBC_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } int offRandomEtc = 0; if (pumpTune2) { if ((pumpTune2 / 1000) != 0) { offRandomEtc = 1000000 * (pumpTune2 / 1000); if (printStuff) { generalMessageHandler->message(CBC_GENERAL, generalMessages) << "Feasibility pump may run twice" << CoinMessageEol; } pumpTune2 = pumpTune2 % 1000; } if ((pumpTune2 / 100) != 0) { offRandomEtc += 100 * (pumpTune2 / 100); if (printStuff) { generalMessageHandler->message(CBC_GENERAL, generalMessages) << "Not using randomized objective" << CoinMessageEol; } } int maxAllowed = pumpTune2 % 100; if (maxAllowed) { offRandomEtc += 1000 * maxAllowed; if (printStuff) { sprintf(generalPrint, "Fixing if same for %d passes", maxAllowed); generalMessageHandler->message(CBC_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } } if (accumulate) { heuristic4.setAccumulate(accumulate); if (printStuff) { if (accumulate) { sprintf(generalPrint, "Accumulate of %d", accumulate); generalMessageHandler->message(CBC_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } } if (r) { // also set increment //double increment = (0.01*i+0.005)*(fabs(value)+1.0e-12); double increment = 0.0; double fakeIncrement = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, numberParameters_, parameters_)].doubleValue(); if (fakeIncrement) increment = fakeIncrement; heuristic4.setAbsoluteIncrement(increment); heuristic4.setMaximumRetries(r + 1); if (printStuff) { if (increment) { sprintf(generalPrint, "Increment of %g", increment); generalMessageHandler->message(CBC_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } sprintf(generalPrint, "%d retries", r + 1); generalMessageHandler->message(CBC_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } if (i + offRandomEtc) { heuristic4.setFeasibilityPumpOptions(i*10 + offRandomEtc); if (printStuff) { sprintf(generalPrint, "Feasibility pump options of %d", i*10 + offRandomEtc); generalMessageHandler->message(CBC_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } pumpTune = pumpTune % 100; if (pumpTune == 6) pumpTune = 13; heuristic4.setWhen((pumpTune % 10) + 10); if (printStuff) { sprintf(generalPrint, "Tuning (fixing) %d", pumpTune % 10); generalMessageHandler->message(CBC_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } } heuristic4.setHeuristicName("feasibility pump"); //#define ROLF #ifdef ROLF CbcHeuristicFPump pump(*model); pump.setMaximumTime(60); pump.setMaximumPasses(100); pump.setMaximumRetries(1); pump.setFixOnReducedCosts(0); pump.setHeuristicName("Feasibility pump"); pump.setFractionSmall(1.0); pump.setWhen(13); model->addHeuristic(&pump); #else model->addHeuristic(&heuristic4); #endif } if (useRounding >= type && useRounding >= kType && useRounding <= kType + 1) { CbcRounding heuristic1(*model); heuristic1.setHeuristicName("rounding"); model->addHeuristic(&heuristic1) ; anyToDo = true; } if (useGreedy >= type && useGreedy >= kType && useGreedy <= kType + 1) { CbcHeuristicGreedyCover heuristic3(*model); heuristic3.setHeuristicName("greedy cover"); CbcHeuristicGreedyEquality heuristic3a(*model); heuristic3a.setHeuristicName("greedy equality"); model->addHeuristic(&heuristic3); model->addHeuristic(&heuristic3a); anyToDo = true; } if ((useRENS==7 && kType==1) || (useRENS==8 && kType==2)) { useRENS=1+2*(useRENS-7); CbcHeuristicRENS heuristic6a(*model); heuristic6a.setHeuristicName("RENSdj"); heuristic6a.setFractionSmall(0.6/*3.4*/); heuristic6a.setFeasibilityPumpOptions(3); heuristic6a.setNumberNodes(10); heuristic6a.setWhereFrom(4*256+4*1); heuristic6a.setWhen(2); heuristic6a.setRensType(1+16); model->addHeuristic(&heuristic6a) ; heuristic6a.setHeuristicName("RENSub"); heuristic6a.setFractionSmall(0.4); heuristic6a.setFeasibilityPumpOptions(1008003); heuristic6a.setNumberNodes(50); heuristic6a.setWhereFrom(4*256+4*1); heuristic6a.setWhen(2); heuristic6a.setRensType(2+16); model->addHeuristic(&heuristic6a) ; } if (useRENS >= kType && useRENS <= kType + 1) { #ifndef JJF_ONE CbcHeuristicRENS heuristic6(*model); heuristic6.setHeuristicName("RENS"); heuristic6.setFractionSmall(0.4); heuristic6.setFeasibilityPumpOptions(1008003); int nodes [] = { -2, 50, 50, 50, 200, 1000, 10000}; heuristic6.setNumberNodes(nodes[useRENS]); #else CbcHeuristicVND heuristic6(*model); heuristic6.setHeuristicName("VND"); heuristic5.setFractionSmall(0.5); heuristic5.setDecayFactor(5.0); #endif model->addHeuristic(&heuristic6) ; anyToDo = true; } if (useNaive >= kType && useNaive <= kType + 1) { CbcHeuristicNaive heuristic5b(*model); heuristic5b.setHeuristicName("Naive"); heuristic5b.setFractionSmall(0.4); heuristic5b.setNumberNodes(50); model->addHeuristic(&heuristic5b) ; anyToDo = true; } int useDIVING = 0; { int useD; useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGV, numberParameters_, parameters_)].currentOptionAsInteger(); useDIVING |= 1 * ((useD >= kType) ? 1 : 0); useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGG, numberParameters_, parameters_)].currentOptionAsInteger(); useDIVING |= 2 * ((useD >= kType) ? 1 : 0); useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGF, numberParameters_, parameters_)].currentOptionAsInteger(); useDIVING |= 4 * ((useD >= kType) ? 1 : 0); useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_)].currentOptionAsInteger(); useDIVING |= 8 * ((useD >= kType) ? 1 : 0); useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGL, numberParameters_, parameters_)].currentOptionAsInteger(); useDIVING |= 16 * ((useD >= kType) ? 1 : 0); useD = parameters_[whichParam(CBC_PARAM_STR_DIVINGP, numberParameters_, parameters_)].currentOptionAsInteger(); useDIVING |= 32 * ((useD >= kType) ? 1 : 0); } if (useDIVING2 >= kType && useDIVING2 <= kType + 1) { int diveOptions = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, numberParameters_, parameters_)].intValue(); if (diveOptions < 0 || diveOptions > 10) diveOptions = 2; CbcHeuristicJustOne heuristicJustOne(*model); heuristicJustOne.setHeuristicName("DiveAny"); heuristicJustOne.setWhen(diveOptions); // add in others CbcHeuristicDiveCoefficient heuristicDC(*model); heuristicDC.setHeuristicName("DiveCoefficient"); heuristicJustOne.addHeuristic(&heuristicDC, 1.0) ; CbcHeuristicDiveFractional heuristicDF(*model); heuristicDF.setHeuristicName("DiveFractional"); heuristicJustOne.addHeuristic(&heuristicDF, 1.0) ; CbcHeuristicDiveGuided heuristicDG(*model); heuristicDG.setHeuristicName("DiveGuided"); heuristicJustOne.addHeuristic(&heuristicDG, 1.0) ; CbcHeuristicDiveLineSearch heuristicDL(*model); heuristicDL.setHeuristicName("DiveLineSearch"); heuristicJustOne.addHeuristic(&heuristicDL, 1.0) ; CbcHeuristicDivePseudoCost heuristicDP(*model); heuristicDP.setHeuristicName("DivePseudoCost"); heuristicJustOne.addHeuristic(&heuristicDP, 1.0) ; CbcHeuristicDiveVectorLength heuristicDV(*model); heuristicDV.setHeuristicName("DiveVectorLength"); heuristicJustOne.addHeuristic(&heuristicDV, 1.0) ; // Now normalize probabilities heuristicJustOne.normalizeProbabilities(); model->addHeuristic(&heuristicJustOne) ; } if (useDIVING > 0) { int majorIterations=64; int diveOptions2 = parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, numberParameters_, parameters_)].intValue(); int diveOptions; if (diveOptions2 > 99) { // switch on various active set stuff diveOptions = diveOptions2%100; diveOptions2 /= 100; } else { diveOptions = diveOptions2; diveOptions2 = 0; } if (diveOptions < 0 || diveOptions > 9) diveOptions = 2; if ((useDIVING&1) != 0) { CbcHeuristicDiveVectorLength heuristicDV(*model); heuristicDV.setHeuristicName("DiveVectorLength"); heuristicDV.setWhen(diveOptions); if (diveOptions2) { heuristicDV.setMaxIterations(majorIterations); heuristicDV.setPercentageToFix(0.0); heuristicDV.setMaxSimplexIterations(COIN_INT_MAX); heuristicDV.setMaxSimplexIterationsAtRoot(COIN_INT_MAX-(diveOptions2-1)); } model->addHeuristic(&heuristicDV) ; } if ((useDIVING&2) != 0) { CbcHeuristicDiveGuided heuristicDG(*model); heuristicDG.setHeuristicName("DiveGuided"); heuristicDG.setWhen(diveOptions); if (diveOptions2) { heuristicDG.setMaxIterations(majorIterations); heuristicDG.setPercentageToFix(0.0); heuristicDG.setMaxSimplexIterations(COIN_INT_MAX); heuristicDG.setMaxSimplexIterationsAtRoot(COIN_INT_MAX-(diveOptions2-1)); } model->addHeuristic(&heuristicDG) ; } if ((useDIVING&4) != 0) { CbcHeuristicDiveFractional heuristicDF(*model); heuristicDF.setHeuristicName("DiveFractional"); heuristicDF.setWhen(diveOptions); if (diveOptions2) { heuristicDF.setMaxIterations(majorIterations); heuristicDF.setPercentageToFix(0.0); heuristicDF.setMaxSimplexIterations(COIN_INT_MAX); heuristicDF.setMaxSimplexIterationsAtRoot(COIN_INT_MAX-(diveOptions2-1)); } model->addHeuristic(&heuristicDF) ; } if ((useDIVING&8) != 0) { CbcHeuristicDiveCoefficient heuristicDC(*model); heuristicDC.setHeuristicName("DiveCoefficient"); heuristicDC.setWhen(diveOptions); if (diveOptions2) { heuristicDC.setMaxIterations(majorIterations); heuristicDC.setPercentageToFix(0.0); heuristicDC.setMaxSimplexIterations(COIN_INT_MAX); heuristicDC.setMaxSimplexIterationsAtRoot(COIN_INT_MAX-(diveOptions2-1)); } model->addHeuristic(&heuristicDC) ; } if ((useDIVING&16) != 0) { CbcHeuristicDiveLineSearch heuristicDL(*model); heuristicDL.setHeuristicName("DiveLineSearch"); heuristicDL.setWhen(diveOptions); if (diveOptions2) { heuristicDL.setMaxIterations(majorIterations); heuristicDL.setPercentageToFix(0.0); heuristicDL.setMaxSimplexIterations(COIN_INT_MAX); heuristicDL.setMaxSimplexIterationsAtRoot(COIN_INT_MAX-(diveOptions2-1)); } model->addHeuristic(&heuristicDL) ; } if ((useDIVING&32) != 0) { CbcHeuristicDivePseudoCost heuristicDP(*model); heuristicDP.setHeuristicName("DivePseudoCost"); heuristicDP.setWhen(diveOptions /*+ diveOptions2*/); if (diveOptions2) { heuristicDP.setMaxIterations(majorIterations); heuristicDP.setPercentageToFix(0.0); heuristicDP.setMaxSimplexIterations(COIN_INT_MAX); heuristicDP.setMaxSimplexIterationsAtRoot(COIN_INT_MAX-(diveOptions2-1)); } model->addHeuristic(&heuristicDP) ; } anyToDo = true; } #ifdef JJF_ZERO if (usePivotC >= type && usePivotC <= kType + 1) { CbcHeuristicPivotAndComplement heuristic(*model); heuristic.setHeuristicName("pivot and complement"); heuristic.setFractionSmall(10.0); // normally 0.5 model->addHeuristic(&heuristic); anyToDo = true; } #endif if (usePivotF >= type && usePivotF <= kType + 1) { CbcHeuristicPivotAndFix heuristic(*model); heuristic.setHeuristicName("pivot and fix"); heuristic.setFractionSmall(10.0); // normally 0.5 model->addHeuristic(&heuristic); anyToDo = true; } if (useRand >= type && useRand <= kType + 1) { CbcHeuristicRandRound heuristic(*model); heuristic.setHeuristicName("randomized rounding"); heuristic.setFractionSmall(10.0); // normally 0.5 model->addHeuristic(&heuristic); anyToDo = true; } if (useDINS >= kType && useDINS <= kType + 1) { CbcHeuristicDINS heuristic5a(*model); heuristic5a.setHeuristicName("DINS"); heuristic5a.setFractionSmall(0.6); if (useDINS < 4) heuristic5a.setDecayFactor(5.0); else heuristic5a.setDecayFactor(1.5); heuristic5a.setNumberNodes(1000); model->addHeuristic(&heuristic5a) ; anyToDo = true; } if (useRINS >= kType && useRINS <= kType + 1) { CbcHeuristicRINS heuristic5(*model); heuristic5.setHeuristicName("RINS"); if (useRINS < 4) { heuristic5.setFractionSmall(0.5); heuristic5.setDecayFactor(5.0); } else { heuristic5.setFractionSmall(0.6); heuristic5.setDecayFactor(1.5); } model->addHeuristic(&heuristic5) ; anyToDo = true; } if (useCombine >= kType && useCombine <= kType + 1) { CbcHeuristicLocal heuristic2(*model); heuristic2.setHeuristicName("combine solutions"); heuristic2.setFractionSmall(0.5); heuristic2.setSearchType(1); model->addHeuristic(&heuristic2); anyToDo = true; } if ((useProximity >= kType && useProximity <= kType + 1)|| (kType == 1 && useProximity >= 4)) { CbcHeuristicProximity heuristic2a(*model); heuristic2a.setHeuristicName("Proximity Search"); heuristic2a.setFractionSmall(9999999.0); heuristic2a.setNumberNodes(30); heuristic2a.setFeasibilityPumpOptions(-2); if (useProximity>=4) { const int nodes[]={10,100,300}; heuristic2a.setNumberNodes(nodes[useProximity-4]); // more print out and stronger feasibility pump if (useProximity==6) heuristic2a.setFeasibilityPumpOptions(-3); } model->addHeuristic(&heuristic2a); anyToDo = true; } if (useCrossover >= kType && useCrossover <= kType + 1) { CbcHeuristicCrossover heuristic2a(*model); heuristic2a.setHeuristicName("crossover"); heuristic2a.setFractionSmall(0.3); // just fix at lower heuristic2a.setWhen(11); model->addHeuristic(&heuristic2a); model->setMaximumSavedSolutions(5); anyToDo = true; } int heurSwitches = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue() % 100; if (heurSwitches) { for (int iHeur = 0; iHeur < model->numberHeuristics(); iHeur++) { CbcHeuristic * heuristic = model->heuristic(iHeur); heuristic->setSwitches(heurSwitches); } } if (type == 2 && anyToDo) { // Do heuristics #ifndef JJF_ONE // clean copy CbcModel model2(*model); // But get rid of heuristics in model model->doHeuristicsAtRoot(2); if (logLevel <= 1) model2.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); OsiBabSolver defaultC; //solver_->setAuxiliaryInfo(&defaultC); model2.passInSolverCharacteristics(&defaultC); // Save bounds int numberColumns = model2.solver()->getNumCols(); model2.createContinuousSolver(); bool cleanModel = !model2.numberIntegers() && !model2.numberObjects(); model2.findIntegers(false); int heurOptions = (parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue() / 100) % 100; if (heurOptions == 0 || heurOptions == 2) { model2.doHeuristicsAtRoot(1); } else if (heurOptions == 1 || heurOptions == 3) { model2.setMaximumNodes(-1); CbcStrategyDefault strategy(0, 5, 5); strategy.setupPreProcessing(1, 0); model2.setStrategy(strategy); model2.branchAndBound(); } if (cleanModel) model2.zapIntegerInformation(false); if (model2.bestSolution()) { double value = model2.getMinimizationObjValue(); model->setCutoff(value); model->setBestSolution(model2.bestSolution(), numberColumns, value); model->setSolutionCount(1); model->setNumberHeuristicSolutions(1); } #else if (logLevel <= 1) model->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); OsiBabSolver defaultC; //solver_->setAuxiliaryInfo(&defaultC); model->passInSolverCharacteristics(&defaultC); // Save bounds int numberColumns = model->solver()->getNumCols(); model->createContinuousSolver(); bool cleanModel = !model->numberIntegers() && !model->numberObjects(); model->findIntegers(false); model->doHeuristicsAtRoot(1); if (cleanModel) model->zapIntegerInformation(false); #endif return 0; } else { return 0; } } Cbc-2.8.12/src/ClpConstraintAmpl.hpp0000644000076600007660000000572312131315050015644 0ustar coincoin/* $Id: ClpConstraintAmpl.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef ClpConstraintAmpl_H #define ClpConstraintAmpl_H #include "ClpConstraint.hpp" //############################################################################# /** Ampl Constraint Class */ class ClpConstraintAmpl : public ClpConstraint { public: ///@name Stuff //@{ /** Fills gradient. If Ampl then solution may be NULL, also returns true value of function and offset so we can use x not deltaX in constraint If refresh is false then uses last solution Uses model for scaling Returns non-zero if gradient udefined at current solution */ virtual int gradient(const ClpSimplex * model, const double * solution, double * gradient, double & functionValue , double & offset, bool useScaling = false, bool refresh = true) const ; /// Resize constraint virtual void resize(int newNumberColumns) ; /// Delete columns in constraint virtual void deleteSome(int numberToDelete, const int * which) ; /// Scale constraint virtual void reallyScale(const double * columnScale) ; /** Given a zeroed array sets nonampl columns to 1. Returns number of nonampl columns */ virtual int markNonlinear(char * which) const ; /** Given a zeroed array sets possible nonzero coefficients to 1. Returns number of nonzeros */ virtual int markNonzero(char * which) const; /// Say we have new primal solution - so may need to recompute virtual void newXValues() ; //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpConstraintAmpl(); /// Constructor from ampl ClpConstraintAmpl(int row, void * amplInfo); /** Copy constructor . */ ClpConstraintAmpl(const ClpConstraintAmpl & rhs); /// Assignment operator ClpConstraintAmpl & operator=(const ClpConstraintAmpl& rhs); /// Destructor virtual ~ClpConstraintAmpl (); /// Clone virtual ClpConstraint * clone() const; //@} ///@name Gets and sets //@{ /// Number of coefficients virtual int numberCoefficients() const; /// Columns inline const int * column() const { return column_; } /// Coefficients inline const double * coefficient() const { return coefficient_; } //@} //--------------------------------------------------------------------------- private: ///@name Private member data /// Ampl info void * amplInfo_; /// Column int * column_; /// Coefficients double * coefficient_; /// Number of coefficients in gradient int numberCoefficients_; //@} }; #endif Cbc-2.8.12/src/CbcHeuristicPivotAndFix.cpp0000644000076600007660000004671512131315050016733 0ustar coincoin/* $Id: CbcHeuristicPivotAndFix.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcHeuristicPivotAndFix.hpp" #include "OsiClpSolverInterface.hpp" #include "CoinTime.hpp" //#define FORNOW // Default Constructor CbcHeuristicPivotAndFix::CbcHeuristicPivotAndFix() : CbcHeuristic() { } // Constructor with model - assumed before cuts CbcHeuristicPivotAndFix::CbcHeuristicPivotAndFix(CbcModel & model) : CbcHeuristic(model) { } // Destructor CbcHeuristicPivotAndFix::~CbcHeuristicPivotAndFix () { } // Clone CbcHeuristic * CbcHeuristicPivotAndFix::clone() const { return new CbcHeuristicPivotAndFix(*this); } // Create C++ lines to get to current state void CbcHeuristicPivotAndFix::generateCpp( FILE * fp) { CbcHeuristicPivotAndFix other; fprintf(fp, "0#include \"CbcHeuristicPivotAndFix.hpp\"\n"); fprintf(fp, "3 CbcHeuristicPivotAndFix heuristicPFX(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicPFX"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicPFX);\n"); } // Copy constructor CbcHeuristicPivotAndFix::CbcHeuristicPivotAndFix(const CbcHeuristicPivotAndFix & rhs) : CbcHeuristic(rhs) { } // Assignment operator CbcHeuristicPivotAndFix & CbcHeuristicPivotAndFix::operator=( const CbcHeuristicPivotAndFix & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); } return *this; } // Resets stuff if model changes void CbcHeuristicPivotAndFix::resetModel(CbcModel * /*model*/) { //CbcHeuristic::resetModel(model); } /* Comments needed Returns 1 if solution, 0 if not */ int CbcHeuristicPivotAndFix::solution(double & /*solutionValue*/, double * /*betterSolution*/) { numCouldRun_++; // Todo: Ask JJHF what this for. std::cout << "Entering Pivot-and-Fix Heuristic" << std::endl; #ifdef FORNOW std::cout << "Lucky you! You're in the Pivot-and-Fix Heuristic" << std::endl; // The struct should be moved to member data typedef struct { int numberSolutions; int maximumSolutions; int numberColumns; double ** solution; int * numberUnsatisfied; } clpSolution; double start = CoinCpuTime(); OsiClpSolverInterface * clpSolverOriginal = dynamic_cast (model_->solver()); assert (clpSolverOriginal); OsiClpSolverInterface *clpSolver(clpSolverOriginal); ClpSimplex * simplex = clpSolver->getModelPtr(); // Initialize the structure holding the solutions clpSolution solutions; // Set typeStruct field of ClpTrustedData struct to one. // This tells Clp it's "Mahdi!" ClpTrustedData trustedSolutions; trustedSolutions.typeStruct = 1; trustedSolutions.data = &solutions; solutions.numberSolutions = 0; solutions.maximumSolutions = 0; solutions.numberColumns = simplex->numberColumns(); solutions.solution = NULL; solutions.numberUnsatisfied = NULL; simplex->setTrustedUserPointer(&trustedSolutions); // Solve from all slack to get some points simplex->allSlackBasis(); simplex->primal(); // ------------------------------------------------- // Get the problem information // - get the number of cols and rows int numCols = clpSolver->getNumCols(); int numRows = clpSolver->getNumRows(); // - get the right hand side of the rows const double * rhs = clpSolver->getRightHandSide(); // - find the integer variables bool * varClassInt = new bool[numCols]; int numInt = 0; for (int i = 0; i < numCols; i++) { if (clpSolver->isContinuous(i)) varClassInt[i] = 0; else { varClassInt[i] = 1; numInt++; } } // -Get the rows sense const char * rowSense; rowSense = clpSolver->getRowSense(); // -Get the objective coefficients const double *objCoefficients = clpSolver->getObjCoefficients(); double *originalObjCoeff = new double [numCols]; for (int i = 0; i < numCols; i++) originalObjCoeff[i] = objCoefficients[i]; // -Get the matrix of the problem double ** matrix = new double * [numRows]; for (int i = 0; i < numRows; i++) { matrix[i] = new double[numCols]; for (int j = 0; j < numCols; j++) matrix[i][j] = 0; } const CoinPackedMatrix* matrixByRow = clpSolver->getMatrixByRow(); const double * matrixElements = matrixByRow->getElements(); const int * matrixIndices = matrixByRow->getIndices(); const int * matrixStarts = matrixByRow->getVectorStarts(); for (int j = 0; j < numRows; j++) { for (int i = matrixStarts[j]; i < matrixStarts[j+1]; i++) { matrix[j][matrixIndices[i]] = matrixElements[i]; } } // The newObj is the randomly perturbed constraint used to find new // corner points double * newObj = new double [numCols]; // Set the random seed srand ( time(NULL) + 1); int randNum; // We're going to add a new row to the LP formulation // after finding each new solution. // Adding a new row requires the new elements and the new indices. // The elements are original objective function coefficients. // The indicies are the (dense) columns indices stored in addRowIndex. // The rhs is the value of the new solution stored in solutionValue. int * addRowIndex = new int[numCols]; for (int i = 0; i < numCols; i++) addRowIndex[i] = i; // The number of feasible solutions found by the PF heuristic. // This controls the return code of the solution() method. int numFeasibles = 0; // Shuffle the rows int * index = new int [numRows]; for (int i = 0; i < numRows; i++) index[i] = i; for (int i = 0; i < numRows; i++) { int temp = index[i]; int randNumTemp = i + (rand() % (numRows - i)); index[i] = index[randNumTemp]; index[randNumTemp] = temp; } // In the clpSolution struct, we store a lot of column solutions. // For each perturb objective, we store the solution from each // iteration of the LP solve. // For each perturb objective, we look at the collection of // solutions to do something extremly intelligent :-) // We could (and should..and will :-) wipe out the block of // solutions when we're done with them. But for now, we just move on // and store the next block of solutions for the next (perturbed) // objective. // The variable startIndex tells us where the new block begins. int startIndex = 0; // At most "fixThreshold" number of integer variables can be unsatisfied // for calling smallBranchAndBound(). // The PF Heuristic only fixes fixThreshold number of variables to // their integer values. Not more. Not less. The reason is to give // the smallBB some opportunity to find better solutions. If we fix // everything it might be too many (leading the heuristic to come up // with infeasibility rather than a useful result). // (This is an important paramater. And it is dynamically set.) double fixThreshold; /* if(numInt > 400) fixThreshold = 17*sqrt(numInt); if(numInt<=400 && numInt>100) fixThreshold = 5*sqrt(numInt); if(numInt<=100) fixThreshold = 4*sqrt(numInt); */ // Initialize fixThreshold based on the number of integer // variables if (numInt <= 100) fixThreshold = .35 * numInt; if (numInt > 100 && numInt < 1000) fixThreshold = .85 * numInt; if (numInt >= 1000) fixThreshold = .1 * numInt; // Whenever the dynamic system for changing fixThreshold // kicks in, it changes the parameter by the // fixThresholdChange amount. // (The 25% should be member data and tuned. Another paper!) double fixThresholdChange = 0.25 * fixThreshold; // maxNode is the maximum number of nodes we allow smallBB to // search. It's initialized to 400 and changed dynamically. // The 400 should be member data, if we become virtuous. int maxNode = 400; // We control the decision to change maxNode through the boolean // variable changeMaxNode. The boolean variable is initialized to // true and gets set to false under a condition (and is never true // again.) // It's flipped off and stays off (in the current incarnation of PF) bool changeMaxNode = 1; // The sumReturnCode is used for the dynamic system that sets // fixThreshold and changeMaxNode. // // We track what's happening in sumReturnCode. There are 8 switches. // The first 5 switches corresponds to a return code for smallBB. // // We want to know how many times we consecutively get the same // return code. // // If "good" return codes are happening often enough, we're happy. // // If a "bad" returncodes happen consecutively, we want to // change something. // // The switch 5 is the number of times PF didn't call smallBB // becuase the number of integer variables that took integer values // was less than fixThreshold. // // The swicth 6 was added for a brilliant idea...to be announced // later (another paper!) // // The switch 7 is the one that changes the max node. Read the // code. (Todo: Verbalize the brilliant idea for the masses.) // int sumReturnCode[8]; /* sumReturnCode[0] ~ -1 --> problem too big for smallBB sumReturnCode[1] ~ 0 --> smallBB not finshed and no soln sumReturnCode[2] ~ 1 --> smallBB not finshed and there is a soln sumReturnCode[3] ~ 2 --> smallBB finished and no soln sumReturnCode[4] ~ 3 --> smallBB finished and there is a soln sumReturnCode[5] ~ didn't call smallBranchAndBound too few to fix sumReturnCode[6] ~ didn't call smallBranchAndBound too many unsatisfied sumReturnCode[7] ~ the same as sumReturnCode[1] but becomes zero just if the returnCode is not 0 */ for (int i = 0; i < 8; i++) sumReturnCode[i] = 0; int * colIndex = new int[numCols]; for (int i = 0; i < numCols; i++) colIndex[i] = i; double cutoff = COIN_DBL_MAX; bool didMiniBB; // Main loop for (int i = 0; i < numRows; i++) { // track the number of mini-bb for the dynamic threshold setting didMiniBB = 0; for (int k = startIndex; k < solutions.numberSolutions; k++) //if the point has 0 unsatisfied variables; make sure it is //feasible. Check integer feasiblity and constraints. if (solutions.numberUnsatisfied[k] == 0) { double feasibility = 1; //check integer feasibility for (int icol = 0; icol < numCols; icol++) { double closest = floor(solutions.solution[k][icol] + 0.5); if (varClassInt[icol] && (fabs(solutions.solution[k][icol] - closest) > 1e-6)) { feasibility = 0; break; } } //check if the solution satisfies the constraints for (int irow = 0; irow < numRows; irow++) { double lhs = 0; for (int j = 0; j < numCols; j++) lhs += matrix[irow][j] * solutions.solution[k][j]; if (rowSense[irow] == 'L' && lhs > rhs[irow] + 1e-6) { feasibility = 0; break; } if (rowSense[irow] == 'G' && lhs < rhs[irow] - 1e-6) { feasibility = 0; break; } if (rowSense[irow] == 'E' && (lhs - rhs[irow] > 1e-6 || lhs - rhs[irow] < -1e-6)) { feasibility = 0; break; } } //if feasible, find the objective value and set the cutoff // for the smallBB and add a new constraint to the LP // (and update the best solution found so far for the // return arguments) if (feasibility) { double objectiveValue = 0; for (int j = 0; j < numCols; j++) objectiveValue += solutions.solution[k][j] * originalObjCoeff[j]; cutoff = objectiveValue; clpSolver->addRow(numCols, addRowIndex, originalObjCoeff, -COIN_DBL_MAX, cutoff); // Todo: pick up the best solution in the block (not // the last). solutionValue = objectiveValue; for (int m = 0; m < numCols; m++) betterSolution[m] = solutions.solution[k][m]; numFeasibles++; } } // Go through the block of solution and decide if to call smallBB for (int k = startIndex; k < solutions.numberSolutions; k++) { if (solutions.numberUnsatisfied[k] <= fixThreshold) { // get new copy OsiSolverInterface * newSolver; newSolver = new OsiClpSolverInterface(*clpSolver); newSolver->setObjSense(1); newSolver->setObjective(originalObjCoeff); int numberColumns = newSolver->getNumCols(); int numFixed = 0; // Fix the first fixThreshold number of integer vars // that are satisfied for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) { if (newSolver->isInteger(iColumn)) { double value = solutions.solution[k][iColumn]; double intValue = floor(value + 0.5); if (fabs(value - intValue) < 1.0e-5) { newSolver->setColLower(iColumn, intValue); newSolver->setColUpper(iColumn, intValue); numFixed++; if (numFixed > numInt - fixThreshold) break; } } } COIN_DETAIL_PRINT(printf("numFixed: %d\n", numFixed)); COIN_DETAIL_PRINT(printf("fixThreshold: %f\n", fixThreshold)); COIN_DETAIL_PRINT(printf("numInt: %d\n", numInt)); double *newSolution = new double[numCols]; double newSolutionValue; // Call smallBB on the modified problem int returnCode = smallBranchAndBound(newSolver, maxNode, newSolution, newSolutionValue, cutoff, "mini"); // If smallBB found a solution, update the better // solution and solutionValue (we gave smallBB our // cutoff, so it only finds improving solutions) if (returnCode == 1 || returnCode == 3) { numFeasibles ++; solutionValue = newSolutionValue; for (int m = 0; m < numCols; m++) betterSolution[m] = newSolution[m]; COIN_DETAIL_PRINT(printf("cutoff: %f\n", newSolutionValue)); COIN_DETAIL_PRINT(printf("time: %.2lf\n", CoinCpuTime() - start)); } didMiniBB = 1; COIN_DETAIL_PRINT(printf("returnCode: %d\n", returnCode)); //Update sumReturnCode array for (int iRC = 0; iRC < 6; iRC++) { if (iRC == returnCode + 1) sumReturnCode[iRC]++; else sumReturnCode[iRC] = 0; } if (returnCode != 0) sumReturnCode[7] = 0; else sumReturnCode[7]++; if (returnCode == 1 || returnCode == 3) { cutoff = newSolutionValue; clpSolver->addRow(numCols, addRowIndex, originalObjCoeff, -COIN_DBL_MAX, cutoff); COIN_DETAIL_PRINT(printf("******************\n\n*****************\n")); } break; } } if (!didMiniBB && solutions.numberSolutions - startIndex > 0) { sumReturnCode[5]++; for (int iRC = 0; iRC < 5; iRC++) sumReturnCode[iRC] = 0; } //Change "fixThreshold" if needed // using the data we've recorded in sumReturnCode if (sumReturnCode[1] >= 3) fixThreshold -= fixThresholdChange; if (sumReturnCode[7] >= 3 && changeMaxNode) { maxNode *= 5; changeMaxNode = 0; } if (sumReturnCode[3] >= 3 && fixThreshold < 0.95 * numInt) fixThreshold += fixThresholdChange; if (sumReturnCode[5] >= 4) fixThreshold += fixThresholdChange; if (sumReturnCode[0] > 3) fixThreshold -= fixThresholdChange; startIndex = solutions.numberSolutions; //Check if the maximum iterations limit is reached // rlh: Ask John how this is working with the change to trustedUserPtr. if (solutions.numberSolutions > 20000) break; // The first time in this loop PF solves orig LP. //Generate the random objective function randNum = rand() % 10 + 1; randNum = fmod(randNum, 2); for (int j = 0; j < numCols; j++) { if (randNum == 1) if (fabs(matrix[index[i]][j]) < 1e-6) newObj[j] = 0.1; else newObj[j] = matrix[index[i]][j] * 1.1; else if (fabs(matrix[index[i]][j]) < 1e-6) newObj[j] = -0.1; else newObj[j] = matrix[index[i]][j] * 0.9; } clpSolver->setObjective(newObj); if (rowSense[i] == 'L') clpSolver->setObjSense(-1); else // Todo #1: We don't need to solve the LPs to optimality. // We just need corner points. // There's a problem in stopping Clp that needs to be looked // into. So for now, we solve optimality. clpSolver->setObjSense(1); // simplex->setMaximumIterations(100); clpSolver->getModelPtr()->primal(1); // simplex->setMaximumIterations(100000); #ifdef COIN_DETAIL printf("cutoff: %f\n", cutoff); printf("time: %.2f\n", CoinCpuTime() - start); for (int iRC = 0; iRC < 8; iRC++) printf("%d ", sumReturnCode[iRC]); printf("\nfixThreshold: %f\n", fixThreshold); printf("numInt: %d\n", numInt); printf("\n---------------------------------------------------------------- %d\n", i); #endif //temp: if (i > 3) break; } COIN_DETAIL_PRINT(printf("Best Feasible Found: %f\n", cutoff)); COIN_DETAIL_PRINT(printf("Total time: %.2f\n", CoinCpuTime() - start)); if (numFeasibles == 0) { return 0; } // We found something better std::cout << "See you soon! You're leaving the Pivot-and-Fix Heuristic" << std::endl; std::cout << std::endl; return 1; #endif return 0; } // update model void CbcHeuristicPivotAndFix::setModel(CbcModel * ) { // probably same as resetModel } Cbc-2.8.12/src/ClpAmplObjective.hpp0000644000076600007660000000660112131315050015426 0ustar coincoin/* $Id: ClpAmplObjective.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef ClpAmplObjective_H #define ClpAmplObjective_H #include "ClpObjective.hpp" #include "CoinPackedMatrix.hpp" //############################################################################# /** Ampl Objective Class */ class ClpAmplObjective : public ClpObjective { public: ///@name Stuff //@{ /** Returns gradient. If Ampl then solution may be NULL, also returns an offset (to be added to current one) If refresh is false then uses last solution Uses model for scaling includeLinear 0 - no, 1 as is, 2 as feasible */ virtual double * gradient(const ClpSimplex * model, const double * solution, double & offset, bool refresh, int includeLinear = 2); /// Resize objective /** Returns reduced gradient.Returns an offset (to be added to current one). */ virtual double reducedGradient(ClpSimplex * model, double * region, bool useFeasibleCosts); /** Returns step length which gives minimum of objective for solution + theta * change vector up to maximum theta. arrays are numberColumns+numberRows Also sets current objective, predicted and at maximumTheta */ virtual double stepLength(ClpSimplex * model, const double * solution, const double * change, double maximumTheta, double & currentObj, double & predictedObj, double & thetaObj); /// Return objective value (without any ClpModel offset) (model may be NULL) virtual double objectiveValue(const ClpSimplex * model, const double * solution) const ; virtual void resize(int newNumberColumns) ; /// Delete columns in objective virtual void deleteSome(int numberToDelete, const int * which) ; /// Scale objective virtual void reallyScale(const double * columnScale) ; /** Given a zeroed array sets nonlinear columns to 1. Returns number of nonlinear columns */ virtual int markNonlinear(char * which); /// Say we have new primal solution - so may need to recompute virtual void newXValues() ; //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpAmplObjective(); /// Constructor from ampl info ClpAmplObjective(void * amplInfo); /** Copy constructor . */ ClpAmplObjective(const ClpAmplObjective & rhs); /// Assignment operator ClpAmplObjective & operator=(const ClpAmplObjective& rhs); /// Destructor virtual ~ClpAmplObjective (); /// Clone virtual ClpObjective * clone() const; //@} ///@name Gets and sets //@{ /// Linear objective double * linearObjective() const; //@} //--------------------------------------------------------------------------- private: ///@name Private member data /// Saved offset double offset_; /// Ampl info void * amplObjective_; /// Objective double * objective_; /// Gradient double * gradient_; //@} }; #endif Cbc-2.8.12/src/CbcGenCtlBlk.hpp0000644000076600007660000007015712131315050014467 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenCtlBlk.hpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #ifndef CbcGenCtlBlk_H #define CbcGenCtlBlk_H /* \file CbcGenCtlBlk.hpp \brief Declarations for parameters of the cbc-generic main program. */ #include "CoinParam.hpp" #include "CoinMessageHandler.hpp" #include "CglCutGenerator.hpp" #include "CglProbing.hpp" #include "CglClique.hpp" #include "CglFlowCover.hpp" #include "CglGomory.hpp" #include "CglKnapsackCover.hpp" #include "CglMixedIntegerRounding2.hpp" #include "CglOddHole.hpp" #include "CglRedSplit.hpp" #include "CglTwomir.hpp" #include "CbcModel.hpp" #include "CbcHeuristic.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcHeuristicGreedy.hpp" #include "CbcHeuristicLocal.hpp" #include "CbcTreeLocal.hpp" #include "CbcGenMessages.hpp" /* It turns out that doxygen is not good with anonymous structures. Hence the `struct nameCtl_struct' style used for structured fields in CbcGenCtlBlk. */ /* $Id: CbcGenCtlBlk.hpp 1902 2013-04-10 16:58:16Z stefan $ */ #define CBC_GENERIC_VERSION "00.01.00" class CbcGenCtlBlk ; namespace CbcGenParamUtils { void addCbcGenParams(int &numParams, CoinParamVec ¶mVec, CbcGenCtlBlk *ctlBlk) ; } /* \brief cbc-generic algorithm control class This class defines values and methods used to control the operation of the cbc-generic main program. */ class CbcGenCtlBlk { friend void CbcGenParamUtils::addCbcGenParams(int &numParams, CoinParamVec ¶mVec, CbcGenCtlBlk *ctlBlk) ; public: /*! \name Enumeration types used for cbc-generic control variables */ //@{ /* In order for initialisation to work properly, the order of declaration of the enum constants here must match the order of keyword declaration for the PREPROCESS parameter in CbcGenParamUtils::addCbcGenParams */ /*! \brief Codes to control integer preprocessing - IPPOff: Integer preprocessing is off. - IPPOn: Integer preprocessing is on. - IPPSave: IPPOn, plus preprocessed system will be saved to presolved.mps. - IPPEqual: IPPOn, plus `<=' cliques are converted to `=' cliques. - IPPSOS: IPPOn, plus will create SOS sets (see below). - IPPTrySOS: IPPOn, plus will create SOS sets (see below). - IPPEqualAll: IPPOn, plus turns all valid inequalities into equalities with integer slacks. - IPPStrategy: look to CbcStrategy object for instructions. IPPSOS will create SOS sets if all binary variables (except perhaps one) can be covered by SOS sets with no overlap between sets. IPPTrySOS will allow any number of binary variables to be uncovered. */ typedef enum { IPPOff = 0, IPPOn, IPPSave, IPPEqual, IPPSOS, IPPTrySOS, IPPEqualAll, IPPStrategy } IPPControl ; /* In order for initialisation to work properly, the order of declaration of the enum constants here must match the order of keyword declaration for the various cut and heuristic control parameters in CbcGenParamUtils::addCbcGenParams */ /*! \brief Codes to control the use of cut generators and heuristics - CGOff: the cut generator will not be installed - CGOn: the cut generator will be installed; exactly how often it's activated depends on the settings at installation - CGRoot: the cut generator will be installed with settings that restrict it to activation at the root node only. - CGIfMove: the cut generator will be installed with settings that allow it to remain active only so long as it's generating cuts that tighten the relaxation. - CGForceOn: the cut generator will be installed with settings that force it to be called at every node - CGForceBut: the cut generator will be installed with settings that force it to be called at every node, but more active at root (probing only) - CGMarker: a convenience to mark the end of the codes. The same codes are used for heuristics. */ typedef enum { CGOff, CGOn, CGRoot, CGIfMove, CGForceOn, CGForceBut, CGMarker } CGControl ; /*! \brief Codes to specify the assignment of branching priorities - BPOff: no priorities are passed to cbc - BPCost: a priority vector is constructed based on objective coefficients - BPOrder: a priority vector is constructed based on column order - BPExt: the user has provided a priority vector */ typedef enum { BPOff, BPCost, BPOrder, BPExt } BPControl ; /*! \brief Major status codes for branch-and-cut - BACInvalid: status not yet set - BACNotRun: branch-and-cut has not yet run for the current problem - BACFinish: branch-and-cut has finished normally - BACStop: branch-and-cut has stopped on a limit - BACAbandon: branch-and-cut abandoned the problem - BACUser: branch-and-cut stopped on user signal Consult minorStatus_ for details. These codes are (mostly) set to match the codes used by CbcModel. Additions to CbcModel codes should be reflected here and in translateMajor. */ typedef enum { BACInvalid = -1, BACFinish = 0, BACStop = 1, BACAbandon = 2, BACNotRun, BACUser = 5 } BACMajor ; /*! \brief Minor status codes - BACmInvalid status not yet set - BACmFinish search exhausted the tree; optimal solution found - BACmInfeas problem is infeasible - BACmUbnd problem is unbounded - BACmGap stopped on integrality gap - BACmNodeLimit stopped on node limit - BACmTimeLimit stopped on time limit - BACmSolnLimit stopped on number of solutions limit - BACmUser stopped due to user event - BACmOther nothing else is appropriate It's not possible to make these codes agree with CbcModel. The meaning varies according to context: if the BACWhere code specifies a relaxation, then the minor status reflects the underlying OSI solver. Otherwise, it reflects the integer problem. */ typedef enum { BACmInvalid = -1, BACmFinish = 0, BACmInfeas, BACmUbnd, BACmGap, BACmNodeLimit, BACmTimeLimit, BACmSolnLimit, BACmUser, BACmOther } BACMinor ; /*! \brief Codes to specify where branch-and-cut stopped - BACwNotStarted stopped before we ever got going - BACwBareRoot stopped after initial solve of root relaxation - BACwIPP stopped after integer preprocessing - BACwIPPRelax stopped after initial solve of preprocessed problem - BACwBAC stopped at some point in branch-and-cut */ typedef enum { BACwInvalid = -1, BACwNotStarted = 0, BACwBareRoot, BACwIPP, BACwIPPRelax, BACwBAC } BACWhere ; //@} /*! \name Constructors and destructors */ //@{ /*! \brief Default constructor */ CbcGenCtlBlk() ; /*! \brief Destructor */ ~CbcGenCtlBlk() ; //@} /*! \name Access and Control Functions for Cut Generators and Heuristics \brief Control functions, plus lazy creation functions for cut generators and heuristics cbc-generic avoids creating objects for cut generators and heuristics unless they're actually used. For cut generators, a prototype is created and reused. For heuristics, the default is to create a new object with each call, because the model may have changed. The object is returned through the reference parameter. The return value of the function is the current action state. Cut generator and heuristic objects created by these calls will be deleted with the destruction of the CbcGenCtlBlk object. */ //@{ /*! \brief Get cut depth setting The name is a bit of a misnomer. Essentially, this overrides the `every so many nodes' control with `execute when (depth in tree) mod (cut depth) == 0'. */ inline int getCutDepth() { return cutDepth_ ; } /*! \brief Set cut depth setting. See comments for getCutDepth(). */ inline void setCutDepth(int cutDepth) { cutDepth_ = cutDepth ; } /*1 \brief Get action state for use of integer preprocessing */ inline IPPControl getIPPAction() { return (preProcess_) ; } /*! \brief Set action state for use of integer preprocessing */ inline void setIPPAction(IPPControl action) { preProcess_ = action ; } /*! \brief Obtain a prototype for a probing cut generator. */ CGControl getProbing(CglCutGenerator *&gen) ; /*! \brief Set action state for use of probing cut generator. */ inline void setProbingAction(CGControl action) { probing_.action_ = action ; } /*! \brief Obtain a prototype for a clique cut generator. */ CGControl getClique(CglCutGenerator *&gen) ; /*! \brief Set action state for use of clique cut generator. */ inline void setCliqueAction(CGControl action) { clique_.action_ = action ; } /*! \brief Obtain a prototype for a flow cover cut generator. */ CGControl getFlow(CglCutGenerator *&gen) ; /*! \brief Set action state for use of flow cover cut generator. */ inline void setFlowAction(CGControl action) { flow_.action_ = action ; } /*! \brief Obtain a prototype for a Gomory cut generator. */ CGControl getGomory(CglCutGenerator *&gen) ; /*! \brief Set action state for use of Gomory cut generator. */ inline void setGomoryAction(CGControl action) { gomory_.action_ = action ; } /*! \brief Obtain a prototype for a knapsack cover cut generator. */ CGControl getKnapsack(CglCutGenerator *&gen) ; /*! \brief Set action state for use of knapsack cut generator. */ inline void setKnapsackAction(CGControl action) { knapsack_.action_ = action ; } /* \brief Obtain a prototype for a lift-and-project cut generator. CGControl getLandP(CglCutGenerator *&gen) ; \brief Set action state for use of lift-and-project cut generator. inline void setLandPAction(CGControl action) { landp_.action_ = action ; } */ /*! \brief Obtain a prototype for a mixed integer rounding (MIR) cut generator. */ CGControl getMir(CglCutGenerator *&gen) ; /*! \brief Set action state for use of MIR cut generator. */ inline void setMirAction(CGControl action) { mir_.action_ = action ; } /*! \brief Obtain a prototype for a reduce and split cut generator. */ CGControl getRedSplit(CglCutGenerator *&gen) ; /*! \brief Set action state for use of reduce and split cut generator. */ inline void setRedSplitAction(CGControl action) { redSplit_.action_ = action ; } /*! \brief Obtain a prototype for a 2-MIR cut generator. */ CGControl getTwomir(CglCutGenerator *&gen) ; /*! \brief Set action state for use of 2-MIR cut generator. */ inline void setTwomirAction(CGControl action) { twomir_.action_ = action ; } /*! \brief Obtain a feasibility pump heuristic. By default, any existing object is deleted and a new object is created and loaded with \c model. Set alwaysCreate = false to return an existing object if one exists. */ CGControl getFPump(CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate = true) ; /*! \brief Set action state for use of feasibility pump heuristic. */ inline void setFPumpAction(CGControl action) { fpump_.action_ = action ; } /*! \brief Obtain a local search/combine heuristic. By default, any existing object is deleted and a new object is created and loaded with \c model. Set alwaysCreate = false to return an existing object if one exists. */ CGControl getCombine(CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate = true) ; /*! \brief Set action state for use of local search/combine heuristic. */ inline void setCombineAction(CGControl action) { combine_.action_ = action ; } /*! \brief Obtain a greedy cover heuristic. By default, any existing object is deleted and a new object is created and loaded with \c model. Set alwaysCreate = false to return an existing object if one exists. */ CGControl getGreedyCover(CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate = true) ; /*! \brief Set action state for use of greedy cover heuristic. */ inline void setGreedyCoverAction(CGControl action) { greedyCover_.action_ = action ; } /*! \brief Obtain a greedy equality heuristic. By default, any existing object is deleted and a new object is created and loaded with \c model. Set alwaysCreate = false to return an existing object if one exists. */ CGControl getGreedyEquality(CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate = true) ; /*! \brief Set action state for use of greedy equality heuristic. */ inline void setGreedyEqualityAction(CGControl action) { greedyEquality_.action_ = action ; } /*! \brief Obtain a simple rounding heuristic. By default, any existing object is deleted and a new object is created and loaded with \c model. Set alwaysCreate = false to return an existing object if one exists. */ CGControl getRounding(CbcHeuristic *&gen, CbcModel *model, bool alwaysCreate = true) ; /*! \brief Set action state for use of simple rounding heuristic. */ inline void setRoundingAction(CGControl action) { rounding_.action_ = action ; } /*! \brief Obtain a local search tree object By default, any existing object is deleted and a new object is created and loaded with \c model. Set alwaysCreate = false to return an existing object if one exists. */ CGControl getTreeLocal(CbcTreeLocal *&localTree, CbcModel *model, bool alwaysCreate = true) ; /*! \brief Set action state for use of local tree. */ inline void setTreeLocalAction(CGControl action) { localTree_.action_ = action ; } //@} /*! \name Status Functions \brief Convenience routines for status codes. */ //@{ /*! \brief Set the result of branch-and-cut search */ inline void setBaBStatus(BACMajor majorStatus, BACMinor minorStatus, BACWhere where, bool haveAnswer, OsiSolverInterface *answerSolver) { bab_.majorStatus_ = majorStatus ; bab_.minorStatus_ = minorStatus ; bab_.where_ = where ; bab_.haveAnswer_ = haveAnswer ; bab_.answerSolver_ = answerSolver ; } /*! \brief Set the result of branch-and-cut search This version will extract the necessary information from the CbcModel object and set appropriate status based on the value passed for where. */ void setBaBStatus(const CbcModel *model, BACWhere where, bool haveAnswer = false, OsiSolverInterface *answerSolver = 0) ; /*! \brief Translate CbcModel major status to #BACMajor See the #BACMajor enum for details. */ BACMajor translateMajor(int status) ; /*!\brief Translate CbcModel minor status to #BACMinor See the #BACMinor enum for details. */ BACMinor translateMinor(int status) ; /*!\brief Translate OsiSolverInterface status to #BACMinor See the #BACMinor enum for details. Optimal, infeasible, and unbounded get their own codes; everything else maps to BACmOther. */ BACMinor translateMinor(const OsiSolverInterface *osi) ; /*! \brief Print the status block */ void printBaBStatus() ; //@} /*! \name Messages and statistics */ //@{ /*! \brief Print a message Uses the current message handler and messages. */ CoinMessageHandler &message(CbcGenMsgCode inID) ; /*! \brief Supply a new message handler. Replaces the current message handler. The current handler is destroyed if ourMsgHandler_ is true, and the call will set ourMsgHandler_ = true. */ void passInMessageHandler(CoinMessageHandler *handler) ; /*! \brief Return a pointer to the message handler */ inline CoinMessageHandler *messageHandler() const { return msgHandler_ ; } /*! \brief Set up messages in the specified language. Building a set of messages in a given language implies rebuilding the whole set of messages, for reasons explained in the body of the code. Hence there's no separate setLanguage routine. Use this routine for the initial setup of messages and any subsequent change in language. Note that the constructor gives you a message handler by default, but \e not messages. You need to call setMessages explicitly. The default value specified here for lang effectively sets the default language. */ void setMessages(CoinMessages::Language lang = CoinMessages::us_en) ; /*! \brief Set log level */ inline void setLogLevel(int lvl) { logLvl_ = lvl ; if (msgHandler_) msgHandler_->setLogLevel(lvl) ; } /*! \brief Get log level */ inline int logLevel() const { return (logLvl_) ; } /*! \brief When greater than 0, integer presolve gives more information and branch-and-cut provides statistics. */ int printOpt_ ; //@} /*! \name Parameter parsing and input/output. */ //@{ /*! \brief cbc-generic version */ std::string version_ ; /*! \brief Default directory prefix */ std::string dfltDirectory_ ; /*! \brief Last MPS input file */ std::string lastMpsIn_ ; /*! \brief Allow/disallow errors when importing a model */ bool allowImportErrors_ ; /*! \brief Last solution output file */ std::string lastSolnOut_ ; /*! \brief Solution printing mode Controls the amount of information printed when printing a solution. Coding is set by the keyword declarations for the printingOptions command. */ int printMode_ ; /*! \brief Print mask Used to specify row/column names to be printed. Not implemented as of 060920. */ std::string printMask_ ; /*! \brief The parameter vector */ CoinParamVec *paramVec_ ; /*! \brief Start and end of cbc-generic parameters in parameter vector */ struct genParamsInfo_struct { int first_ ; int last_ ; } genParams_ ; /*! \brief Start and end of CbcModel parameters in parameter vector */ struct cbcParamsInfo_struct { int first_ ; int last_ ; } cbcParams_ ; /*! \brief Start and end of OsiSolverInterface parameters in parameter vector */ struct osiParamsInfo_struct { int first_ ; int last_ ; } osiParams_ ; /*! \brief Verbosity level for help messages. Interpretation is bitwise: - (0): short help - (1): long help - (2): unused (for compatibility with cbc; indicates AMPL) - (3): show parameters with display = false. */ int verbose_ ; /*! \brief Number of parameters processed */ int paramsProcessed_ ; /*! \brief Record of parameters changed by user command */ std::vector setByUser_ ; /*! \brief False if the user has made nontrivial modifications to the default control settings. Initially true. Specifying DJFIX, TIGHTENFACTOR, or any cut or heuristic parameter will set this to false. */ bool defaultSettings_ ; /*! \brief Control debug file creation At the conclusion of branch-and-cut, dump the full solution in a binary format to debug.file in the current directory. When set to "createAfterPre", the solution is dumped before integer presolve transforms are removed. When set to "create", the solution is dumped after integer presolve transforms are backed out. */ std::string debugCreate_ ; /*! \brief Last debug input file The file is expected to be in a binary format understood by activateRowCutDebugger. */ std::string debugFile_ ; /*! \brief Array of primal variable values for debugging Used to provide a known optimal solution to activateRowCutDebugger(). */ struct debugSolInfo_struct { int numCols_ ; double *values_ ; } debugSol_ ; //@} /* \name Timing */ //@{ /*! \brief Total elapsed time for this run. */ double totalTime_ ; //@} /*! \name Models of various flavours */ //@{ /*! \brief The reference CbcModel object. This is the CbcModel created when cbc-generic boots up. It holds the default solver with the current constraint system. CbcCbcParam parameters are applied here, and CbcOsiParam parameters are applied to the solver. Major modifications for branch-and-cut (integer preprocessing, installation of heuristics and cut generators) are performed on a clone. The solution is transferred back into this object. */ CbcModel *model_ ; /*! \brief The current default LP solver This is a pointer to a reference copy. If you want the solver associated with #model_, ask for it directly. */ OsiSolverInterface *dfltSolver_ ; /*! \brief True if we have a valid model loaded, false otherwise. */ bool goodModel_ ; /*! \brief State of branch-and-cut Major and minor status codes, and a solver holding the answer, assuming we have a valid answer. See the documentation with the BACMajor, BACMinor, and BACWhere enums for the meaning of the codes. */ struct babState_struct { BACMajor majorStatus_ ; BACMinor minorStatus_ ; BACWhere where_ ; bool haveAnswer_ ; OsiSolverInterface *answerSolver_ ; } bab_ ; //@} /*! \name Various algorithm control variables and settings */ //@{ /*! \brief Control use of reduced cost fixing prior to B&C This heuristic fixes variables whose reduced cost for the root relaxtion exceeds the specified threshold. This is purely a heuristic, performed before there's any incumbent solution. It may well fix variables at the wrong bound! */ struct djFixCtl_struct { bool action_ ; double threshold_ ; } djFix_ ; /*! \brief Control the assignment of branching priorities to integer variables. */ BPControl priorityAction_ ; //@} /*! \name Branching Method Control \brief Usage control and prototypes for branching methods. Looking to the future, this covers only OsiChoose methods. */ //@{ /*! \brief Control variables for a strong branching method. Consult OsiChooseVariable and CbcModel for details. An artifact of the changeover from CbcObjects to OsiObjects is that the number of uses before pseudo costs are trusted (numBeforeTrust_) and the number of variables evaluated with strong branching (numStrong_) are parameters of CbcModel. */ struct chooseStrongCtl_struct { int numBeforeTrust_ ; int numStrong_ ; int shadowPriceMode_ ; } chooseStrong_ ; //@} private: /*! \name Cut Generator and Heuristic Control \brief Usage control and prototypes for cut generators and heuristics. */ //@{ /*! \brief Control integer preprocessing. */ IPPControl preProcess_ ; /*! \brief Control cut generator activity Generators that are active in the tree will be activated when (depth) mod (cutDepth) == 0. */ int cutDepth_ ; /*! \brief Control variable and prototype for probing cut generator */ struct probingCtl_struct { CGControl action_ ; CglProbing *proto_ ; bool usingObjective_ ; int maxPass_ ; int maxPassRoot_ ; int maxProbe_ ; int maxProbeRoot_ ; int maxLook_ ; int maxLookRoot_ ; int maxElements_ ; int rowCuts_ ; } probing_ ; /*! \brief Control variable and prototype for clique cut generator */ struct cliqueCtl_struct { CGControl action_ ; CglClique *proto_ ; bool starCliqueReport_ ; bool rowCliqueReport_ ; double minViolation_ ; } clique_ ; /*! \brief Control variable and prototype for flow cover cut generator */ struct flowCtl_struct { CGControl action_ ; CglFlowCover *proto_ ; } flow_ ; /*! \brief Control variable and prototype for Gomory cut generator */ struct gomoryCtl_struct { CGControl action_ ; CglGomory *proto_ ; int limit_ ; int limitAtRoot_ ; } gomory_ ; /* \brief Control variable and prototype for lift-and-project cut generator struct landpCtl_struct { CGControl action_ ; CglLandP *proto_ ; } landp_ ; */ /*! \brief Control variable and prototype for knapsack cover cut generator */ struct knapsackCtl_struct { CGControl action_ ; CglKnapsackCover *proto_ ; } knapsack_ ; /*! \brief Control variable and prototype for MIR cut generator */ struct mirCtl_struct { CGControl action_ ; CglMixedIntegerRounding2 *proto_ ; } mir_ ; /*! \brief Control variable and prototype for odd hole cut generator */ struct oddHoleCtl_struct { CGControl action_ ; CglOddHole *proto_ ; } oddHole_ ; /*! \brief Control variable and prototype for reduce-and-split cut generator */ struct redSplitCtl_struct { CGControl action_ ; CglRedSplit *proto_ ; } redSplit_ ; /*! \brief Control variable and prototype for Two-MIR cut generator */ struct twomirCtl_struct { CGControl action_ ; CglTwomir *proto_ ; int maxElements_ ; } twomir_ ; /*! \brief Control variable and prototype for feasibility pump heuristic */ struct fpumpCtl_struct { CGControl action_ ; CbcHeuristicFPump *proto_ ; int iters_ ; } fpump_ ; /*! \brief Control variable and prototype for combine heuristic */ struct combineCtl_struct { CGControl action_ ; CbcHeuristicLocal *proto_ ; int trySwap_ ; } combine_ ; /*! \brief Control variable and prototype for greedy cover heuristic */ struct greedyCoverCtl_struct { CGControl action_ ; CbcHeuristicGreedyCover *proto_ ; } greedyCover_ ; /*! \brief Control variable and prototype for greedy equality heuristic */ struct greedyEqualityCtl_struct { CGControl action_ ; CbcHeuristicGreedyEquality *proto_ ; } greedyEquality_ ; /*! \brief Control variable and prototype for simple rounding heuristic */ struct roundingCtl_struct { CGControl action_ ; CbcRounding *proto_ ; } rounding_ ; /*! \brief Control variables for local tree This is a bit different --- getTreeLocal() takes a CbcModel as a parameter and installs a local tree object. But we can keep the parameters here and hide the details. Consult CbcTreeLocal.hpp for details. */ struct localTreeCtl_struct { CGControl action_ ; CbcTreeLocal *proto_ ; double *soln_ ; int range_ ; int typeCuts_ ; int maxDiverge_ ; int timeLimit_ ; int nodeLimit_ ; bool refine_ ; } localTree_ ; //@} /*! \name Messages and statistics (private) \brief Data and objects related to messages and statistics that should be protected from direct manipulation. */ //@{ /*! \brief Message handler. */ CoinMessageHandler *msgHandler_ ; /*! \brief Ownership of message handler. If true, the control block owns the message handler and it will be destroyed with the control block. If false, the client is responsible for the message handler. */ bool ourMsgHandler_ ; /*! \brief The current language */ CoinMessages::Language cur_lang_ ; /*! \brief The current set of messages. */ CoinMessages *msgs_ ; /*! \brief The current log level */ int logLvl_ ; //@} } ; #endif Cbc-2.8.12/src/CbcFeasibilityBase.hpp0000644000076600007660000000275311510742604015727 0ustar coincoin/* $Id: CbcFeasibilityBase.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcFeasibilityBase_H #define CbcFeasibilityBase_H //############################################################################# /* There are cases where the user wants to control how CBC sees the problems feasibility. The user may want to examine the problem and say : a) The default looks OK b) Pretend this problem is Integer feasible c) Pretend this problem is infeasible even though it looks feasible This simple class allows user to do that. */ class CbcModel; class CbcFeasibilityBase { public: // Default Constructor CbcFeasibilityBase () {} /** On input mode: 0 - called after a solve but before any cuts -1 - called after strong branching Returns : 0 - no opinion -1 pretend infeasible 1 pretend integer solution */ virtual int feasible(CbcModel * , int ) { return 0; } virtual ~CbcFeasibilityBase() {} // Copy constructor CbcFeasibilityBase ( const CbcFeasibilityBase & ) {} // Assignment operator CbcFeasibilityBase & operator=( const CbcFeasibilityBase& ) { return *this; } /// Clone virtual CbcFeasibilityBase * clone() const { return new CbcFeasibilityBase(*this); } }; #endif Cbc-2.8.12/src/CbcSolverAnalyze.hpp0000644000076600007660000000120312131315050015442 0ustar coincoin/* $Id: CbcSolverAnalyze.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /*! \file CbcSolverAnalyze.hpp \brief Look to see if a constraint is all-integer (variables & coeffs), or could be all integer. */ #ifndef CbcSolverAnalyze_H #define CbcSolverAnalyze_H int * analyze(OsiClpSolverInterface * solverMod, int & numberChanged, double & increment, bool changeInt, CoinMessageHandler * generalMessageHandler, bool noPrinting); #endif Cbc-2.8.12/src/Cbc_ampl.h0000644000076600007660000000323711510742604013416 0ustar coincoin/* $Id: Cbc_ampl.h 1573 2011-01-05 01:12:36Z lou $ */ /* Copyright (C) 2006, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). */ #ifndef AmplInterface_H #define AmplInterface_H typedef struct { int numberRows; int numberColumns; int numberBinary; int numberIntegers; /* non binary */ int numberSos; int numberElements; int numberArguments; int problemStatus; double direction; double offset; double objValue; double * objective; double * rowLower; double * rowUpper; double * columnLower; double * columnUpper; int * starts; int * rows; double * elements; double * primalSolution; double * dualSolution; int * columnStatus; int * rowStatus; int * priorities; int * branchDirection; double * pseudoDown; double * pseudoUp; char * sosType; int * sosPriority; int * sosStart; int * sosIndices; double * sosReference; int * cut; int * special; char ** arguments; char buffer[300]; int logLevel; int nonLinear; } ampl_info; #ifdef __cplusplus extern "C" { #endif /* return nonzero if bad */ int readAmpl(ampl_info * info, int argc, char ** argv, void ** coinModel); /* frees some input arrays */ void freeArrays1(ampl_info * info); /* frees rest */ void freeArrays2(ampl_info * info); /* frees fake arguments */ void freeArgs(ampl_info * info); /* writes ampl stuff */ void writeAmpl(ampl_info * info); /* objective precision */ int ampl_obj_prec(); #ifdef __cplusplus } #endif #endif Cbc-2.8.12/src/CbcBranchBase.hpp0000644000076600007660000000460011510742604014651 0ustar coincoin/* $Id: CbcBranchBase.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcBranchBase_H #define CbcBranchBase_H #include #include #include "OsiBranchingObject.hpp" enum CbcRangeCompare { CbcRangeSame, CbcRangeDisjoint, CbcRangeSubset, CbcRangeSuperset, CbcRangeOverlap }; #include "CbcObject.hpp" #include "CbcBranchingObject.hpp" #include "CbcBranchDecision.hpp" #include "CbcConsequence.hpp" #include "CbcObjectUpdateData.hpp" //############################################################################## /** Compare two ranges. The two bounds arrays are both of size two and describe closed intervals. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the content of thisBd with the intersection of the ranges. */ static inline CbcRangeCompare CbcCompareRanges(double* thisBd, const double* otherBd, const bool replaceIfOverlap) { const double lbDiff = thisBd[0] - otherBd[0]; if (lbDiff < 0) { // lb of this < lb of other if (thisBd[1] >= otherBd[1]) { // ub of this >= ub of other return CbcRangeSuperset; } else if (thisBd[1] < otherBd[0]) { return CbcRangeDisjoint; } else { // overlap if (replaceIfOverlap) { thisBd[0] = otherBd[0]; } return CbcRangeOverlap; } } else if (lbDiff > 0) { // lb of this > lb of other if (thisBd[1] <= otherBd[1]) { // ub of this <= ub of other return CbcRangeSubset; } else if (thisBd[0] > otherBd[1]) { return CbcRangeDisjoint; } else { // overlap if (replaceIfOverlap) { thisBd[1] = otherBd[1]; } return CbcRangeOverlap; } } else { // lb of this == lb of other if (thisBd[1] == otherBd[1]) { return CbcRangeSame; } return thisBd[1] < otherBd[1] ? CbcRangeSubset : CbcRangeSuperset; } return CbcRangeSame; // fake return } //############################################################################# #endif Cbc-2.8.12/src/CbcHeuristicGreedy.hpp0000644000076600007660000002113611513124702015757 0ustar coincoin/* $Id: CbcHeuristicGreedy.hpp 1585 2011-01-11 19:04:34Z forrest $ */ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicGreedy_H #define CbcHeuristicGreedy_H #include "CbcHeuristic.hpp" /** Greedy heuristic classes */ class CbcHeuristicGreedyCover : public CbcHeuristic { public: // Default Constructor CbcHeuristicGreedyCover (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicGreedyCover (CbcModel & model); // Copy constructor CbcHeuristicGreedyCover ( const CbcHeuristicGreedyCover &); // Destructor ~CbcHeuristicGreedyCover (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicGreedyCover & operator=(const CbcHeuristicGreedyCover& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) We leave all variables which are at one at this node of the tree to that value and will initially set all others to zero. We then sort all variables in order of their cost divided by the number of entries in rows which are not yet covered. We randomize that value a bit so that ties will be broken in different ways on different runs of the heuristic. We then choose the best one and set it to one and repeat the exercise. */ virtual int solution(double & objectiveValue, double * newSolution); /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) virtual void validate() ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /* Algorithm 0 - use current upper bounds 1 - use original upper bounds If 10 added perturb ratios more if 100 added round up all >=0.5 */ inline int algorithm() const { return algorithm_; } inline void setAlgorithm(int value) { algorithm_ = value; } // Only do this many times inline int numberTimes() const { return numberTimes_; } inline void setNumberTimes(int value) { numberTimes_ = value; } protected: /// Guts of constructor from a CbcModel void gutsOfConstructor(CbcModel * model); // Data // Original matrix by column CoinPackedMatrix matrix_; // original number of rows int originalNumberRows_; /* Algorithm 0 - use current upper bounds 1 - use original upper bounds If 10 added perturb ratios more */ int algorithm_; /// Do this many times int numberTimes_; }; class CbcHeuristicGreedyEquality : public CbcHeuristic { public: // Default Constructor CbcHeuristicGreedyEquality (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicGreedyEquality (CbcModel & model); // Copy constructor CbcHeuristicGreedyEquality ( const CbcHeuristicGreedyEquality &); // Destructor ~CbcHeuristicGreedyEquality (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicGreedyEquality & operator=(const CbcHeuristicGreedyEquality& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) We leave all variables which are at one at this node of the tree to that value and will initially set all others to zero. We then sort all variables in order of their cost divided by the number of entries in rows which are not yet covered. We randomize that value a bit so that ties will be broken in different ways on different runs of the heuristic. We then choose the best one and set it to one and repeat the exercise. */ virtual int solution(double & objectiveValue, double * newSolution); /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) virtual void validate() ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /* Algorithm 0 - use current upper bounds 1 - use original upper bounds If 10 added perturb ratios more if 100 added round up all >=0.5 */ inline int algorithm() const { return algorithm_; } inline void setAlgorithm(int value) { algorithm_ = value; } // Fraction of rhs to cover before branch and cut inline void setFraction(double value) { fraction_ = value; } inline double fraction() const { return fraction_; } // Only do this many times inline int numberTimes() const { return numberTimes_; } inline void setNumberTimes(int value) { numberTimes_ = value; } protected: /// Guts of constructor from a CbcModel void gutsOfConstructor(CbcModel * model); // Data // Original matrix by column CoinPackedMatrix matrix_; // Fraction of rhs to cover before branch and cut double fraction_; // original number of rows int originalNumberRows_; /* Algorithm 0 - use current upper bounds 1 - use original upper bounds If 10 added perturb ratios more */ int algorithm_; /// Do this many times int numberTimes_; }; /** Greedy heuristic for SOS and L rows (and positive elements) */ class CbcHeuristicGreedySOS : public CbcHeuristic { public: // Default Constructor CbcHeuristicGreedySOS (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicGreedySOS (CbcModel & model); // Copy constructor CbcHeuristicGreedySOS ( const CbcHeuristicGreedySOS &); // Destructor ~CbcHeuristicGreedySOS (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicGreedySOS & operator=(const CbcHeuristicGreedySOS& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) We leave all variables which are at one at this node of the tree to that value and will initially set all others to zero. We then sort all variables in order of their cost divided by the number of entries in rows which are not yet covered. We randomize that value a bit so that ties will be broken in different ways on different runs of the heuristic. We then choose the best one and set it to one and repeat the exercise. */ virtual int solution(double & objectiveValue, double * newSolution); /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) virtual void validate() ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /* Algorithm Bits 1 bit - use current model, otherwise original 2 - use current solution as starting point, otherwise pure greedy 4 - as 2 but use merit not merit/size 8 - use duals to modify greedy 16 - use duals on GUB/SOS in special way */ inline int algorithm() const { return algorithm_; } inline void setAlgorithm(int value) { algorithm_ = value; } // Only do this many times inline int numberTimes() const { return numberTimes_; } inline void setNumberTimes(int value) { numberTimes_ = value; } protected: /// Guts of constructor from a CbcModel void gutsOfConstructor(CbcModel * model); // Data // Original RHS - if -1.0 then SOS otherwise <= value double * originalRhs_; // Original matrix by column CoinPackedMatrix matrix_; // original number of rows int originalNumberRows_; /* Algorithm */ int algorithm_; /// Do this many times int numberTimes_; }; #endif Cbc-2.8.12/src/CbcStatistics.cpp0000644000076600007660000001033711510742604015012 0ustar coincoin/* $Id: CbcStatistics.cpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include "CbcStatistics.hpp" CbcStatistics & CbcStatistics::operator=(const CbcStatistics & rhs) { if (this != &rhs) { value_ = rhs.value_; startingObjective_ = rhs.startingObjective_; endingObjective_ = rhs.endingObjective_; id_ = rhs.id_; parentId_ = rhs.parentId_; way_ = rhs.way_; sequence_ = rhs.sequence_; depth_ = rhs.depth_; startingInfeasibility_ = rhs.startingInfeasibility_; endingInfeasibility_ = rhs.endingInfeasibility_; numberIterations_ = rhs.numberIterations_; } return *this; } CbcStatistics::CbcStatistics () : value_ ( 0.0), startingObjective_(0.0), endingObjective_(COIN_DBL_MAX), id_(-1), parentId_(-1), way_ ( 0), sequence_(-1), depth_(0), startingInfeasibility_(-1), endingInfeasibility_(0), numberIterations_(0) { } // First or second branch CbcStatistics::CbcStatistics(CbcNode * node, CbcModel * model) : endingObjective_(COIN_DBL_MAX), endingInfeasibility_(0), numberIterations_(0) { CbcNodeInfo * nodeInfo = node->nodeInfo(); CbcNodeInfo * parent = nodeInfo->parent(); int numberBranches = nodeInfo->numberBranchesLeft(); const CbcBranchingObject * branch = dynamic_cast (node->branchingObject()); const OsiTwoWayBranchingObject * branch2 = dynamic_cast (node->branchingObject()); startingObjective_ = node->objectiveValue(); way_ = node->way(); depth_ = node->depth(); startingInfeasibility_ = node->numberUnsatisfied(); if (branch) { sequence_ = branch->variable(); value_ = branch->value(); } else { const OsiSimpleInteger * obj = dynamic_cast(branch2->originalObject()); assert (obj); sequence_ = obj->columnNumber(); value_ = branch2->value(); } if (parent) parentId_ = parent->nodeNumber(); else parentId_ = -1; if (numberBranches == 2) { id_ = nodeInfo->nodeNumber(); } else { way_ *= 10; id_ = model->getNodeCount2(); } } CbcStatistics::CbcStatistics(const CbcStatistics & rhs) : value_ ( rhs.value_), startingObjective_(rhs.startingObjective_), endingObjective_(rhs.endingObjective_), id_(rhs.id_), parentId_(rhs.parentId_), way_ ( rhs.way_), sequence_(rhs.sequence_), depth_(rhs.depth_), startingInfeasibility_(rhs.startingInfeasibility_), endingInfeasibility_(rhs.endingInfeasibility_), numberIterations_(rhs.numberIterations_) { } CbcStatistics::~CbcStatistics () { } // Update at end of branch void CbcStatistics::endOfBranch(int numberIterations, double objectiveValue) { numberIterations_ = numberIterations; endingObjective_ = objectiveValue; } // Update number of infeasibilities void CbcStatistics::updateInfeasibility(int numberInfeasibilities) { endingInfeasibility_ = numberInfeasibilities; } // Branch found to be infeasible by chooseBranch void CbcStatistics::sayInfeasible() { endingObjective_ = COIN_DBL_MAX; } // Just prints void CbcStatistics::print(const int * sequenceLookup) const { int sequence = -1; if (sequence_ >= 0) sequence = sequenceLookup ? sequenceLookup[sequence_] : sequence_; printf("%6d %6d %5d %6d %7.3f %s %s %13.7g (%5d) -> ", id_, parentId_, depth_, sequence, value_, abs(way_) == 1 ? " left" : "right", way_ < 0 ? "down" : " up ", startingObjective_, startingInfeasibility_); if (endingObjective_ != COIN_DBL_MAX) if (endingInfeasibility_) printf("%13.7g (%5d)\n", endingObjective_, endingInfeasibility_); else printf("%13.7g ** Solution\n", endingObjective_); else printf("cutoff\n"); } Cbc-2.8.12/src/CbcBranchActual.hpp0000644000076600007660000000133611510742604015213 0ustar coincoin/* $Id: CbcBranchActual.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcBranchActual_H #define CbcBranchActual_H #include "CbcBranchBase.hpp" #include "CoinPackedMatrix.hpp" #include "CbcClique.hpp" #include "CbcSOS.hpp" #include "CbcSimpleInteger.hpp" #include "CbcNWay.hpp" #include "CbcSimpleIntegerPseudoCost.hpp" #include "CbcBranchDefaultDecision.hpp" #include "CbcFollowOn.hpp" #include "CbcFixVariable.hpp" #include "CbcDummyBranchingObject.hpp" #include "CbcGeneral.hpp" #include "CbcGeneralDepth.hpp" #include "CbcSubProblem.hpp" #endif Cbc-2.8.12/src/CbcSimpleIntegerPseudoCost.hpp0000644000076600007660000000646412131315050017442 0ustar coincoin// $Id: CbcSimpleIntegerPseudoCost.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #ifndef CbcSimpleIntegerPseudoCost_H #define CbcSimpleIntegerPseudoCost_H #include "CbcSimpleInteger.hpp" /// Define a single integer class but with pseudo costs class CbcSimpleIntegerPseudoCost : public CbcSimpleInteger { public: // Default Constructor CbcSimpleIntegerPseudoCost (); // Useful constructor - passed model index CbcSimpleIntegerPseudoCost (CbcModel * model, int iColumn, double breakEven = 0.5); // Useful constructor - passed and model index and pseudo costs CbcSimpleIntegerPseudoCost (CbcModel * model, int iColumn, double downPseudoCost, double upPseudoCost); // Useful constructor - passed and model index and pseudo costs CbcSimpleIntegerPseudoCost (CbcModel * model, int dummy, int iColumn, double downPseudoCost, double upPseudoCost); // Copy constructor CbcSimpleIntegerPseudoCost ( const CbcSimpleIntegerPseudoCost &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcSimpleIntegerPseudoCost & operator=( const CbcSimpleIntegerPseudoCost& rhs); // Destructor virtual ~CbcSimpleIntegerPseudoCost (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Down pseudo cost inline double downPseudoCost() const { return downPseudoCost_; } /// Set down pseudo cost inline void setDownPseudoCost(double value) { downPseudoCost_ = value; } /// Up pseudo cost inline double upPseudoCost() const { return upPseudoCost_; } /// Set up pseudo cost inline void setUpPseudoCost(double value) { upPseudoCost_ = value; } /// Up down separator inline double upDownSeparator() const { return upDownSeparator_; } /// Set up down separator inline void setUpDownSeparator(double value) { upDownSeparator_ = value; } /// Return "up" estimate virtual double upEstimate() const; /// Return "down" estimate (default 1.0e-5) virtual double downEstimate() const; /// method - see below for details inline int method() const { return method_; } /// Set method inline void setMethod(int value) { method_ = value; } protected: /// data /// Down pseudo cost double downPseudoCost_; /// Up pseudo cost double upPseudoCost_; /** Up/down separator If >0.0 then do first branch up if value-floor(value) >= this value */ double upDownSeparator_; /** Method - 0 - normal - return min (up,down) 1 - if before any solution return CoinMax(up,down) 2 - if before branched solution return CoinMax(up,down) 3 - always return CoinMax(up,down) */ int method_; }; #endif Cbc-2.8.12/src/CbcGeneral.hpp0000644000076600007660000000302112131315050014221 0ustar coincoin// $Id: CbcGeneral.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #ifndef CbcGeneral_H #define CbcGeneral_H #include "CbcBranchBase.hpp" /** Define a catch all class. This will create a list of subproblems */ class CbcGeneral : public CbcObject { public: // Default Constructor CbcGeneral (); /** Useful constructor Just needs to point to model. */ CbcGeneral (CbcModel * model); // Copy constructor CbcGeneral ( const CbcGeneral &); /// Clone virtual CbcObject * clone() const = 0; // Assignment operator CbcGeneral & operator=( const CbcGeneral& rhs); // Destructor ~CbcGeneral (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /// This looks at solution and sets bounds to contain solution virtual void feasibleRegion() = 0; /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Redoes data when sequence numbers change virtual void redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns) = 0; protected: /// data }; #endif Cbc-2.8.12/src/CbcFathom.cpp0000644000076600007660000000522411510742604014075 0ustar coincoin/* $Id: CbcFathom.cpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #endif #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcFathom.hpp" // Default Constructor CbcFathom::CbcFathom() : model_(NULL), possible_(false) { } // Constructor from model CbcFathom::CbcFathom(CbcModel & model) : model_(&model), possible_(false) { } // Resets stuff if model changes void CbcFathom::resetModel(CbcModel * model) { model_ = model; } // Destructor CbcFathom::~CbcFathom () { } // update model void CbcFathom::setModel(CbcModel * model) { model_ = model; } #ifdef COIN_HAS_CLP //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CbcOsiSolver::CbcOsiSolver () : OsiClpSolverInterface() { cbcModel_ = NULL; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * CbcOsiSolver::clone(bool /*copyData*/) const { //assert (copyData); return new CbcOsiSolver(*this); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CbcOsiSolver::CbcOsiSolver ( const CbcOsiSolver & rhs) : OsiSolverInterface(), // Should not be needed but get warning OsiClpSolverInterface(rhs) { cbcModel_ = rhs.cbcModel_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CbcOsiSolver::~CbcOsiSolver () { } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcOsiSolver & CbcOsiSolver::operator=(const CbcOsiSolver & rhs) { if (this != &rhs) { OsiClpSolverInterface::operator=(rhs); cbcModel_ = rhs.cbcModel_; } return *this; } #endif Cbc-2.8.12/src/CbcBranchDynamic.cpp0000644000076600007660000007071311510742604015366 0ustar coincoin/* $Id: CbcBranchDynamic.cpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG //#define TRACE_ONE 19 #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchDynamic.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" // Removing magic constants. // This is a very small number, added to something to make sure it's non-zero. // Useful, for example in denominators of ratios to avoid any possible division by zero # define nonZeroAmount 1.0e-30 // Increasing the size of an array when it grows to the end of its alloted space. // In this file, only used for the history of the outcome of a branch. // New size is size_scale_numerator* / size_scale_denominator + additive_size_increase. #define size_scale_numerator 3 #define size_scale_denominator 2 #define additive_size_increase 100 // Explanation of options used in this file // TYPE2 defines a strategy for computing pseudocosts // 0 means to just use the absolute change in objective // 1 means use the relative change in objective // 2 means use a convex combination of absolute and relative objective changes // For option 2 (TYPE2 == 2), the specific combination is controlled by TYPERATIO // Includes a TYPERATIO fraction of the absolute change and (1 - TYPERATIO) fraction of // the relative change. So should in general have 0 <= TYPERATIO <= 1. But for the // equality cases, you're better off using the other strategy (TYPE2) options. #ifdef COIN_DEVELOP typedef struct { double sumUp_; double upEst_; // or change in obj in update double sumDown_; double downEst_; // or movement in value in update int sequence_; int numberUp_; int numberUpInf_; int numberDown_; int numberDownInf_; char where_; char status_; } History; History * history = NULL; int numberHistory = 0; int maxHistory = 0; bool getHistoryStatistics_ = true; static void increaseHistory() { if (numberHistory == maxHistory) { // This was originally 3 * maxHistory/2 + 100 maxHistory = additive_size_increase + (size_scale_numerator * maxHistory) / size_scale_denominator; History * temp = new History [maxHistory]; memcpy(temp, history, numberHistory*sizeof(History)); delete [] history; history = temp; } } static bool addRecord(History newOne) { //if (!getHistoryStatistics_) return false; bool fromCompare = false; int i; for ( i = numberHistory - 1; i >= 0; i--) { if (newOne.sequence_ != history[i].sequence_) continue; if (newOne.where_ != history[i].where_) continue; if (newOne.numberUp_ != history[i].numberUp_) continue; if (newOne.sumUp_ != history[i].sumUp_) continue; if (newOne.numberUpInf_ != history[i].numberUpInf_) continue; if (newOne.upEst_ != history[i].upEst_) continue; if (newOne.numberDown_ != history[i].numberDown_) continue; if (newOne.sumDown_ != history[i].sumDown_) continue; if (newOne.numberDownInf_ != history[i].numberDownInf_) continue; if (newOne.downEst_ != history[i].downEst_) continue; // If B knock out previous B if (newOne.where_ == 'C') { fromCompare = true; if (newOne.status_ == 'B') { int j; for (j = i - 1; j >= 0; j--) { if (history[j].where_ == 'C') { if (history[j].status_ == 'I') { break; } else if (history[j].status_ == 'B') { history[j].status_ = ' '; break; } } } } break; } } if (i == -1 || fromCompare) { //add increaseHistory(); history[numberHistory++] = newOne; return true; } else { return false; } } #endif // Default Constructor CbcBranchDynamicDecision::CbcBranchDynamicDecision() : CbcBranchDecision() { bestCriterion_ = 0.0; bestChangeUp_ = 0.0; bestNumberUp_ = 0; bestChangeDown_ = 0.0; bestNumberDown_ = 0; bestObject_ = NULL; } // Copy constructor CbcBranchDynamicDecision::CbcBranchDynamicDecision ( const CbcBranchDynamicDecision & rhs) : CbcBranchDecision() { bestCriterion_ = rhs.bestCriterion_; bestChangeUp_ = rhs.bestChangeUp_; bestNumberUp_ = rhs.bestNumberUp_; bestChangeDown_ = rhs.bestChangeDown_; bestNumberDown_ = rhs.bestNumberDown_; bestObject_ = rhs.bestObject_; } CbcBranchDynamicDecision::~CbcBranchDynamicDecision() { } // Clone CbcBranchDecision * CbcBranchDynamicDecision::clone() const { return new CbcBranchDynamicDecision(*this); } // Initialize i.e. before start of choosing at a node void CbcBranchDynamicDecision::initialize(CbcModel * /*model*/) { bestCriterion_ = 0.0; bestChangeUp_ = 0.0; bestNumberUp_ = 0; bestChangeDown_ = 0.0; bestNumberDown_ = 0; bestObject_ = NULL; #ifdef COIN_DEVELOP History hist; hist.where_ = 'C'; hist.status_ = 'I'; hist.sequence_ = 55555; hist.numberUp_ = 0; hist.numberUpInf_ = 0; hist.sumUp_ = 0.0; hist.upEst_ = 0.0; hist.numberDown_ = 0; hist.numberDownInf_ = 0; hist.sumDown_ = 0.0; hist.downEst_ = 0.0; addRecord(hist); #endif } /* Saves a clone of current branching object. Can be used to update information on object causing branch - after branch */ void CbcBranchDynamicDecision::saveBranchingObject(OsiBranchingObject * object) { OsiBranchingObject * obj = object->clone(); #ifndef NDEBUG CbcBranchingObject * obj2 = dynamic_cast(obj); assert (obj2); #if COIN_DEVELOP>1 CbcDynamicPseudoCostBranchingObject * branchingObject = dynamic_cast(obj); if (!branchingObject) printf("no dynamic branching object Dynamic Decision\n"); #endif #else CbcBranchingObject * obj2 = static_cast(obj); #endif //object_=branchingObject; object_ = obj2; } /* Pass in information on branch just done. assumes object can get information from solver */ /* The expectation is that this method will be called after the branch has been imposed on the constraint system and resolve() has executed. Note that the CbcBranchDecision is a property of the CbcModel. Note also that this method is reaching right through the CbcBranchingObject to update information in the underlying CbcObject. That's why we delete the branchingObject at the end of the method --- the next time we're called, the CbcObject will be different. */ void CbcBranchDynamicDecision::updateInformation(OsiSolverInterface * solver, const CbcNode * node) { assert (object_); const CbcModel * model = object_->model(); double originalValue = node->objectiveValue(); int originalUnsatisfied = node->numberUnsatisfied(); double objectiveValue = solver->getObjValue() * model->getObjSense(); int unsatisfied = 0; int i; int numberIntegers = model->numberIntegers();; const double * solution = solver->getColSolution(); //const double * lower = solver->getColLower(); //const double * upper = solver->getColUpper(); /* Gain access to the associated CbcBranchingObject and its underlying CbcObject. Seems like we'd want to distinguish between no branching object and a branching object of the wrong type. Just deleting an object of the wrong type hides many sins. Hmmm ... if we're using the OSI side of the hierarchy, is this indicated by a null object_? Nah, then we have an assert failure off the top. */ CbcDynamicPseudoCostBranchingObject * branchingObject = dynamic_cast(object_); if (!branchingObject) { delete object_; object_ = NULL; return; } CbcSimpleIntegerDynamicPseudoCost * object = branchingObject->object(); /* change is the change in objective due to the branch we've just imposed. It's possible we may have gone infeasible. */ double change = CoinMax(0.0, objectiveValue - originalValue); // probably should also ignore if stopped // FIXME. Could use enum to avoid numbers for iStatus (e.g. optimal, unknown, infeasible) int iStatus; if (solver->isProvenOptimal()) iStatus = 0; // optimal else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) iStatus = 2; // unknown else iStatus = 1; // infeasible /* If we're feasible according to the solver, evaluate integer feasibility. */ bool feasible = iStatus != 1; if (feasible) { double integerTolerance = model->getDblParam(CbcModel::CbcIntegerTolerance); const int * integerVariable = model->integerVariable(); for (i = 0; i < numberIntegers; i++) { int j = integerVariable[i]; double value = solution[j]; double nearest = floor(value + 0.5); if (fabs(value - nearest) > integerTolerance) unsatisfied++; } } /* Finally, update the object. Defaults (080104) are TYPE2 = 0, INFEAS = 1. Pseudocosts are at heart the average of actual costs for a branch. We just need to update the information used to calculate that average. */ int way = object_->way(); double value = object_->value(); //#define TYPE2 1 //#define TYPERATIO 0.9 if (way < 0) { // down if (feasible) { double movement = value - floor(value); movement = CoinMax(movement, MINIMUM_MOVEMENT); //printf("(down change %g value down %g ",change,movement); object->incrementNumberTimesDown(); object->addToSumDownChange(nonZeroAmount + movement); object->addToSumDownDecrease(originalUnsatisfied - unsatisfied); #if TYPE2==0 object->addToSumDownCost(change / (nonZeroAmount + movement)); object->setDownDynamicPseudoCost(object->sumDownCost() / static_cast (object->numberTimesDown())); #elif TYPE2==1 object->addToSumDownCost(change); object->setDownDynamicPseudoCost(object->sumDownCost() / object->sumDownChange()); #elif TYPE2==2 object->addToSumDownCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (nonZeroAmount + movement)); object->setDownDynamicPseudoCost(object->sumDownCost()*(TYPERATIO / object->sumDownChange() + (1.0 - TYPERATIO) / (double) object->numberTimesDown())); #endif } else { //printf("(down infeasible value down %g ",change,movement); object->incrementNumberTimesDown(); object->incrementNumberTimesDownInfeasible(); #if INFEAS==2 double distanceToCutoff = 0.0; double objectiveValue = model->getCurrentMinimizationObjValue(); distanceToCutoff = model->getCutoff() - originalValue; if (distanceToCutoff < 1.0e20) change = distanceToCutoff * 2.0; else change = object->downDynamicPseudoCost() * movement * 10.0; change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change); object->addToSumDownChange(nonZeroAmount + movement); object->addToSumDownDecrease(originalUnsatisfied - unsatisfied); #if TYPE2==0 object->addToSumDownCost(change / (nonZeroAmount + movement)); object->setDownDynamicPseudoCost(object->sumDownCost() / (double) object->numberTimesDown()); #elif TYPE2==1 object->addToSumDownCost(change); object->setDownDynamicPseudoCost(object->sumDownCost() / object->sumDownChange()); #elif TYPE2==2 object->addToSumDownCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (nonZeroAmount + movement)); object->setDownDynamicPseudoCost(object->sumDownCost()*(TYPERATIO / object->sumDownChange() + (1.0 - TYPERATIO) / (double) object->numberTimesDown())); #endif #endif } } else { // up if (feasible) { double movement = ceil(value) - value; movement = CoinMax(movement, MINIMUM_MOVEMENT); //printf("(up change %g value down %g ",change,movement); object->incrementNumberTimesUp(); object->addToSumUpChange(nonZeroAmount + movement); object->addToSumUpDecrease(unsatisfied - originalUnsatisfied); #if TYPE2==0 object->addToSumUpCost(change / (nonZeroAmount + movement)); object->setUpDynamicPseudoCost(object->sumUpCost() / static_cast (object->numberTimesUp())); #elif TYPE2==1 object->addToSumUpCost(change); object->setUpDynamicPseudoCost(object->sumUpCost() / object->sumUpChange()); #elif TYPE2==2 object->addToSumUpCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (nonZeroAmount + movement)); object->setUpDynamicPseudoCost(object->sumUpCost()*(TYPERATIO / object->sumUpChange() + (1.0 - TYPERATIO) / (double) object->numberTimesUp())); #endif } else { //printf("(up infeasible value down %g ",change,movement); object->incrementNumberTimesUp(); object->incrementNumberTimesUpInfeasible(); #if INFEAS==2 double distanceToCutoff = 0.0; double objectiveValue = model->getCurrentMinimizationObjValue(); distanceToCutoff = model->getCutoff() - originalValue; if (distanceToCutoff < 1.0e20) change = distanceToCutoff * 2.0; else change = object->upDynamicPseudoCost() * movement * 10.0; change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change); object->addToSumUpChange(nonZeroAmount + movement); object->addToSumUpDecrease(unsatisfied - originalUnsatisfied); #if TYPE2==0 object->addToSumUpCost(change / (nonZeroAmount + movement)); object->setUpDynamicPseudoCost(object->sumUpCost() / (double) object->numberTimesUp()); #elif TYPE2==1 object->addToSumUpCost(change); object->setUpDynamicPseudoCost(object->sumUpCost() / object->sumUpChange()); #elif TYPE2==2 object->addToSumUpCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (nonZeroAmount + movement)); object->setUpDynamicPseudoCost(object->sumUpCost()*(TYPERATIO / object->sumUpChange() + (1.0 - TYPERATIO) / (double) object->numberTimesUp())); #endif #endif } } //object->print(1,0.5); delete object_; object_ = NULL; } /* Simple dynamic decision algorithm. Compare based on infeasibility (numInfUp, numInfDown) until a solution is found by search, then switch to change in objective (changeUp, changeDown). Note that bestSoFar is remembered in bestObject_, so the parameter bestSoFar is unused. */ int CbcBranchDynamicDecision::betterBranch(CbcBranchingObject * thisOne, CbcBranchingObject * /*bestSoFar*/, double changeUp, int numInfUp, double changeDown, int numInfDown) { CbcModel * model = thisOne->model(); int stateOfSearch = model->stateOfSearch() % 10; int betterWay = 0; double value = 0.0; if (!bestObject_) { bestCriterion_ = -1.0e30; bestNumberUp_ = COIN_INT_MAX; bestNumberDown_ = COIN_INT_MAX; } // maybe branch up more if no solution or not many nodes done? if (stateOfSearch <= 2) { //#define TRY_STUFF 1 #ifdef TRY_STUFF // before solution - choose smallest number // could add in depth as well int bestNumber = CoinMin(bestNumberUp_, bestNumberDown_); if (numInfUp < numInfDown) { if (numInfUp < bestNumber) { betterWay = 1; } else if (numInfUp == bestNumber) { if (changeUp < bestChangeUp_) betterWay = 1; } } else if (numInfUp > numInfDown) { if (numInfDown < bestNumber) { betterWay = -1; } else if (numInfDown == bestNumber) { if (changeDown < bestChangeDown_) betterWay = -1; } } else { // up and down have same number bool better = false; if (numInfUp < bestNumber) { better = true; } else if (numInfUp == bestNumber) { if (CoinMin(changeUp, changeDown) < CoinMin(bestChangeUp_, bestChangeDown_) - 1.0e-5) better = true;; } if (better) { // see which way if (changeUp <= changeDown) betterWay = 1; else betterWay = -1; } } if (betterWay) { value = CoinMin(numInfUp, numInfDown); } #else // use pseudo shadow prices modified by locks // test testosi #ifndef JJF_ONE double objectiveValue = model->getCurrentMinimizationObjValue(); double distanceToCutoff = model->getCutoff() - objectiveValue; if (distanceToCutoff < 1.0e20) distanceToCutoff *= 10.0; else distanceToCutoff = 1.0e2 + fabs(objectiveValue); distanceToCutoff = CoinMax(distanceToCutoff, 1.0e-12 * (1.0 + fabs(objectiveValue))); double continuousObjective = model->getContinuousObjective(); double distanceToCutoffC = model->getCutoff() - continuousObjective; if (distanceToCutoffC > 1.0e20) distanceToCutoffC = 1.0e2 + fabs(objectiveValue); distanceToCutoffC = CoinMax(distanceToCutoffC, 1.0e-12 * (1.0 + fabs(objectiveValue))); int numberInfC = model->getContinuousInfeasibilities(); double perInf = distanceToCutoffC / static_cast (numberInfC); assert (perInf > 0.0); //int numberIntegers = model->numberIntegers(); changeDown += perInf * numInfDown; changeUp += perInf * numInfUp; #ifdef JJF_ZERO if (numInfDown == 1) { if (numInfUp == 1) { changeUp += 1.0e6; changeDown += 1.0e6; } else if (changeDown <= 1.5*changeUp) { changeUp += 1.0e6; } } else if (numInfUp == 1 && changeUp <= 1.5*changeDown) { changeDown += 1.0e6; } #endif #endif double minValue = CoinMin(changeDown, changeUp); double maxValue = CoinMax(changeDown, changeUp); value = WEIGHT_BEFORE * minValue + (1.0 - WEIGHT_BEFORE) * maxValue; if (value > bestCriterion_ + 1.0e-8) { if (changeUp <= 1.5*changeDown) { betterWay = 1; } else { betterWay = -1; } } #endif } else { #define TRY_STUFF 2 #if TRY_STUFF > 1 // Get current number of infeasibilities, cutoff and current objective CbcNode * node = model->currentNode(); int numberUnsatisfied = node->numberUnsatisfied(); double cutoff = model->getCutoff(); double objectiveValue = node->objectiveValue(); #endif // got a solution double minValue = CoinMin(changeDown, changeUp); double maxValue = CoinMax(changeDown, changeUp); // Reduce #ifdef TRY_STUFF //maxValue = CoinMin(maxValue,minValue*4.0); #else //maxValue = CoinMin(maxValue,minValue*2.0); #endif #ifndef WEIGHT_PRODUCT value = WEIGHT_AFTER * minValue + (1.0 - WEIGHT_AFTER) * maxValue; #else double minProductWeight = model->getDblParam(CbcModel::CbcSmallChange); value = CoinMax(minValue, minProductWeight) * CoinMax(maxValue, minProductWeight); //value += minProductWeight*minValue; #endif double useValue = value; double useBest = bestCriterion_; #if TRY_STUFF>1 int thisNumber = CoinMin(numInfUp, numInfDown); int bestNumber = CoinMin(bestNumberUp_, bestNumberDown_); double distance = cutoff - objectiveValue; assert (distance >= 0.0); if (useValue + 0.1*distance > useBest && useValue*1.1 > useBest && useBest + 0.1*distance > useValue && useBest*1.1 > useValue) { // not much in it - look at unsatisfied if (thisNumber < numberUnsatisfied || bestNumber < numberUnsatisfied) { double perInteger = distance / (static_cast (numberUnsatisfied)); useValue += thisNumber * perInteger; useBest += bestNumber * perInteger; } } #endif if (useValue > useBest + 1.0e-8) { if (changeUp <= 1.5*changeDown) { betterWay = 1; } else { betterWay = -1; } } } #ifdef COIN_DEVELOP History hist; { CbcDynamicPseudoCostBranchingObject * branchingObject = dynamic_cast(thisOne); if (branchingObject) { CbcSimpleIntegerDynamicPseudoCost * object = branchingObject->object(); assert (object); hist.where_ = 'C'; hist.status_ = ' '; hist.sequence_ = object->columnNumber(); hist.numberUp_ = object->numberTimesUp(); hist.numberUpInf_ = numInfUp; hist.sumUp_ = object->sumUpCost(); hist.upEst_ = changeUp; hist.numberDown_ = object->numberTimesDown(); hist.numberDownInf_ = numInfDown; hist.sumDown_ = object->sumDownCost(); hist.downEst_ = changeDown; } } #endif if (betterWay) { #ifdef COIN_DEVELOP hist.status_ = 'B'; #endif // maybe change better way CbcDynamicPseudoCostBranchingObject * branchingObject = dynamic_cast(thisOne); if (branchingObject) { CbcSimpleIntegerDynamicPseudoCost * object = branchingObject->object(); double separator = object->upDownSeparator(); if (separator > 0.0) { const double * solution = thisOne->model()->testSolution(); double valueVariable = solution[object->columnNumber()]; betterWay = (valueVariable - floor(valueVariable) >= separator) ? 1 : -1; } } bestCriterion_ = value; bestChangeUp_ = changeUp; bestNumberUp_ = numInfUp; bestChangeDown_ = changeDown; bestNumberDown_ = numInfDown; bestObject_ = thisOne; // See if user is overriding way if (thisOne->object() && thisOne->object()->preferredWay()) betterWay = thisOne->object()->preferredWay(); } #ifdef COIN_DEVELOP addRecord(hist); #endif return betterWay; } /* Sets or gets best criterion so far */ void CbcBranchDynamicDecision::setBestCriterion(double value) { bestCriterion_ = value; } double CbcBranchDynamicDecision::getBestCriterion() const { return bestCriterion_; } #ifdef COIN_DEVELOP void printHistory(const char * file) { if (!numberHistory) return; FILE * fp = fopen(file, "w"); assert(fp); int numberIntegers = 0; int i; for (i = 0; i < numberHistory; i++) { if (history[i].where_ != 'C' || history[i].status_ != 'I') numberIntegers = CoinMax(numberIntegers, history[i].sequence_); } numberIntegers++; for (int iC = 0; iC < numberIntegers; iC++) { int n = 0; for (i = 0; i < numberHistory; i++) { if (history[i].sequence_ == iC) { if (!n) fprintf(fp, "XXX %d\n", iC); n++; fprintf(fp, "%c%c up %8d %8d %12.5f %12.5f down %8d %8d %12.5f %12.5f\n", history[i].where_, history[i].status_, history[i].numberUp_, history[i].numberUpInf_, history[i].sumUp_, history[i].upEst_, history[i].numberDown_, history[i].numberDownInf_, history[i].sumDown_, history[i].downEst_); } } } fclose(fp); } #endif // Default Constructor CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject() : CbcIntegerBranchingObject() { changeInGuessed_ = 1.0e-5; object_ = NULL; } // Useful constructor CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject (CbcModel * model, int variable, int way , double value, CbcSimpleIntegerDynamicPseudoCost * object) : CbcIntegerBranchingObject(model, variable, way, value) { changeInGuessed_ = 1.0e-5; object_ = object; } // Does part of work for constructor void CbcDynamicPseudoCostBranchingObject::fillPart (int variable, int way , double value, CbcSimpleIntegerDynamicPseudoCost * object) { CbcIntegerBranchingObject::fillPart(variable, way, value); changeInGuessed_ = 1.0e-5; object_ = object; } // Useful constructor for fixing CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject (CbcModel * model, int variable, int way, double lowerValue, double /*upperValue*/) : CbcIntegerBranchingObject(model, variable, way, lowerValue) { changeInGuessed_ = 1.0e100; object_ = NULL; } // Copy constructor CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject ( const CbcDynamicPseudoCostBranchingObject & rhs) : CbcIntegerBranchingObject(rhs) { changeInGuessed_ = rhs.changeInGuessed_; object_ = rhs.object_; } // Assignment operator CbcDynamicPseudoCostBranchingObject & CbcDynamicPseudoCostBranchingObject::operator=( const CbcDynamicPseudoCostBranchingObject & rhs) { if (this != &rhs) { CbcIntegerBranchingObject::operator=(rhs); changeInGuessed_ = rhs.changeInGuessed_; object_ = rhs.object_; } return *this; } CbcBranchingObject * CbcDynamicPseudoCostBranchingObject::clone() const { return (new CbcDynamicPseudoCostBranchingObject(*this)); } // Destructor CbcDynamicPseudoCostBranchingObject::~CbcDynamicPseudoCostBranchingObject () { } /* Perform a branch by adjusting the bounds of the specified variable. Note that each arm of the branch advances the object to the next arm by advancing the value of way_. Providing new values for the variable's lower and upper bounds for each branching direction gives a little bit of additional flexibility and will be easily extensible to multi-way branching. Returns change in guessed objective on next branch */ double CbcDynamicPseudoCostBranchingObject::branch() { CbcIntegerBranchingObject::branch(); return changeInGuessed_; } /* Some branchingObjects may claim to be able to skip strong branching. If so they have to fill in CbcStrongInfo. The object mention in incoming CbcStrongInfo must match. Returns nonzero if skip is wanted */ int CbcDynamicPseudoCostBranchingObject::fillStrongInfo( CbcStrongInfo & info) { assert (object_); assert (info.possibleBranch == this); info.upMovement = object_->upDynamicPseudoCost() * (ceil(value_) - value_); info.downMovement = object_->downDynamicPseudoCost() * (value_ - floor(value_)); info.numIntInfeasUp -= static_cast (object_->sumUpDecrease() / (1.0e-12 + static_cast (object_->numberTimesUp()))); info.numIntInfeasUp = CoinMax(info.numIntInfeasUp, 0); info.numObjInfeasUp = 0; info.finishedUp = false; info.numItersUp = 0; info.numIntInfeasDown -= static_cast (object_->sumDownDecrease() / (1.0e-12 + static_cast (object_->numberTimesDown()))); info.numIntInfeasDown = CoinMax(info.numIntInfeasDown, 0); info.numObjInfeasDown = 0; info.finishedDown = false; info.numItersDown = 0; info.fix = 0; if (object_->numberTimesUp() < object_->numberBeforeTrust() + 2*object_->numberTimesUpInfeasible() || object_->numberTimesDown() < object_->numberBeforeTrust() + 2*object_->numberTimesDownInfeasible()) { return 0; } else { return 1; } } Cbc-2.8.12/src/CbcBranchLotsize.cpp0000644000076600007660000006277312371443325015446 0ustar coincoin/* $Id: CbcBranchLotsize.cpp 2055 2014-08-09 16:05:41Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchLotsize.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" /* CBC_PRINT 1 just does sanity checks - no printing Larger values of CBC_PRINT set various printing levels. Larger values print more. */ //#define CBC_PRINT 1 // First/last variable to print info on #if CBC_PRINT // preset does all - change to x,x to just do x static int firstPrint = 0; static int lastPrint = 1000000; static CbcModel * saveModel = NULL; #endif // Just for debug (CBC_PRINT defined in CbcBranchLotsize.cpp) void #if CBC_PRINT CbcLotsize::printLotsize(double value, bool condition, int type) const #else CbcLotsize::printLotsize(double , bool , int ) const #endif { #if CBC_PRINT if (columnNumber_ >= firstPrint && columnNumber_ <= lastPrint) { int printIt = CBC_PRINT - 1; // Get details OsiSolverInterface * solver = saveModel->solver(); double currentLower = solver->getColLower()[columnNumber_]; double currentUpper = solver->getColUpper()[columnNumber_]; int i; // See if in a valid range (with two tolerances) bool inRange = false; bool inRange2 = false; double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); // increase if type 2 if (type == 2) { integerTolerance *= 100.0; type = 0; printIt = 2; // always print } // bounds should match some bound int rangeL = -1; int rangeU = -1; if (rangeType_ == 1) { for (i = 0; i < numberRanges_; i++) { if (fabs(currentLower - bound_[i]) < 1.0e-12) rangeL = i; if (fabs(currentUpper - bound_[i]) < 1.0e-12) rangeU = i; if (fabs(value - bound_[i]) < integerTolerance) inRange = true; if (fabs(value - bound_[i]) < 1.0e8) inRange2 = true; } } else { for (i = 0; i < numberRanges_; i++) { if (fabs(currentLower - bound_[2*i]) < 1.0e-12) rangeL = i; if (fabs(currentUpper - bound_[2*i+1]) < 1.0e-12) rangeU = i; if (value > bound_[2*i] - integerTolerance && value < bound_[2*i+1] + integerTolerance) inRange = true; if (value > bound_[2*i] - integerTolerance && value < bound_[2*i+1] + integerTolerance) inRange = true; } } assert (rangeL >= 0 && rangeU >= 0); bool abortIt = false; switch (type) { // returning from findRange (fall through to just check) case 0: if (printIt) { printf("findRange returns %s for column %d and value %g", condition ? "true" : "false", columnNumber_, value); if (printIt > 1) printf(" LP bounds %g, %g", currentLower, currentUpper); printf("\n"); } // Should match case 1: if (inRange != condition) { printIt = 2; abortIt = true; } break; // case 2: break; // case 3: break; // case 4: break; } } #endif } /** Default Constructor */ CbcLotsize::CbcLotsize () : CbcObject(), columnNumber_(-1), rangeType_(0), numberRanges_(0), largestGap_(0), bound_(NULL), range_(0) { } /** Useful constructor Loads actual upper & lower bounds for the specified variable. */ CbcLotsize::CbcLotsize (CbcModel * model, int iColumn, int numberPoints, const double * points, bool range) : CbcObject(model) { #if CBC_PRINT if (!saveModel) saveModel = model; #endif assert (numberPoints > 0); columnNumber_ = iColumn ; // and set id so can be used for branching id_ = iColumn; // sort ranges int * sort = new int[numberPoints]; double * weight = new double [numberPoints]; int i; if (range) { rangeType_ = 2; } else { rangeType_ = 1; } for (i = 0; i < numberPoints; i++) { sort[i] = i; weight[i] = points[i*rangeType_]; } CoinSort_2(weight, weight + numberPoints, sort); numberRanges_ = 1; largestGap_ = 0; if (rangeType_ == 1) { bound_ = new double[numberPoints+1]; bound_[0] = weight[0]; for (i = 1; i < numberPoints; i++) { if (weight[i] != weight[i-1]) bound_[numberRanges_++] = weight[i]; } // and for safety bound_[numberRanges_] = bound_[numberRanges_-1]; for (i = 1; i < numberRanges_; i++) { largestGap_ = CoinMax(largestGap_, bound_[i] - bound_[i-1]); } } else { bound_ = new double[2*numberPoints+2]; bound_[0] = points[sort[0] * 2]; bound_[1] = points[sort[0] * 2 + 1]; double hi = bound_[1]; assert (hi >= bound_[0]); for (i = 1; i < numberPoints; i++) { double thisLo = points[sort[i] * 2]; double thisHi = points[sort[i] * 2 + 1]; assert (thisHi >= thisLo); if (thisLo > hi) { bound_[2*numberRanges_] = thisLo; bound_[2*numberRanges_+1] = thisHi; numberRanges_++; hi = thisHi; } else { //overlap hi = CoinMax(hi, thisHi); bound_[2*numberRanges_-1] = hi; } } // and for safety bound_[2*numberRanges_] = bound_[2*numberRanges_-2]; bound_[2*numberRanges_+1] = bound_[2*numberRanges_-1]; for (i = 1; i < numberRanges_; i++) { largestGap_ = CoinMax(largestGap_, bound_[2*i] - bound_[2*i-1]); } } delete [] sort; delete [] weight; range_ = 0; } // Copy constructor CbcLotsize::CbcLotsize ( const CbcLotsize & rhs) : CbcObject(rhs) { columnNumber_ = rhs.columnNumber_; rangeType_ = rhs.rangeType_; numberRanges_ = rhs.numberRanges_; range_ = rhs.range_; largestGap_ = rhs.largestGap_; if (numberRanges_) { assert (rangeType_ > 0 && rangeType_ < 3); bound_ = new double [(numberRanges_+1)*rangeType_]; memcpy(bound_, rhs.bound_, (numberRanges_ + 1)*rangeType_*sizeof(double)); } else { bound_ = NULL; } } // Clone CbcObject * CbcLotsize::clone() const { return new CbcLotsize(*this); } // Assignment operator CbcLotsize & CbcLotsize::operator=( const CbcLotsize & rhs) { if (this != &rhs) { CbcObject::operator=(rhs); columnNumber_ = rhs.columnNumber_; rangeType_ = rhs.rangeType_; numberRanges_ = rhs.numberRanges_; largestGap_ = rhs.largestGap_; delete [] bound_; range_ = rhs.range_; if (numberRanges_) { assert (rangeType_ > 0 && rangeType_ < 3); bound_ = new double [(numberRanges_+1)*rangeType_]; memcpy(bound_, rhs.bound_, (numberRanges_ + 1)*rangeType_*sizeof(double)); } else { bound_ = NULL; } } return *this; } // Destructor CbcLotsize::~CbcLotsize () { delete [] bound_; } /* Finds range of interest so value is feasible in range range_ or infeasible between hi[range_] and lo[range_+1]. Returns true if feasible. */ bool CbcLotsize::findRange(double value) const { assert (range_ >= 0 && range_ < numberRanges_ + 1); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); int iLo; int iHi; double infeasibility = 0.0; if (rangeType_ == 1) { if (value < bound_[range_] - integerTolerance) { iLo = 0; iHi = range_ - 1; } else if (value < bound_[range_] + integerTolerance) { #if CBC_PRINT printLotsize(value, true, 0); #endif return true; } else if (value < bound_[range_+1] - integerTolerance) { #ifdef CBC_PRINT printLotsize(value, false, 0); #endif return false; } else { iLo = range_ + 1; iHi = numberRanges_ - 1; } // check lo and hi bool found = false; if (value > bound_[iLo] - integerTolerance && value < bound_[iLo+1] + integerTolerance) { range_ = iLo; found = true; } else if (value > bound_[iHi] - integerTolerance && value < bound_[iHi+1] + integerTolerance) { range_ = iHi; found = true; } else { range_ = (iLo + iHi) >> 1; } //points while (!found) { if (value < bound_[range_]) { if (value >= bound_[range_-1]) { // found range_--; break; } else { iHi = range_; } } else { if (value < bound_[range_+1]) { // found break; } else { iLo = range_; } } range_ = (iLo + iHi) >> 1; } if (value - bound_[range_] <= bound_[range_+1] - value) { infeasibility = value - bound_[range_]; } else { infeasibility = bound_[range_+1] - value; if (infeasibility < integerTolerance) range_++; } #ifdef CBC_PRINT printLotsize(value, (infeasibility < integerTolerance), 0); #endif return (infeasibility < integerTolerance); } else { // ranges if (value < bound_[2*range_] - integerTolerance) { iLo = 0; iHi = range_ - 1; } else if (value < bound_[2*range_+1] + integerTolerance) { #ifdef CBC_PRINT printLotsize(value, true, 0); #endif return true; } else if (value < bound_[2*range_+2] - integerTolerance) { #ifdef CBC_PRINT printLotsize(value, false, 0); #endif return false; } else { iLo = range_ + 1; iHi = numberRanges_ - 1; } // check lo and hi bool found = false; if (value > bound_[2*iLo] - integerTolerance && value < bound_[2*iLo+2] - integerTolerance) { range_ = iLo; found = true; } else if (value >= bound_[2*iHi] - integerTolerance) { range_ = iHi; found = true; } else { range_ = (iLo + iHi) >> 1; } //points while (!found) { if (value < bound_[2*range_]) { if (value >= bound_[2*range_-2]) { // found range_--; break; } else { iHi = range_; } } else { if (value < bound_[2*range_+2]) { // found break; } else { iLo = range_; } } range_ = (iLo + iHi) >> 1; } if (value >= bound_[2*range_] - integerTolerance && value <= bound_[2*range_+1] + integerTolerance) infeasibility = 0.0; else if (value - bound_[2*range_+1] < bound_[2*range_+2] - value) { infeasibility = value - bound_[2*range_+1]; } else { infeasibility = bound_[2*range_+2] - value; } #ifdef CBC_PRINT printLotsize(value, (infeasibility < integerTolerance), 0); #endif return (infeasibility < integerTolerance); } } /* Returns floor and ceiling */ void CbcLotsize::floorCeiling(double & floorLotsize, double & ceilingLotsize, double value, double /*tolerance*/) const { bool feasible = findRange(value); if (rangeType_ == 1) { floorLotsize = bound_[range_]; ceilingLotsize = bound_[range_+1]; // may be able to adjust if (feasible && fabs(value - floorLotsize) > fabs(value - ceilingLotsize)) { floorLotsize = bound_[range_+1]; ceilingLotsize = bound_[range_+2]; } } else { // ranges assert (value >= bound_[2*range_+1]); floorLotsize = bound_[2*range_+1]; ceilingLotsize = bound_[2*range_+2]; } } double CbcLotsize::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); /*printf("%d %g %g %g %g\n",columnNumber_,value,lower[columnNumber_], solution[columnNumber_],upper[columnNumber_]);*/ assert (value >= bound_[0] - integerTolerance && value <= bound_[rangeType_*numberRanges_-1] + integerTolerance); double infeasibility = 0.0; bool feasible = findRange(value); if (!feasible) { if (rangeType_ == 1) { if (value - bound_[range_] < bound_[range_+1] - value) { preferredWay = -1; infeasibility = value - bound_[range_]; } else { preferredWay = 1; infeasibility = bound_[range_+1] - value; } } else { // ranges if (value - bound_[2*range_+1] < bound_[2*range_+2] - value) { preferredWay = -1; infeasibility = value - bound_[2*range_+1]; } else { preferredWay = 1; infeasibility = bound_[2*range_+2] - value; } } } else { // always satisfied preferredWay = -1; } if (infeasibility < integerTolerance) infeasibility = 0.0; else infeasibility /= largestGap_; #ifdef CBC_PRINT printLotsize(value, infeasibility, 1); #endif return infeasibility; } /* Column number if single column object -1 otherwise, so returns >= 0 Used by heuristics */ int CbcLotsize::columnNumber() const { return columnNumber_; } // This looks at solution and sets bounds to contain solution /** More precisely: it first forces the variable within the existing bounds, and then tightens the bounds to make sure the variable is feasible */ void CbcLotsize::feasibleRegion() { OsiSolverInterface * solver = model_->solver(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * solution = model_->testSolution(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); findRange(value); double nearest; if (rangeType_ == 1) { nearest = bound_[range_]; solver->setColLower(columnNumber_, nearest); solver->setColUpper(columnNumber_, nearest); } else { // ranges solver->setColLower(columnNumber_, CoinMax(bound_[2*range_], lower[columnNumber_])); solver->setColUpper(columnNumber_, CoinMin(bound_[2*range_+1], upper[columnNumber_])); if (value > bound_[2*range_+1]) nearest = bound_[2*range_+1]; else if (value < bound_[2*range_]) nearest = bound_[2*range_]; else nearest = value; } #ifdef CBC_PRINT // print details printLotsize(value, true, 2); #endif // Scaling may have moved it a bit // Lotsizing variables could be a lot larger #ifndef NDEBUG double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); assert (fabs(value - nearest) <= (100.0 + 10.0*fabs(nearest))*integerTolerance); #endif } CbcBranchingObject * CbcLotsize::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int way) { //OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); assert (!findRange(value)); return new CbcLotsizeBranchingObject(model_, columnNumber_, way, value, this); } /* Given valid solution (i.e. satisfied) and reduced costs etc returns a branching object which would give a new feasible point in direction reduced cost says would be cheaper. If no feasible point returns null */ CbcBranchingObject * CbcLotsize::preferredNewFeasible() const { OsiSolverInterface * solver = model_->solver(); assert (findRange(model_->testSolution()[columnNumber_])); double dj = solver->getObjSense() * solver->getReducedCost()[columnNumber_]; CbcLotsizeBranchingObject * object = NULL; double lo, up; if (dj >= 0.0) { // can we go down if (range_) { // yes if (rangeType_ == 1) { lo = bound_[range_-1]; up = bound_[range_-1]; } else { lo = bound_[2*range_-2]; up = bound_[2*range_-1]; } object = new CbcLotsizeBranchingObject(model_, columnNumber_, -1, lo, up); } } else { // can we go up if (range_ < numberRanges_ - 1) { // yes if (rangeType_ == 1) { lo = bound_[range_+1]; up = bound_[range_+1]; } else { lo = bound_[2*range_+2]; up = bound_[2*range_+3]; } object = new CbcLotsizeBranchingObject(model_, columnNumber_, -1, lo, up); } } return object; } /* Given valid solution (i.e. satisfied) and reduced costs etc returns a branching object which would give a new feasible point in direction opposite to one reduced cost says would be cheaper. If no feasible point returns null */ CbcBranchingObject * CbcLotsize::notPreferredNewFeasible() const { OsiSolverInterface * solver = model_->solver(); #ifndef NDEBUG double value = model_->testSolution()[columnNumber_]; double nearest = floor(value + 0.5); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); // Scaling may have moved it a bit // Lotsizing variables could be a lot larger assert (fabs(value - nearest) <= (10.0 + 10.0*fabs(nearest))*integerTolerance); #endif double dj = solver->getObjSense() * solver->getReducedCost()[columnNumber_]; CbcLotsizeBranchingObject * object = NULL; double lo, up; if (dj <= 0.0) { // can we go down if (range_) { // yes if (rangeType_ == 1) { lo = bound_[range_-1]; up = bound_[range_-1]; } else { lo = bound_[2*range_-2]; up = bound_[2*range_-1]; } object = new CbcLotsizeBranchingObject(model_, columnNumber_, -1, lo, up); } } else { // can we go up if (range_ < numberRanges_ - 1) { // yes if (rangeType_ == 1) { lo = bound_[range_+1]; up = bound_[range_+1]; } else { lo = bound_[2*range_+2]; up = bound_[2*range_+3]; } object = new CbcLotsizeBranchingObject(model_, columnNumber_, -1, lo, up); } } return object; } /* Bounds may be tightened, so it may be good to be able to refresh the local copy of the original bounds. */ void CbcLotsize::resetBounds(const OsiSolverInterface * /*solver*/) { } // Default Constructor CbcLotsizeBranchingObject::CbcLotsizeBranchingObject() : CbcBranchingObject() { down_[0] = 0.0; down_[1] = 0.0; up_[0] = 0.0; up_[1] = 0.0; } // Useful constructor CbcLotsizeBranchingObject::CbcLotsizeBranchingObject (CbcModel * model, int variable, int way , double value, const CbcLotsize * lotsize) : CbcBranchingObject(model, variable, way, value) { int iColumn = lotsize->modelSequence(); assert (variable == iColumn); down_[0] = model_->solver()->getColLower()[iColumn]; double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); lotsize->floorCeiling(down_[1], up_[0], value, integerTolerance); up_[1] = model->getColUpper()[iColumn]; } // Useful constructor for fixing CbcLotsizeBranchingObject::CbcLotsizeBranchingObject (CbcModel * model, int variable, int way, double lowerValue, double upperValue) : CbcBranchingObject(model, variable, way, lowerValue) { setNumberBranchesLeft(1); down_[0] = lowerValue; down_[1] = upperValue; up_[0] = lowerValue; up_[1] = upperValue; } // Copy constructor CbcLotsizeBranchingObject::CbcLotsizeBranchingObject ( const CbcLotsizeBranchingObject & rhs) : CbcBranchingObject(rhs) { down_[0] = rhs.down_[0]; down_[1] = rhs.down_[1]; up_[0] = rhs.up_[0]; up_[1] = rhs.up_[1]; } // Assignment operator CbcLotsizeBranchingObject & CbcLotsizeBranchingObject::operator=( const CbcLotsizeBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); down_[0] = rhs.down_[0]; down_[1] = rhs.down_[1]; up_[0] = rhs.up_[0]; up_[1] = rhs.up_[1]; } return *this; } CbcBranchingObject * CbcLotsizeBranchingObject::clone() const { return (new CbcLotsizeBranchingObject(*this)); } // Destructor CbcLotsizeBranchingObject::~CbcLotsizeBranchingObject () { } /* Perform a branch by adjusting the bounds of the specified variable. Note that each arm of the branch advances the object to the next arm by advancing the value of way_. Providing new values for the variable's lower and upper bounds for each branching direction gives a little bit of additional flexibility and will be easily extensible to multi-way branching. */ double CbcLotsizeBranchingObject::branch() { decrementNumberBranchesLeft(); int iColumn = variable_; if (way_ < 0) { #ifndef NDEBUG { double olb, oub ; olb = model_->solver()->getColLower()[iColumn] ; oub = model_->solver()->getColUpper()[iColumn] ; #ifdef CBC_DEBUG printf("branching down on var %d: [%g,%g] => [%g,%g]\n", iColumn, olb, oub, down_[0], down_[1]) ; #endif assert (olbdown_[1]-1.0e-7); } #endif model_->solver()->setColLower(iColumn, down_[0]); model_->solver()->setColUpper(iColumn, down_[1]); way_ = 1; } else { #ifndef NDEBUG { double olb, oub ; olb = model_->solver()->getColLower()[iColumn] ; oub = model_->solver()->getColUpper()[iColumn] ; #ifdef CBC_DEBUG printf("branching up on var %d: [%g,%g] => [%g,%g]\n", iColumn, olb, oub, up_[0], up_[1]) ; #endif assert (olbup_[1]-1.0e-7); } #endif model_->solver()->setColLower(iColumn, up_[0]); model_->solver()->setColUpper(iColumn, up_[1]); way_ = -1; // Swap direction } return 0.0; } // Print void CbcLotsizeBranchingObject::print() { int iColumn = variable_; if (way_ < 0) { { double olb, oub ; olb = model_->solver()->getColLower()[iColumn] ; oub = model_->solver()->getColUpper()[iColumn] ; printf("branching down on var %d: [%g,%g] => [%g,%g]\n", iColumn, olb, oub, down_[0], down_[1]) ; } } else { { double olb, oub ; olb = model_->solver()->getColLower()[iColumn] ; oub = model_->solver()->getColUpper()[iColumn] ; printf("branching up on var %d: [%g,%g] => [%g,%g]\n", iColumn, olb, oub, up_[0], up_[1]) ; } } } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcLotsizeBranchingObject::compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap) { const CbcLotsizeBranchingObject* br = dynamic_cast(brObj); assert(br); double* thisBd = way_ == -1 ? down_ : up_; const double* otherBd = br->way_ == -1 ? br->down_ : br->up_; return CbcCompareRanges(thisBd, otherBd, replaceIfOverlap); } Cbc-2.8.12/src/CbcParam.cpp0000644000076600007660000003667311510742604013733 0ustar coincoin/* $Id: CbcParam.cpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include "CbcParam.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CbcParam::CbcParam () : type_(CBC_PARAM_NOTUSED_INVALID), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), lowerIntValue_(0), upperIntValue_(0), lengthName_(0), lengthMatch_(0), definedKeyWords_(), name_(), shortHelp_(), longHelp_(), action_(CBC_PARAM_NOTUSED_INVALID), currentKeyWord_(-1) { } // Other constructors CbcParam::CbcParam (std::string name, std::string help, double lower, double upper, CbcParameterType type, bool display) : type_(type), lowerIntValue_(0), upperIntValue_(0), definedKeyWords_(), name_(name), shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(-1) { lowerDoubleValue_ = lower; upperDoubleValue_ = upper; gutsOfConstructor(); } CbcParam::CbcParam (std::string name, std::string help, int lower, int upper, CbcParameterType type, bool display) : type_(type), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), definedKeyWords_(), name_(name), shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(-1) { gutsOfConstructor(); lowerIntValue_ = lower; upperIntValue_ = upper; } // Other strings will be added by append CbcParam::CbcParam (std::string name, std::string help, std::string firstValue, CbcParameterType type, int defaultIndex, bool display) : type_(type), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), lowerIntValue_(0), upperIntValue_(0), definedKeyWords_(), name_(name), shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(0) { gutsOfConstructor(); definedKeyWords_.push_back(firstValue); } // Action CbcParam::CbcParam (std::string name, std::string help, CbcParameterType type, int indexNumber, bool display) : type_(type), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), lowerIntValue_(0), upperIntValue_(0), definedKeyWords_(), name_(name), shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(-1) { gutsOfConstructor(); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CbcParam::CbcParam (const CbcParam & rhs) { type_ = rhs.type_; lowerDoubleValue_ = rhs.lowerDoubleValue_; upperDoubleValue_ = rhs.upperDoubleValue_; lowerIntValue_ = rhs.lowerIntValue_; upperIntValue_ = rhs.upperIntValue_; lengthName_ = rhs.lengthName_; lengthMatch_ = rhs.lengthMatch_; definedKeyWords_ = rhs.definedKeyWords_; name_ = rhs.name_; shortHelp_ = rhs.shortHelp_; longHelp_ = rhs.longHelp_; action_ = rhs.action_; currentKeyWord_ = rhs.currentKeyWord_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CbcParam::~CbcParam () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcParam & CbcParam::operator=(const CbcParam & rhs) { if (this != &rhs) { type_ = rhs.type_; lowerDoubleValue_ = rhs.lowerDoubleValue_; upperDoubleValue_ = rhs.upperDoubleValue_; lowerIntValue_ = rhs.lowerIntValue_; upperIntValue_ = rhs.upperIntValue_; lengthName_ = rhs.lengthName_; lengthMatch_ = rhs.lengthMatch_; definedKeyWords_ = rhs.definedKeyWords_; name_ = rhs.name_; shortHelp_ = rhs.shortHelp_; longHelp_ = rhs.longHelp_; action_ = rhs.action_; currentKeyWord_ = rhs.currentKeyWord_; } return *this; } void CbcParam::gutsOfConstructor() { std::string::size_type shriekPos = name_.find('!'); lengthName_ = name_.length(); if ( shriekPos == std::string::npos ) { //does not contain '!' lengthMatch_ = lengthName_; } else { lengthMatch_ = shriekPos; name_ = name_.substr(0, shriekPos) + name_.substr(shriekPos + 1); lengthName_--; } } // Insert string (only valid for keywords) void CbcParam::append(std::string keyWord) { definedKeyWords_.push_back(keyWord); } int CbcParam::matches (std::string input) const { // look up strings to do more elegantly if (input.length() > lengthName_) { return 0; } else { unsigned int i; for (i = 0; i < input.length(); i++) { if (tolower(name_[i]) != tolower(input[i])) break; } if (i < input.length()) { return 0; } else if (i >= lengthMatch_) { return 1; } else { // matched but too short return 2; } } } // Returns name which could match std::string CbcParam::matchName ( ) const { if (lengthMatch_ == lengthName_) return name_; else return name_.substr(0, lengthMatch_) + "(" + name_.substr(lengthMatch_) + ")"; } // Returns parameter option which matches (-1 if none) int CbcParam::parameterOption ( std::string check ) const { int numberItems = definedKeyWords_.size(); if (!numberItems) { return -1; } else { int whichItem = 0; unsigned int it; for (it = 0; it < definedKeyWords_.size(); it++) { std::string thisOne = definedKeyWords_[it]; std::string::size_type shriekPos = thisOne.find('!'); unsigned int length1 = thisOne.length(); unsigned int length2 = length1; if ( shriekPos != std::string::npos ) { //contains '!' length2 = shriekPos; thisOne = thisOne.substr(0, shriekPos) + thisOne.substr(shriekPos + 1); length1 = thisOne.length(); } if (check.length() <= length1) { unsigned int i; for (i = 0; i < check.length(); i++) { if (tolower(thisOne[i]) != tolower(check[i])) break; } if (i < check.length()) { whichItem++; } else if (i >= length2) { break; } } else { whichItem++; } } if (whichItem < numberItems) return whichItem; else return -1; } } // Prints parameter options void CbcParam::printOptions ( ) const { std::cout << "Possible options for " << name_ << " are:" << std::endl; unsigned int it; for (it = 0; it < definedKeyWords_.size(); it++) { std::string thisOne = definedKeyWords_[it]; std::string::size_type shriekPos = thisOne.find('!'); if ( shriekPos != std::string::npos ) { //contains '!' thisOne = thisOne.substr(0, shriekPos) + "(" + thisOne.substr(shriekPos + 1) + ")"; } std::cout << thisOne << std::endl; } } int CbcParam::setDoubleParameter (OsiSolverInterface * model, double value) const { if (value < lowerDoubleValue_ || value > upperDoubleValue_) { std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; return 1; } else { double oldValue; switch (type_) { case CLP_PARAM_DBL_DUALTOLERANCE: model->getDblParam(OsiDualTolerance, oldValue); model->setDblParam(OsiDualTolerance, value); break; case CLP_PARAM_DBL_PRIMALTOLERANCE: model->getDblParam(OsiPrimalTolerance, oldValue); model->setDblParam(OsiPrimalTolerance, value); break; default: oldValue = 0.0; // to avoid compiler message abort(); } std::cout << name_ << " was changed from " << oldValue << " to " << value << std::endl; return 0; } } int CbcParam::checkDoubleParameter (double value) const { if (value < lowerDoubleValue_ || value > upperDoubleValue_) { std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; return 1; } else { return 0; } } double CbcParam::doubleParameter (OsiSolverInterface * model) const { double value; bool getDblParamRetValue; switch (type_) { case CLP_PARAM_DBL_DUALTOLERANCE: getDblParamRetValue = model->getDblParam(OsiDualTolerance, value); assert(getDblParamRetValue); break; case CLP_PARAM_DBL_PRIMALTOLERANCE: getDblParamRetValue = model->getDblParam(OsiPrimalTolerance, value); assert(getDblParamRetValue); break; default: abort(); } return value; } int CbcParam::setIntParameter (OsiSolverInterface * model, int value) const { if (value < lowerIntValue_ || value > upperIntValue_) { std::cout << value << " was provided for " << name_ << " - valid range is " << lowerIntValue_ << " to " << upperIntValue_ << std::endl; return 1; } else { int oldValue; switch (type_) { case CLP_PARAM_INT_LOGLEVEL: oldValue = model->messageHandler()->logLevel(); model->messageHandler()->setLogLevel(value); break; default: oldValue = 0; // to avoid compiler message abort(); } std::cout << name_ << " was changed from " << oldValue << " to " << value << std::endl; return 0; } } int CbcParam::intParameter (OsiSolverInterface * model) const { int value = 0; switch (type_) { case CLP_PARAM_INT_LOGLEVEL: //value=model->logLevel(); break; default: abort(); } return value; } int CbcParam::setDoubleParameter (CbcModel &model, double value) const { if (value < lowerDoubleValue_ || value > upperDoubleValue_) { std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; return 1; } else { double oldValue; switch (type_) { case CBC_PARAM_DBL_INFEASIBILITYWEIGHT: oldValue = model.getDblParam(CbcModel::CbcInfeasibilityWeight); model.setDblParam(CbcModel::CbcInfeasibilityWeight, value); break; case CBC_PARAM_DBL_INTEGERTOLERANCE: oldValue = model.getDblParam(CbcModel::CbcIntegerTolerance); model.setDblParam(CbcModel::CbcIntegerTolerance, value); break; case CBC_PARAM_DBL_INCREMENT: oldValue = model.getDblParam(CbcModel::CbcCutoffIncrement); model.setDblParam(CbcModel::CbcCutoffIncrement, value); case CBC_PARAM_DBL_ALLOWABLEGAP: oldValue = model.getDblParam(CbcModel::CbcAllowableGap); model.setDblParam(CbcModel::CbcAllowableGap, value); break; case CLP_PARAM_DBL_TIMELIMIT: { oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds) ; model.setDblParam(CbcModel::CbcMaximumSeconds, value) ; break ; } case CLP_PARAM_DBL_DUALTOLERANCE: case CLP_PARAM_DBL_PRIMALTOLERANCE: setDoubleParameter(model.solver(), value); return 0; // to avoid message default: oldValue = 0.0; // to avoid compiler message abort(); } std::cout << name_ << " was changed from " << oldValue << " to " << value << std::endl; return 0; } } double CbcParam::doubleParameter (CbcModel &model) const { double value; switch (type_) { case CBC_PARAM_DBL_INFEASIBILITYWEIGHT: value = model.getDblParam(CbcModel::CbcInfeasibilityWeight); break; case CBC_PARAM_DBL_INTEGERTOLERANCE: value = model.getDblParam(CbcModel::CbcIntegerTolerance); break; case CBC_PARAM_DBL_INCREMENT: value = model.getDblParam(CbcModel::CbcCutoffIncrement); case CBC_PARAM_DBL_ALLOWABLEGAP: value = model.getDblParam(CbcModel::CbcAllowableGap); break; case CLP_PARAM_DBL_TIMELIMIT: { value = model.getDblParam(CbcModel::CbcMaximumSeconds) ; break ; } case CLP_PARAM_DBL_DUALTOLERANCE: case CLP_PARAM_DBL_PRIMALTOLERANCE: value = doubleParameter(model.solver()); break; default: abort(); } return value; } int CbcParam::setIntParameter (CbcModel &model, int value) const { if (value < lowerIntValue_ || value > upperIntValue_) { std::cout << value << " was provided for " << name_ << " - valid range is " << lowerIntValue_ << " to " << upperIntValue_ << std::endl; return 1; } else { int oldValue; switch (type_) { case CLP_PARAM_INT_LOGLEVEL: oldValue = model.messageHandler()->logLevel(); model.messageHandler()->setLogLevel(value); break; case CLP_PARAM_INT_SOLVERLOGLEVEL: oldValue = model.solver()->messageHandler()->logLevel(); model.solver()->messageHandler()->setLogLevel(value); break; case CBC_PARAM_INT_MAXNODES: oldValue = model.getIntParam(CbcModel::CbcMaxNumNode); model.setIntParam(CbcModel::CbcMaxNumNode, value); break; case CBC_PARAM_INT_STRONGBRANCHING: oldValue = model.numberStrong(); model.setNumberStrong(value); break; default: oldValue = 0; // to avoid compiler message abort(); } std::cout << name_ << " was changed from " << oldValue << " to " << value << std::endl; return 0; } } int CbcParam::intParameter (CbcModel &model) const { int value; switch (type_) { case CLP_PARAM_INT_LOGLEVEL: value = model.messageHandler()->logLevel(); break; case CLP_PARAM_INT_SOLVERLOGLEVEL: value = model.solver()->messageHandler()->logLevel(); break; case CBC_PARAM_INT_MAXNODES: value = model.getIntParam(CbcModel::CbcMaxNumNode); break; case CBC_PARAM_INT_STRONGBRANCHING: value = model.numberStrong(); break; default: abort(); } return value; } Cbc-2.8.12/src/CbcHeuristic.cpp0000644000076600007660000034357312371443325014636 0ustar coincoin/* $Id: CbcHeuristic.cpp 2055 2014-08-09 16:05:41Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" #include #include #include #include //#define PRINT_DEBUG #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #endif #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcHeuristic.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcStrategy.hpp" #include "CglPreProcess.hpp" #include "CglGomory.hpp" #include "CglProbing.hpp" #include "OsiAuxInfo.hpp" #include "OsiPresolve.hpp" #include "CbcBranchActual.hpp" #include "CbcCutGenerator.hpp" //============================================================================== CbcHeuristicNode::CbcHeuristicNode(const CbcHeuristicNode& rhs) { numObjects_ = rhs.numObjects_; brObj_ = new CbcBranchingObject*[numObjects_]; for (int i = 0; i < numObjects_; ++i) { brObj_[i] = rhs.brObj_[i]->clone(); } } void CbcHeuristicNodeList::gutsOfDelete() { for (int i = (static_cast(nodes_.size())) - 1; i >= 0; --i) { delete nodes_[i]; } } void CbcHeuristicNodeList::gutsOfCopy(const CbcHeuristicNodeList& rhs) { append(rhs); } CbcHeuristicNodeList::CbcHeuristicNodeList(const CbcHeuristicNodeList& rhs) { gutsOfCopy(rhs); } CbcHeuristicNodeList& CbcHeuristicNodeList::operator= (const CbcHeuristicNodeList & rhs) { if (this != &rhs) { gutsOfDelete(); gutsOfCopy(rhs); } return *this; } CbcHeuristicNodeList::~CbcHeuristicNodeList() { gutsOfDelete(); } void CbcHeuristicNodeList::append(CbcHeuristicNode*& node) { nodes_.push_back(node); node = NULL; } void CbcHeuristicNodeList::append(const CbcHeuristicNodeList& nodes) { nodes_.reserve(nodes_.size() + nodes.size()); for (int i = 0; i < nodes.size(); ++i) { CbcHeuristicNode* node = new CbcHeuristicNode(*nodes.node(i)); append(node); } } //============================================================================== #define DEFAULT_WHERE ((255-2-16)*(1+256)) // Default Constructor CbcHeuristic::CbcHeuristic() : model_(NULL), when_(2), numberNodes_(200), feasibilityPumpOptions_(-1), fractionSmall_(1.0), heuristicName_("Unknown"), howOften_(1), decayFactor_(0.0), switches_(0), whereFrom_(DEFAULT_WHERE), shallowDepth_(1), howOftenShallow_(1), numInvocationsInShallow_(0), numInvocationsInDeep_(0), lastRunDeep_(0), numRuns_(0), minDistanceToRun_(1), runNodes_(), numCouldRun_(0), numberSolutionsFound_(0), numberNodesDone_(0), inputSolution_(NULL) { // As CbcHeuristic virtual need to modify .cpp if above change } // Constructor from model CbcHeuristic::CbcHeuristic(CbcModel & model) : model_(&model), when_(2), numberNodes_(200), feasibilityPumpOptions_(-1), fractionSmall_(1.0), heuristicName_("Unknown"), howOften_(1), decayFactor_(0.0), switches_(0), whereFrom_(DEFAULT_WHERE), shallowDepth_(1), howOftenShallow_(1), numInvocationsInShallow_(0), numInvocationsInDeep_(0), lastRunDeep_(0), numRuns_(0), minDistanceToRun_(1), runNodes_(), numCouldRun_(0), numberSolutionsFound_(0), numberNodesDone_(0), inputSolution_(NULL) {} void CbcHeuristic::gutsOfCopy(const CbcHeuristic & rhs) { model_ = rhs.model_; when_ = rhs.when_; numberNodes_ = rhs.numberNodes_; feasibilityPumpOptions_ = rhs.feasibilityPumpOptions_; fractionSmall_ = rhs.fractionSmall_; randomNumberGenerator_ = rhs.randomNumberGenerator_; heuristicName_ = rhs.heuristicName_; howOften_ = rhs.howOften_; decayFactor_ = rhs.decayFactor_; switches_ = rhs.switches_; whereFrom_ = rhs.whereFrom_; shallowDepth_ = rhs.shallowDepth_; howOftenShallow_ = rhs.howOftenShallow_; numInvocationsInShallow_ = rhs.numInvocationsInShallow_; numInvocationsInDeep_ = rhs.numInvocationsInDeep_; lastRunDeep_ = rhs.lastRunDeep_; numRuns_ = rhs.numRuns_; numCouldRun_ = rhs.numCouldRun_; minDistanceToRun_ = rhs.minDistanceToRun_; runNodes_ = rhs.runNodes_; numberSolutionsFound_ = rhs.numberSolutionsFound_; numberNodesDone_ = rhs.numberNodesDone_; if (rhs.inputSolution_) { int numberColumns = model_->getNumCols(); setInputSolution(rhs.inputSolution_, rhs.inputSolution_[numberColumns]); } } // Copy constructor CbcHeuristic::CbcHeuristic(const CbcHeuristic & rhs) { inputSolution_ = NULL; gutsOfCopy(rhs); } // Assignment operator CbcHeuristic & CbcHeuristic::operator=( const CbcHeuristic & rhs) { if (this != &rhs) { gutsOfDelete(); gutsOfCopy(rhs); } return *this; } void CbcHeurDebugNodes(CbcModel* model_) { CbcNode* node = model_->currentNode(); CbcNodeInfo* nodeInfo = node->nodeInfo(); std::cout << "===============================================================\n"; while (nodeInfo) { const CbcNode* node = nodeInfo->owner(); printf("nodeinfo: node %i\n", nodeInfo->nodeNumber()); { const CbcIntegerBranchingObject* brPrint = dynamic_cast(nodeInfo->parentBranch()); if (!brPrint) { printf(" parentBranch: NULL\n"); } else { const double* downBounds = brPrint->downBounds(); const double* upBounds = brPrint->upBounds(); int variable = brPrint->variable(); int way = brPrint->way(); printf(" parentBranch: var %i downBd [%i,%i] upBd [%i,%i] way %i\n", variable, static_cast(downBounds[0]), static_cast(downBounds[1]), static_cast(upBounds[0]), static_cast(upBounds[1]), way); } } if (! node) { printf(" owner: NULL\n"); } else { printf(" owner: node %i depth %i onTree %i active %i", node->nodeNumber(), node->depth(), node->onTree(), node->active()); const OsiBranchingObject* osibr = nodeInfo->owner()->branchingObject(); const CbcBranchingObject* cbcbr = dynamic_cast(osibr); const CbcIntegerBranchingObject* brPrint = dynamic_cast(cbcbr); if (!brPrint) { printf(" ownerBranch: NULL\n"); } else { const double* downBounds = brPrint->downBounds(); const double* upBounds = brPrint->upBounds(); int variable = brPrint->variable(); int way = brPrint->way(); printf(" ownerbranch: var %i downBd [%i,%i] upBd [%i,%i] way %i\n", variable, static_cast(downBounds[0]), static_cast(downBounds[1]), static_cast(upBounds[0]), static_cast(upBounds[1]), way); } } nodeInfo = nodeInfo->parent(); } } void CbcHeuristic::debugNodes() { CbcHeurDebugNodes(model_); } void CbcHeuristic::printDistanceToNodes() { const CbcNode* currentNode = model_->currentNode(); if (currentNode != NULL) { CbcHeuristicNode* nodeDesc = new CbcHeuristicNode(*model_); for (int i = runNodes_.size() - 1; i >= 0; --i) { nodeDesc->distance(runNodes_.node(i)); } runNodes_.append(nodeDesc); } } bool CbcHeuristic::shouldHeurRun(int whereFrom) { assert (whereFrom >= 0 && whereFrom < 16); // take off 8 (code - likes new solution) whereFrom &= 7; if ((whereFrom_&(1 << whereFrom)) == 0) return false; // No longer used for original purpose - so use for ever run at all JJF #ifndef JJF_ONE // Don't run if hot start or no rows! if (model_ && (model_->hotstartSolution()||!model_->getNumRows())) return false; else return true; #else #ifdef JJF_ZERO const CbcNode* currentNode = model_->currentNode(); if (currentNode == NULL) { return false; } debugNodes(); // return false; const int depth = currentNode->depth(); #else int depth = model_->currentDepth(); #endif const int nodeCount = model_->getNodeCount(); // FIXME: check that this is // correct in parallel if (nodeCount == 0 || depth <= shallowDepth_) { // what to do when we are in the shallow part of the tree if (model_->getCurrentPassNumber() == 1) { // first time in the node... numInvocationsInShallow_ = 0; } ++numInvocationsInShallow_; // Very large howOftenShallow_ will give the original test: // (model_->getCurrentPassNumber() != 1) // if ((numInvocationsInShallow_ % howOftenShallow_) != 1) { if ((numInvocationsInShallow_ % howOftenShallow_) != 0) { return false; } // LL: should we save these nodes in the list of nodes where the heur was // LL: run? #ifndef JJF_ONE if (currentNode != NULL) { // Get where we are and create the appropriate CbcHeuristicNode object CbcHeuristicNode* nodeDesc = new CbcHeuristicNode(*model_); runNodes_.append(nodeDesc); } #endif } else { // deeper in the tree if (model_->getCurrentPassNumber() == 1) { // first time in the node... ++numInvocationsInDeep_; } if (numInvocationsInDeep_ - lastRunDeep_ < howOften_) { return false; } if (model_->getCurrentPassNumber() != 1) { // Run the heuristic only when first entering the node. // LL: I don't think this is right. It should run just before strong // LL: branching, I believe. return false; } // Get where we are and create the appropriate CbcHeuristicNode object CbcHeuristicNode* nodeDesc = new CbcHeuristicNode(*model_); //#ifdef PRINT_DEBUG #ifndef JJF_ONE const double minDistanceToRun = 1.5 * log((double)depth) / log((double)2); #else const double minDistanceToRun = minDistanceToRun_; #endif #ifdef PRINT_DEBUG double minDistance = nodeDesc->minDistance(runNodes_); std::cout << "minDistance = " << minDistance << ", minDistanceToRun = " << minDistanceToRun << std::endl; #endif if (nodeDesc->minDistanceIsSmall(runNodes_, minDistanceToRun)) { delete nodeDesc; return false; } runNodes_.append(nodeDesc); lastRunDeep_ = numInvocationsInDeep_; // ++lastRunDeep_; } ++numRuns_; return true; #endif } bool CbcHeuristic::shouldHeurRun_randomChoice() { if (!when_) return false; int depth = model_->currentDepth(); // when_ -999 is special marker to force to run if (depth != 0 && when_ != -999) { const double numerator = depth * depth; const double denominator = exp(depth * log(2.0)); double probability = numerator / denominator; double randomNumber = randomNumberGenerator_.randomDouble(); int when = when_ % 100; if (when > 2 && when < 8) { /* JJF adjustments 3 only at root and if no solution 4 only at root and if this heuristic has not got solution 5 as 3 but decay more 6 decay 7 run up to 2 times if solution found 4 otherwise */ switch (when) { case 3: default: if (model_->bestSolution()) probability = -1.0; break; case 4: if (numberSolutionsFound_) probability = -1.0; break; case 5: assert (decayFactor_); if (model_->bestSolution()) { probability = -1.0; } else if (numCouldRun_ > 1000) { decayFactor_ *= 0.99; probability *= decayFactor_; } break; case 6: if (depth >= 3) { if ((numCouldRun_ % howOften_) == 0 && numberSolutionsFound_*howOften_ < numCouldRun_) { #ifdef COIN_DEVELOP int old = howOften_; #endif howOften_ = CoinMin(CoinMax(static_cast (howOften_ * 1.1), howOften_ + 1), 1000000); #ifdef COIN_DEVELOP printf("Howoften changed from %d to %d for %s\n", old, howOften_, heuristicName_.c_str()); #endif } probability = 1.0 / howOften_; if (model_->bestSolution()) probability *= 0.5; } break; case 7: if ((model_->bestSolution() && numRuns_ >= 2) || numRuns_ >= 4) probability = -1.0; break; } } if (randomNumber > probability) return false; if (model_->getCurrentPassNumber() > 1) return false; #ifdef COIN_DEVELOP printf("Running %s, random %g probability %g\n", heuristicName_.c_str(), randomNumber, probability); #endif } else { #ifdef COIN_DEVELOP printf("Running %s, depth %d when %d\n", heuristicName_.c_str(), depth, when_); #endif } ++numRuns_; return true; } // Resets stuff if model changes void CbcHeuristic::resetModel(CbcModel * model) { model_ = model; } // Set seed void CbcHeuristic::setSeed(int value) { if (value==0) { double time = fabs(CoinGetTimeOfDay()); while (time>=COIN_INT_MAX) time *= 0.5; value = static_cast(time); char printArray[100]; sprintf(printArray, "using time of day seed was changed from %d to %d", randomNumberGenerator_.getSeed(), value); if (model_) model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << printArray << CoinMessageEol; } randomNumberGenerator_.setSeed(value); } // Get seed int CbcHeuristic::getSeed() const { return randomNumberGenerator_.getSeed(); } // Create C++ lines to get to current state void CbcHeuristic::generateCpp( FILE * fp, const char * heuristic) { // hard coded as CbcHeuristic virtual if (when_ != 2) fprintf(fp, "3 %s.setWhen(%d);\n", heuristic, when_); else fprintf(fp, "4 %s.setWhen(%d);\n", heuristic, when_); if (numberNodes_ != 200) fprintf(fp, "3 %s.setNumberNodes(%d);\n", heuristic, numberNodes_); else fprintf(fp, "4 %s.setNumberNodes(%d);\n", heuristic, numberNodes_); if (feasibilityPumpOptions_ != -1) fprintf(fp, "3 %s.setFeasibilityPumpOptions(%d);\n", heuristic, feasibilityPumpOptions_); else fprintf(fp, "4 %s.setFeasibilityPumpOptions(%d);\n", heuristic, feasibilityPumpOptions_); if (fractionSmall_ != 1.0) fprintf(fp, "3 %s.setFractionSmall(%g);\n", heuristic, fractionSmall_); else fprintf(fp, "4 %s.setFractionSmall(%g);\n", heuristic, fractionSmall_); if (heuristicName_ != "Unknown") fprintf(fp, "3 %s.setHeuristicName(\"%s\");\n", heuristic, heuristicName_.c_str()) ; else fprintf(fp, "4 %s.setHeuristicName(\"%s\");\n", heuristic, heuristicName_.c_str()) ; if (decayFactor_ != 0.0) fprintf(fp, "3 %s.setDecayFactor(%g);\n", heuristic, decayFactor_); else fprintf(fp, "4 %s.setDecayFactor(%g);\n", heuristic, decayFactor_); if (switches_ != 0) fprintf(fp, "3 %s.setSwitches(%d);\n", heuristic, switches_); else fprintf(fp, "4 %s.setSwitches(%d);\n", heuristic, switches_); if (whereFrom_ != DEFAULT_WHERE) fprintf(fp, "3 %s.setWhereFrom(%d);\n", heuristic, whereFrom_); else fprintf(fp, "4 %s.setWhereFrom(%d);\n", heuristic, whereFrom_); if (shallowDepth_ != 1) fprintf(fp, "3 %s.setShallowDepth(%d);\n", heuristic, shallowDepth_); else fprintf(fp, "4 %s.setShallowDepth(%d);\n", heuristic, shallowDepth_); if (howOftenShallow_ != 1) fprintf(fp, "3 %s.setHowOftenShallow(%d);\n", heuristic, howOftenShallow_); else fprintf(fp, "4 %s.setHowOftenShallow(%d);\n", heuristic, howOftenShallow_); if (minDistanceToRun_ != 1) fprintf(fp, "3 %s.setMinDistanceToRun(%d);\n", heuristic, minDistanceToRun_); else fprintf(fp, "4 %s.setMinDistanceToRun(%d);\n", heuristic, minDistanceToRun_); } // Destructor CbcHeuristic::~CbcHeuristic () { delete [] inputSolution_; } // update model void CbcHeuristic::setModel(CbcModel * model) { model_ = model; } /* Clone but .. type 0 clone solver, 1 clone continuous solver Add 2 to say without integer variables which are at low priority Add 4 to say quite likely infeasible so give up easily.*/ OsiSolverInterface * CbcHeuristic::cloneBut(int type) { OsiSolverInterface * solver; if ((type&1) == 0 || !model_->continuousSolver()) solver = model_->solver()->clone(); else solver = model_->continuousSolver()->clone(); #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver); #endif if ((type&2) != 0) { int n = model_->numberObjects(); int priority = model_->continuousPriority(); if (priority < COIN_INT_MAX) { for (int i = 0; i < n; i++) { const OsiObject * obj = model_->object(i); const CbcSimpleInteger * thisOne = dynamic_cast (obj); if (thisOne) { int iColumn = thisOne->columnNumber(); if (thisOne->priority() >= priority) solver->setContinuous(iColumn); } } } #ifdef COIN_HAS_CLP if (clpSolver) { for (int i = 0; i < n; i++) { const OsiObject * obj = model_->object(i); const CbcSimpleInteger * thisOne = dynamic_cast (obj); if (thisOne) { int iColumn = thisOne->columnNumber(); if (clpSolver->isOptionalInteger(iColumn)) clpSolver->setContinuous(iColumn); } } } #endif } #ifdef COIN_HAS_CLP if ((type&4) != 0 && clpSolver) { int options = clpSolver->getModelPtr()->moreSpecialOptions(); clpSolver->getModelPtr()->setMoreSpecialOptions(options | 64); } #endif return solver; } // Whether to exit at once on gap bool CbcHeuristic::exitNow(double bestObjective) const { if ((switches_&2048) != 0) { // exit may be forced - but unset for next time switches_ &= ~2048; if ((switches_&1024) != 0) return true; } else if ((switches_&1) == 0) { return false; } // See if can stop on gap OsiSolverInterface * solver = model_->solver(); double bestPossibleObjective = solver->getObjValue() * solver->getObjSense(); double absGap = CoinMax(model_->getAllowableGap(), model_->getHeuristicGap()); double fracGap = CoinMax(model_->getAllowableFractionGap(), model_->getHeuristicFractionGap()); double testGap = CoinMax(absGap, fracGap * CoinMax(fabs(bestObjective), fabs(bestPossibleObjective))); if (bestObjective - bestPossibleObjective < testGap && model_->getCutoffIncrement() >= 0.0) { return true; } else { return false; } } #ifdef HISTORY_STATISTICS extern bool getHistoryStatistics_; #endif static double sizeRatio(int numberRowsNow, int numberColumnsNow, int numberRowsStart, int numberColumnsStart) { double valueNow; if (numberRowsNow*10 > numberColumnsNow || numberColumnsNow < 200) { valueNow = 2 * numberRowsNow + numberColumnsNow; } else { // long and thin - rows are more important if (numberRowsNow*40 > numberColumnsNow) valueNow = 10 * numberRowsNow + numberColumnsNow; else valueNow = 200 * numberRowsNow + numberColumnsNow; } double valueStart; if (numberRowsStart*10 > numberColumnsStart || numberColumnsStart < 200) { valueStart = 2 * numberRowsStart + numberColumnsStart; } else { // long and thin - rows are more important if (numberRowsStart*40 > numberColumnsStart) valueStart = 10 * numberRowsStart + numberColumnsStart; else valueStart = 200 * numberRowsStart + numberColumnsStart; } //printf("sizeProblem Now %g, %d rows, %d columns\nsizeProblem Start %g, %d rows, %d columns\n", // valueNow,numberRowsNow,numberColumnsNow, // valueStart,numberRowsStart,numberColumnsStart); if (10*numberRowsNow < 8*numberRowsStart || 10*numberColumnsNow < 7*numberColumnsStart) return valueNow / valueStart; else if (10*numberRowsNow < 9*numberRowsStart) return 1.1*(valueNow / valueStart); else if (numberRowsNow < numberRowsStart) return 1.5*(valueNow / valueStart); else return 2.0*(valueNow / valueStart); } // Do mini branch and bound (return 1 if solution) int CbcHeuristic::smallBranchAndBound(OsiSolverInterface * solver, int numberNodes, double * newSolution, double & newSolutionValue, double cutoff, std::string name) const { // size before int shiftRows = 0; if (numberNodes < 0) shiftRows = solver->getNumRows() - numberNodes_; int numberRowsStart = solver->getNumRows() - shiftRows; int numberColumnsStart = solver->getNumCols(); #ifdef CLP_INVESTIGATE printf("%s has %d rows, %d columns\n", name.c_str(), solver->getNumRows(), solver->getNumCols()); #endif // Use this fraction double fractionSmall = fractionSmall_; double before = 2 * numberRowsStart + numberColumnsStart; if (before > 40000.0) { // fairly large - be more conservative double multiplier = 1.0 - 0.3 * CoinMin(100000.0, before - 40000.0) / 100000.0; if (multiplier < 1.0) { fractionSmall *= multiplier; #ifdef CLP_INVESTIGATE printf("changing fractionSmall from %g to %g for %s\n", fractionSmall_, fractionSmall, name.c_str()); #endif } } #ifdef COIN_HAS_CLP OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver); if (osiclp && (osiclp->specialOptions()&65536) == 0) { // go faster stripes if (osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500) { osiclp->setupForRepeatedUse(2, 0); } else { osiclp->setupForRepeatedUse(0, 0); } // Turn this off if you get problems // Used to be automatically set osiclp->setSpecialOptions(osiclp->specialOptions() | (128 + 64 - 128)); ClpSimplex * lpSolver = osiclp->getModelPtr(); lpSolver->setSpecialOptions(lpSolver->specialOptions() | 0x01000000); // say is Cbc (and in branch and bound) lpSolver->setSpecialOptions(lpSolver->specialOptions() | (/*16384+*/4096 + 512 + 128)); } #endif #ifdef HISTORY_STATISTICS getHistoryStatistics_ = false; #endif #ifdef COIN_DEVELOP int status = 0; #endif int logLevel = model_->logLevel(); #define LEN_PRINT 250 char generalPrint[LEN_PRINT]; // Do presolve to see if possible int numberColumns = solver->getNumCols(); char * reset = NULL; int returnCode = 1; int saveModelOptions = model_->specialOptions(); //assert ((saveModelOptions&2048) == 0); model_->setSpecialOptions(saveModelOptions | 2048); { int saveLogLevel = solver->messageHandler()->logLevel(); if (saveLogLevel == 1) solver->messageHandler()->setLogLevel(0); OsiPresolve * pinfo = new OsiPresolve(); int presolveActions = 0; // Allow dual stuff on integers presolveActions = 1; // Do not allow all +1 to be tampered with //if (allPlusOnes) //presolveActions |= 2; // allow transfer of costs // presolveActions |= 4; pinfo->setPresolveActions(presolveActions); OsiSolverInterface * presolvedModel = pinfo->presolvedModel(*solver, 1.0e-8, true, 2); delete pinfo; // see if too big if (presolvedModel) { int afterRows = presolvedModel->getNumRows(); int afterCols = presolvedModel->getNumCols(); //#define COIN_DEVELOP #ifdef COIN_DEVELOP_z if (numberNodes < 0) { solver->writeMpsNative("before.mps", NULL, NULL, 2, 1); presolvedModel->writeMpsNative("after1.mps", NULL, NULL, 2, 1); } #endif delete presolvedModel; double ratio = sizeRatio(afterRows - shiftRows, afterCols, numberRowsStart, numberColumnsStart); double after = 2 * afterRows + afterCols; if (ratio > fractionSmall && after > 300 && numberNodes >= 0) { // Need code to try again to compress further using used const int * used = model_->usedInSolution(); int maxUsed = 0; int iColumn; const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn]) { if (solver->isBinary(iColumn)) maxUsed = CoinMax(maxUsed, used[iColumn]); } } if (maxUsed) { reset = new char [numberColumns]; int nFix = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { reset[iColumn] = 0; if (upper[iColumn] > lower[iColumn]) { if (solver->isBinary(iColumn) && used[iColumn] == maxUsed) { bool setValue = true; if (maxUsed == 1) { double randomNumber = randomNumberGenerator_.randomDouble(); if (randomNumber > 0.3) setValue = false; } if (setValue) { reset[iColumn] = 1; solver->setColLower(iColumn, 1.0); nFix++; } } } } pinfo = new OsiPresolve(); presolveActions = 0; // Allow dual stuff on integers presolveActions = 1; // Do not allow all +1 to be tampered with //if (allPlusOnes) //presolveActions |= 2; // allow transfer of costs // presolveActions |= 4; pinfo->setPresolveActions(presolveActions); presolvedModel = pinfo->presolvedModel(*solver, 1.0e-8, true, 2); delete pinfo; if (presolvedModel) { // see if too big int afterRows2 = presolvedModel->getNumRows(); int afterCols2 = presolvedModel->getNumCols(); delete presolvedModel; double ratio = sizeRatio(afterRows2 - shiftRows, afterCols2, numberRowsStart, numberColumnsStart); double after = 2 * afterRows2 + afterCols2; if (ratio > fractionSmall && (after > 300 || numberNodes < 0)) { sprintf(generalPrint, "Full problem %d rows %d columns, reduced to %d rows %d columns - %d fixed gives %d, %d - still too large", solver->getNumRows(), solver->getNumCols(), afterRows, afterCols, nFix, afterRows2, afterCols2); // If much too big - give up if (ratio > 0.75) returnCode = -1; } else { sprintf(generalPrint, "Full problem %d rows %d columns, reduced to %d rows %d columns - %d fixed gives %d, %d - ok now", solver->getNumRows(), solver->getNumCols(), afterRows, afterCols, nFix, afterRows2, afterCols2); } model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << generalPrint << CoinMessageEol; } else { returnCode = 2; // infeasible } } } else if (ratio > fractionSmall && after > 300 && numberNodes >=0) { returnCode = -1; } } else { returnCode = 2; // infeasible } solver->messageHandler()->setLogLevel(saveLogLevel); } if (returnCode == 2 || returnCode == -1) { model_->setSpecialOptions(saveModelOptions); delete [] reset; #ifdef HISTORY_STATISTICS getHistoryStatistics_ = true; #endif //printf("small no good\n"); return returnCode; } // Reduce printout bool takeHint; OsiHintStrength strength; solver->getHintParam(OsiDoReducePrint, takeHint, strength); solver->setHintParam(OsiDoReducePrint, true, OsiHintTry); solver->setHintParam(OsiDoPresolveInInitial, false, OsiHintTry); double signedCutoff = cutoff*solver->getObjSense(); solver->setDblParam(OsiDualObjectiveLimit, signedCutoff); solver->initialSolve(); if (solver->isProvenOptimal()) { CglPreProcess process; OsiSolverInterface * solver2 = NULL; if ((model_->moreSpecialOptions()&65536)!=0) process.setOptions(2+4+8); // no cuts /* Do not try and produce equality cliques and do up to 2 passes (normally) 5 if restart */ int numberPasses = 2; if (numberNodes < 0) { numberPasses = 5; // Say some rows cuts int numberRows = solver->getNumRows(); if (numberNodes_ < numberRows && true /* think */) { char * type = new char[numberRows]; memset(type, 0, numberNodes_); memset(type + numberNodes_, 1, numberRows - numberNodes_); process.passInRowTypes(type, numberRows); delete [] type; } } if (logLevel <= 1) process.messageHandler()->setLogLevel(0); if (!solver->defaultHandler()&& solver->messageHandler()->logLevel(0)!=-1000) process.passInMessageHandler(solver->messageHandler()); solver2 = process.preProcessNonDefault(*solver, false, numberPasses); if (!solver2) { if (logLevel > 1) printf("Pre-processing says infeasible\n"); returnCode = 2; // so will be infeasible } else { #ifdef COIN_DEVELOP_z if (numberNodes < 0) { solver2->writeMpsNative("after2.mps", NULL, NULL, 2, 1); } #endif // see if too big double ratio = sizeRatio(solver2->getNumRows() - shiftRows, solver2->getNumCols(), numberRowsStart, numberColumnsStart); double after = 2 * solver2->getNumRows() + solver2->getNumCols(); if (ratio > fractionSmall && (after > 300 || numberNodes < 0)) { sprintf(generalPrint, "Full problem %d rows %d columns, reduced to %d rows %d columns - too large", solver->getNumRows(), solver->getNumCols(), solver2->getNumRows(), solver2->getNumCols()); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << generalPrint << CoinMessageEol; returnCode = -1; //printf("small no good2\n"); } else { sprintf(generalPrint, "Full problem %d rows %d columns, reduced to %d rows %d columns", solver->getNumRows(), solver->getNumCols(), solver2->getNumRows(), solver2->getNumCols()); model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << generalPrint << CoinMessageEol; } if (returnCode == 1) { solver2->resolve(); CbcModel model(*solver2); // move seed across model.randomNumberGenerator()->setSeed(model_->randomNumberGenerator()->getSeed()); if (numberNodes >= 0) { // normal model.setSpecialOptions(saveModelOptions | 2048); if (logLevel <= 1 && feasibilityPumpOptions_ != -3) model.setLogLevel(0); else model.setLogLevel(logLevel); // No small fathoming model.setFastNodeDepth(-1); model.setCutoff(signedCutoff); model.setStrongStrategy(0); // Don't do if original fraction > 1.0 and too large if (fractionSmall_>1.0 && fractionSmall_ < 1000000.0) { /* 1.4 means -1 nodes if >.4 2.4 means -1 nodes if >.5 and 0 otherwise 3.4 means -1 nodes if >.6 and 0 or 5 4.4 means -1 nodes if >.7 and 0, 5 or 10 */ double fraction = fractionSmall_-floor(fractionSmall_); if (ratio>fraction) { int type = static_cast(floor(fractionSmall_*0.1)); int over = static_cast(ceil(ratio-fraction)); int maxNodes[]={-1,0,5,10}; if (type>over) numberNodes=maxNodes[type-over]; else numberNodes=-1; } } model.setMaximumNodes(numberNodes); model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); if ((saveModelOptions&2048) == 0) model.setMoreSpecialOptions(model_->moreSpecialOptions()); // off conflict analysis model.setMoreSpecialOptions(model.moreSpecialOptions()&~4194304); // Lightweight CbcStrategyDefaultSubTree strategy(model_, 1, 5, 1, 0); model.setStrategy(strategy); model.solver()->setIntParam(OsiMaxNumIterationHotStart, 10); model.setMaximumCutPassesAtRoot(CoinMin(20, CoinAbs(model_->getMaximumCutPassesAtRoot()))); model.setMaximumCutPasses(CoinMin(10, model_->getMaximumCutPasses())); } else { model.setSpecialOptions(saveModelOptions); model_->messageHandler()->message(CBC_RESTART, model_->messages()) << solver2->getNumRows() << solver2->getNumCols() << CoinMessageEol; // going for full search and copy across more stuff model.gutsOfCopy(*model_, 2); assert (!model_->heuristicModel()); model_->setHeuristicModel(&model); for (int i = 0; i < model.numberCutGenerators(); i++) { CbcCutGenerator * generator = model.cutGenerator(i); CglGomory * gomory = dynamic_cast (generator->generator()); if (gomory&&gomory->originalSolver()) gomory->passInOriginalSolver(model.solver()); generator->setTiming(true); // Turn on if was turned on int iOften = model_->cutGenerator(i)->howOften(); #ifdef CLP_INVESTIGATE printf("Gen %d often %d %d\n", i, generator->howOften(), iOften); #endif if (iOften > 0) generator->setHowOften(iOften % 1000000); if (model_->cutGenerator(i)->howOftenInSub() == -200) generator->setHowOften(-100); } model.setCutoff(signedCutoff); // make sure can't do nested search! but allow heuristics model.setSpecialOptions((model.specialOptions()&(~(512 + 2048))) | 1024); bool takeHint; OsiHintStrength strength; // Switch off printing if asked to model_->solver()->getHintParam(OsiDoReducePrint, takeHint, strength); model.solver()->setHintParam(OsiDoReducePrint, takeHint, strength); // no cut generators if none in parent CbcStrategyDefault strategy(model_->numberCutGenerators() ? 1 : -1, model_->numberStrong(), model_->numberBeforeTrust()); // Set up pre-processing - no strategy.setupPreProcessing(0); // was (4); model.setStrategy(strategy); //model.solver()->writeMps("crunched"); int numberCuts = process.cuts().sizeRowCuts(); if (numberCuts) { // add in cuts CglStored cuts = process.cuts(); model.addCutGenerator(&cuts, 1, "Stored from first"); model.cutGenerator(model.numberCutGenerators()-1)->setGlobalCuts(true); } } // Do search if (logLevel > 1) model_->messageHandler()->message(CBC_START_SUB, model_->messages()) << name << model.getMaximumNodes() << CoinMessageEol; // probably faster to use a basis to get integer solutions model.setSpecialOptions(model.specialOptions() | 2); #ifdef CBC_THREAD if (model_->getNumberThreads() > 0 && (model_->getThreadMode()&4) != 0) { // See if at root node bool atRoot = model_->getNodeCount() == 0; int passNumber = model_->getCurrentPassNumber(); if (atRoot && passNumber == 1) model.setNumberThreads(model_->getNumberThreads()); } #endif model.setParentModel(*model_); model.setMaximumSolutions(model_->getMaximumSolutions()); model.setOriginalColumns(process.originalColumns()); model.setSearchStrategy(-1); // If no feasibility pump then insert a lightweight one if (feasibilityPumpOptions_ >= 0 || feasibilityPumpOptions_ == -2) { CbcHeuristicFPump * fpump = NULL; for (int i = 0; i < model.numberHeuristics(); i++) { CbcHeuristicFPump* pump = dynamic_cast(model.heuristic(i)); if (pump) { fpump = pump; break; } } if (!fpump) { CbcHeuristicFPump heuristic4; // use any cutoff heuristic4.setFakeCutoff(0.5*COIN_DBL_MAX); if (fractionSmall_<=1.0) heuristic4.setMaximumPasses(10); int pumpTune = feasibilityPumpOptions_; if (pumpTune==-2) pumpTune = 4; // proximity if (pumpTune > 0) { /* >=10000000 for using obj >=1000000 use as accumulate switch >=1000 use index+1 as number of large loops >=100 use 0.05 objvalue as increment %100 == 10,20 etc for experimentation 1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds 4 and static continuous, 5 as 3 but no internal integers 6 as 3 but all slack basis! */ double value = solver2->getObjSense() * solver2->getObjValue(); int w = pumpTune / 10; int ix = w % 10; w /= 10; int c = w % 10; w /= 10; int r = w; int accumulate = r / 1000; r -= 1000 * accumulate; if (accumulate >= 10) { int which = accumulate / 10; accumulate -= 10 * which; which--; // weights and factors double weight[] = {0.1, 0.1, 0.5, 0.5, 1.0, 1.0, 5.0, 5.0}; double factor[] = {0.1, 0.5, 0.1, 0.5, 0.1, 0.5, 0.1, 0.5}; heuristic4.setInitialWeight(weight[which]); heuristic4.setWeightFactor(factor[which]); } // fake cutoff if (c) { double cutoff; solver2->getDblParam(OsiDualObjectiveLimit, cutoff); cutoff = CoinMin(cutoff, value + 0.1 * fabs(value) * c); heuristic4.setFakeCutoff(cutoff); } if (r) { // also set increment //double increment = (0.01*i+0.005)*(fabs(value)+1.0e-12); double increment = 0.0; heuristic4.setAbsoluteIncrement(increment); heuristic4.setAccumulate(accumulate); heuristic4.setMaximumRetries(r + 1); } pumpTune = pumpTune % 100; if (pumpTune == 6) pumpTune = 13; if (pumpTune != 13) pumpTune = pumpTune % 10; heuristic4.setWhen(pumpTune); if (ix) { heuristic4.setFeasibilityPumpOptions(ix*10); } } model.addHeuristic(&heuristic4, "feasibility pump", 0); } } else if (feasibilityPumpOptions_==-3) { // add all (except this) for (int i = 0; i < model_->numberHeuristics(); i++) { if (strcmp(heuristicName(),model_->heuristic(i)->heuristicName())) model.addHeuristic(model_->heuristic(i)); } } //printf("sol %x\n",inputSolution_); if (inputSolution_) { // translate and add a serendipity heuristic int numberColumns = solver2->getNumCols(); const int * which = process.originalColumns(); OsiSolverInterface * solver3 = solver2->clone(); for (int i = 0; i < numberColumns; i++) { if (solver3->isInteger(i)) { int k = which[i]; double value = inputSolution_[k]; //if (value) //printf("orig col %d now %d val %g\n", // k,i,value); solver3->setColLower(i, value); solver3->setColUpper(i, value); } } solver3->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); solver3->resolve(); if (!solver3->isProvenOptimal()) { // Try just setting nonzeros OsiSolverInterface * solver4 = solver2->clone(); for (int i = 0; i < numberColumns; i++) { if (solver4->isInteger(i)) { int k = which[i]; double value = floor(inputSolution_[k] + 0.5); if (value) { solver3->setColLower(i, value); solver3->setColUpper(i, value); } } } solver4->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); solver4->resolve(); int nBad = -1; if (solver4->isProvenOptimal()) { nBad = 0; const double * solution = solver4->getColSolution(); for (int i = 0; i < numberColumns; i++) { if (solver4->isInteger(i)) { double value = floor(solution[i] + 0.5); if (fabs(value - solution[i]) > 1.0e-6) nBad++; } } } if (nBad) { delete solver4; } else { delete solver3; solver3 = solver4; } } if (solver3->isProvenOptimal()) { // good CbcSerendipity heuristic(model); double value = solver3->getObjSense() * solver3->getObjValue(); heuristic.setInputSolution(solver3->getColSolution(), value); value = value + 1.0e-7*(1.0 + fabs(value)); value *= solver3->getObjSense(); model.setCutoff(value); model.addHeuristic(&heuristic, "Previous solution", 0); //printf("added seren\n"); } else { double value = model_->getMinimizationObjValue(); value = value + 1.0e-7*(1.0 + fabs(value)); value *= solver3->getObjSense(); model.setCutoff(value); #ifdef CLP_INVESTIGATE printf("NOT added seren\n"); solver3->writeMps("bad_seren"); solver->writeMps("orig_seren"); #endif } delete solver3; } if (model_->searchStrategy() == 2) { model.setNumberStrong(5); model.setNumberBeforeTrust(5); } if (model.getNumCols()) { if (numberNodes >= 0) { setCutAndHeuristicOptions(model); // not too many iterations model.setMaximumNumberIterations(100*(numberNodes + 10)); // Not fast stuff model.setFastNodeDepth(-1); } else if (model.fastNodeDepth() >= 1000000) { // already set model.setFastNodeDepth(model.fastNodeDepth() - 1000000); } model.setWhenCuts(999998); #define ALWAYS_DUAL #ifdef ALWAYS_DUAL OsiSolverInterface * solverD = model.solver(); bool takeHint; OsiHintStrength strength; solverD->getHintParam(OsiDoDualInResolve, takeHint, strength); solverD->setHintParam(OsiDoDualInResolve, true, OsiHintDo); #endif model.passInEventHandler(model_->getEventHandler()); // say model_ is sitting there int saveOptions = model_->specialOptions(); model_->setSpecialOptions(saveOptions|1048576); model.branchAndBound(); model_->setHeuristicModel(NULL); model_->setSpecialOptions(saveOptions); #ifdef ALWAYS_DUAL solverD = model.solver(); solverD->setHintParam(OsiDoDualInResolve, takeHint, strength); #endif numberNodesDone_ = model.getNodeCount(); #ifdef COIN_DEVELOP printf("sub branch %d nodes, %d iterations - max %d\n", model.getNodeCount(), model.getIterationCount(), 100*(numberNodes + 10)); #endif if (numberNodes < 0) { model_->incrementIterationCount(model.getIterationCount()); model_->incrementNodeCount(model.getNodeCount()); // update best solution (in case ctrl-c) // !!! not a good idea - think a bit harder //model_->setMinimizationObjValue(model.getMinimizationObjValue()); for (int iGenerator = 0; iGenerator < model.numberCutGenerators(); iGenerator++) { CbcCutGenerator * generator = model.cutGenerator(iGenerator); sprintf(generalPrint, "%s was tried %d times and created %d cuts of which %d were active after adding rounds of cuts (%.3f seconds)", generator->cutGeneratorName(), generator->numberTimesEntered(), generator->numberCutsInTotal() + generator->numberColumnCuts(), generator->numberCutsActive(), generator->timeInCutGenerator()); CglStored * stored = dynamic_cast(generator->generator()); if (stored && !generator->numberCutsInTotal()) continue; #ifndef CLP_INVESTIGATE CglImplication * implication = dynamic_cast(generator->generator()); if (implication) continue; #endif model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << generalPrint << CoinMessageEol; } } } else { // empty model model.setMinimizationObjValue(model.solver()->getObjSense()*model.solver()->getObjValue()); } if (logLevel > 1) model_->messageHandler()->message(CBC_END_SUB, model_->messages()) << name << CoinMessageEol; if (model.getMinimizationObjValue() < CoinMin(cutoff, 1.0e30)) { // solution if (model.getNumCols()) returnCode = model.isProvenOptimal() ? 3 : 1; else returnCode = 3; // post process #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model.solver()); if (clpSolver) { ClpSimplex * lpSolver = clpSolver->getModelPtr(); lpSolver->setSpecialOptions(lpSolver->specialOptions() | 0x01000000); // say is Cbc (and in branch and bound) } #endif //if (fractionSmall_ < 1000000.0) process.postProcess(*model.solver()); if (solver->isProvenOptimal() && solver->getObjValue()*solver->getObjSense() < cutoff) { // Solution now back in solver int numberColumns = solver->getNumCols(); memcpy(newSolution, solver->getColSolution(), numberColumns*sizeof(double)); newSolutionValue = model.getMinimizationObjValue(); } else { // odd - but no good returnCode = 0; // so will be infeasible } } else { // no good returnCode = model.isProvenInfeasible() ? 2 : 0; // so will be infeasible } int totalNumberIterations = model.getIterationCount() + process.numberIterationsPre() + process.numberIterationsPost(); if (totalNumberIterations > 100*(numberNodes + 10) && fractionSmall_ < 1000000.0) { // only allow smaller problems fractionSmall = fractionSmall_; fractionSmall_ *= 0.9; #ifdef CLP_INVESTIGATE printf("changing fractionSmall from %g to %g for %s as %d iterations\n", fractionSmall, fractionSmall_, name.c_str(), totalNumberIterations); #endif } if (model.status() == 5) model_->sayEventHappened(); #ifdef COIN_DEVELOP if (model.isProvenInfeasible()) status = 1; else if (model.isProvenOptimal()) status = 2; #endif } } } else { returnCode = 2; // infeasible finished } model_->setSpecialOptions(saveModelOptions); model_->setLogLevel(logLevel); if (returnCode == 1 || returnCode == 2) { OsiSolverInterface * solverC = model_->continuousSolver(); if (false && solverC) { const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * lowerC = solverC->getColLower(); const double * upperC = solverC->getColUpper(); bool good = true; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (solverC->isInteger(iColumn)) { if (lower[iColumn] > lowerC[iColumn] && upper[iColumn] < upperC[iColumn]) { good = false; printf("CUT - can't add\n"); break; } } } if (good) { double * cut = new double [numberColumns]; int * which = new int [numberColumns]; double rhs = -1.0; int n = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (solverC->isInteger(iColumn)) { if (lower[iColumn] == upperC[iColumn]) { rhs += lower[iColumn]; cut[n] = 1.0; which[n++] = iColumn; } else if (upper[iColumn] == lowerC[iColumn]) { rhs -= upper[iColumn]; cut[n] = -1.0; which[n++] = iColumn; } } } printf("CUT has %d entries\n", n); OsiRowCut newCut; newCut.setLb(-COIN_DBL_MAX); newCut.setUb(rhs); newCut.setRow(n, which, cut, false); model_->makeGlobalCut(newCut); delete [] cut; delete [] which; } } #ifdef COIN_DEVELOP if (status == 1) printf("heuristic could add cut because infeasible (%s)\n", heuristicName_.c_str()); else if (status == 2) printf("heuristic could add cut because optimal (%s)\n", heuristicName_.c_str()); #endif } if (reset) { for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (reset[iColumn]) solver->setColLower(iColumn, 0.0); } delete [] reset; } #ifdef HISTORY_STATISTICS getHistoryStatistics_ = true; #endif solver->setHintParam(OsiDoReducePrint, takeHint, strength); return returnCode; } // Set input solution void CbcHeuristic::setInputSolution(const double * solution, double objValue) { delete [] inputSolution_; inputSolution_ = NULL; if (model_ && solution) { int numberColumns = model_->getNumCols(); inputSolution_ = new double [numberColumns+1]; memcpy(inputSolution_, solution, numberColumns*sizeof(double)); inputSolution_[numberColumns] = objValue; } } //############################################################################## inline int compare3BranchingObjects(const CbcBranchingObject* br0, const CbcBranchingObject* br1) { const int t0 = br0->type(); const int t1 = br1->type(); if (t0 < t1) { return -1; } if (t0 > t1) { return 1; } return br0->compareOriginalObject(br1); } //============================================================================== inline bool compareBranchingObjects(const CbcBranchingObject* br0, const CbcBranchingObject* br1) { return compare3BranchingObjects(br0, br1) < 0; } //============================================================================== void CbcHeuristicNode::gutsOfConstructor(CbcModel& model) { // CbcHeurDebugNodes(&model); CbcNode* node = model.currentNode(); brObj_ = new CbcBranchingObject*[node->depth()]; CbcNodeInfo* nodeInfo = node->nodeInfo(); int cnt = 0; while (nodeInfo->parentBranch() != NULL) { const OsiBranchingObject* br = nodeInfo->parentBranch(); const CbcBranchingObject* cbcbr = dynamic_cast(br); if (! cbcbr) { throw CoinError("CbcHeuristicNode can be used only with CbcBranchingObjects.\n", "gutsOfConstructor", "CbcHeuristicNode", __FILE__, __LINE__); } brObj_[cnt] = cbcbr->clone(); brObj_[cnt]->previousBranch(); ++cnt; nodeInfo = nodeInfo->parent(); } std::sort(brObj_, brObj_ + cnt, compareBranchingObjects); if (cnt <= 1) { numObjects_ = cnt; } else { numObjects_ = 0; CbcBranchingObject* br = NULL; // What should this be? for (int i = 1; i < cnt; ++i) { if (compare3BranchingObjects(brObj_[numObjects_], brObj_[i]) == 0) { int comp = brObj_[numObjects_]->compareBranchingObject(brObj_[i], br != 0); switch (comp) { case CbcRangeSame: // the same range case CbcRangeDisjoint: // disjoint decisions // should not happen! we are on a chain! abort(); case CbcRangeSubset: // brObj_[numObjects_] is a subset of brObj_[i] delete brObj_[i]; break; case CbcRangeSuperset: // brObj_[i] is a subset of brObj_[numObjects_] delete brObj_[numObjects_]; brObj_[numObjects_] = brObj_[i]; break; case CbcRangeOverlap: // overlap delete brObj_[i]; delete brObj_[numObjects_]; brObj_[numObjects_] = br; break; } continue; } else { brObj_[++numObjects_] = brObj_[i]; } } ++numObjects_; } } //============================================================================== CbcHeuristicNode::CbcHeuristicNode(CbcModel& model) { gutsOfConstructor(model); } //============================================================================== double CbcHeuristicNode::distance(const CbcHeuristicNode* node) const { const double disjointWeight = 1; const double overlapWeight = 0.4; const double subsetWeight = 0.2; int countDisjointWeight = 0; int countOverlapWeight = 0; int countSubsetWeight = 0; int i = 0; int j = 0; double dist = 0.0; #ifdef PRINT_DEBUG printf(" numObjects_ = %i, node->numObjects_ = %i\n", numObjects_, node->numObjects_); #endif while ( i < numObjects_ && j < node->numObjects_) { CbcBranchingObject* br0 = brObj_[i]; const CbcBranchingObject* br1 = node->brObj_[j]; #ifdef PRINT_DEBUG const CbcIntegerBranchingObject* brPrint0 = dynamic_cast(br0); const double* downBounds = brPrint0->downBounds(); const double* upBounds = brPrint0->upBounds(); int variable = brPrint0->variable(); int way = brPrint0->way(); printf(" br0: var %i downBd [%i,%i] upBd [%i,%i] way %i\n", variable, static_cast(downBounds[0]), static_cast(downBounds[1]), static_cast(upBounds[0]), static_cast(upBounds[1]), way); const CbcIntegerBranchingObject* brPrint1 = dynamic_cast(br1); downBounds = brPrint1->downBounds(); upBounds = brPrint1->upBounds(); variable = brPrint1->variable(); way = brPrint1->way(); printf(" br1: var %i downBd [%i,%i] upBd [%i,%i] way %i\n", variable, static_cast(downBounds[0]), static_cast(downBounds[1]), static_cast(upBounds[0]), static_cast(upBounds[1]), way); #endif const int brComp = compare3BranchingObjects(br0, br1); if (brComp < 0) { dist += subsetWeight; countSubsetWeight++; ++i; } else if (brComp > 0) { dist += subsetWeight; countSubsetWeight++; ++j; } else { const int comp = br0->compareBranchingObject(br1, false); switch (comp) { case CbcRangeSame: // do nothing break; case CbcRangeDisjoint: // disjoint decisions dist += disjointWeight; countDisjointWeight++; break; case CbcRangeSubset: // subset one way or another case CbcRangeSuperset: dist += subsetWeight; countSubsetWeight++; break; case CbcRangeOverlap: // overlap dist += overlapWeight; countOverlapWeight++; break; } ++i; ++j; } } dist += subsetWeight * (numObjects_ - i + node->numObjects_ - j); countSubsetWeight += (numObjects_ - i + node->numObjects_ - j); COIN_DETAIL_PRINT(printf("subset = %i, overlap = %i, disjoint = %i\n", countSubsetWeight, countOverlapWeight, countDisjointWeight)); return dist; } //============================================================================== CbcHeuristicNode::~CbcHeuristicNode() { for (int i = 0; i < numObjects_; ++i) { delete brObj_[i]; } delete [] brObj_; } //============================================================================== double CbcHeuristicNode::minDistance(const CbcHeuristicNodeList& nodeList) const { double minDist = COIN_DBL_MAX; for (int i = nodeList.size() - 1; i >= 0; --i) { minDist = CoinMin(minDist, distance(nodeList.node(i))); } return minDist; } //============================================================================== bool CbcHeuristicNode::minDistanceIsSmall(const CbcHeuristicNodeList& nodeList, const double threshold) const { for (int i = nodeList.size() - 1; i >= 0; --i) { if (distance(nodeList.node(i)) >= threshold) { continue; } else { return true; } } return false; } //============================================================================== double CbcHeuristicNode::avgDistance(const CbcHeuristicNodeList& nodeList) const { if (nodeList.size() == 0) { return COIN_DBL_MAX; } double sumDist = 0; for (int i = nodeList.size() - 1; i >= 0; --i) { sumDist += distance(nodeList.node(i)); } return sumDist / nodeList.size(); } //############################################################################## // Default Constructor CbcRounding::CbcRounding() : CbcHeuristic() { // matrix and row copy will automatically be empty seed_ = 7654321; down_ = NULL; up_ = NULL; equal_ = NULL; //whereFrom_ |= 16; // allow more often } // Constructor from model CbcRounding::CbcRounding(CbcModel & model) : CbcHeuristic(model) { // Get a copy of original matrix (and by row for rounding); assert(model.solver()); if (model.solver()->getNumRows()) { matrix_ = *model.solver()->getMatrixByCol(); matrixByRow_ = *model.solver()->getMatrixByRow(); validate(); } down_ = NULL; up_ = NULL; equal_ = NULL; seed_ = 7654321; //whereFrom_ |= 16; // allow more often } // Destructor CbcRounding::~CbcRounding () { delete [] down_; delete [] up_; delete [] equal_; } // Clone CbcHeuristic * CbcRounding::clone() const { return new CbcRounding(*this); } // Create C++ lines to get to current state void CbcRounding::generateCpp( FILE * fp) { CbcRounding other; fprintf(fp, "0#include \"CbcHeuristic.hpp\"\n"); fprintf(fp, "3 CbcRounding rounding(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "rounding"); if (seed_ != other.seed_) fprintf(fp, "3 rounding.setSeed(%d);\n", seed_); else fprintf(fp, "4 rounding.setSeed(%d);\n", seed_); fprintf(fp, "3 cbcModel->addHeuristic(&rounding);\n"); } //#define NEW_ROUNDING // Copy constructor CbcRounding::CbcRounding(const CbcRounding & rhs) : CbcHeuristic(rhs), matrix_(rhs.matrix_), matrixByRow_(rhs.matrixByRow_), seed_(rhs.seed_) { #ifdef NEW_ROUNDING int numberColumns = matrix_.getNumCols(); down_ = CoinCopyOfArray(rhs.down_, numberColumns); up_ = CoinCopyOfArray(rhs.up_, numberColumns); equal_ = CoinCopyOfArray(rhs.equal_, numberColumns); #else down_ = NULL; up_ = NULL; equal_ = NULL; #endif } // Assignment operator CbcRounding & CbcRounding::operator=( const CbcRounding & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); matrix_ = rhs.matrix_; matrixByRow_ = rhs.matrixByRow_; #ifdef NEW_ROUNDING delete [] down_; delete [] up_; delete [] equal_; int numberColumns = matrix_.getNumCols(); down_ = CoinCopyOfArray(rhs.down_, numberColumns); up_ = CoinCopyOfArray(rhs.up_, numberColumns); equal_ = CoinCopyOfArray(rhs.equal_, numberColumns); #else down_ = NULL; up_ = NULL; equal_ = NULL; #endif seed_ = rhs.seed_; } return *this; } // Resets stuff if model changes void CbcRounding::resetModel(CbcModel * model) { model_ = model; // Get a copy of original matrix (and by row for rounding); assert(model_->solver()); matrix_ = *model_->solver()->getMatrixByCol(); matrixByRow_ = *model_->solver()->getMatrixByRow(); validate(); } // See if rounding will give solution // Sets value of solution // Assumes rhs for original matrix still okay // At present only works with integers // Fix values if asked for // Returns 1 if solution, 0 if not int CbcRounding::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; // See if to do if (!when() || (when() % 10 == 1 && model_->phase() != 1) || (when() % 10 == 2 && (model_->phase() != 2 && model_->phase() != 3))) return 0; // switched off numRuns_++; OsiSolverInterface * solver = model_->solver(); double direction = solver->getObjSense(); double newSolutionValue = direction * solver->getObjValue(); return solution(solutionValue, betterSolution, newSolutionValue); } // See if rounding will give solution // Sets value of solution // Assumes rhs for original matrix still okay // At present only works with integers // Fix values if asked for // Returns 1 if solution, 0 if not int CbcRounding::solution(double & solutionValue, double * betterSolution, double newSolutionValue) { // See if to do if (!when() || (when() % 10 == 1 && model_->phase() != 1) || (when() % 10 == 2 && (model_->phase() != 2 && model_->phase() != 3))) return 0; // switched off OsiSolverInterface * solver = model_->solver(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); const double * solution = solver->getColSolution(); const double * objective = solver->getObjCoefficients(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); int numberRows = matrix_.getNumRows(); assert (numberRows <= solver->getNumRows()); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; double direction = solver->getObjSense(); //double newSolutionValue = direction*solver->getObjValue(); int returnCode = 0; // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); // Get solution array for heuristic solution int numberColumns = solver->getNumCols(); double * newSolution = new double [numberColumns]; memcpy(newSolution, solution, numberColumns*sizeof(double)); double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); for (i = 0; i < numberColumns; i++) { int j; double value = newSolution[i]; if (value < lower[i]) { value = lower[i]; newSolution[i] = value; } else if (value > upper[i]) { value = upper[i]; newSolution[i] = value; } if (value) { for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } // check was feasible - if not adjust (cleaning may move) for (i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i]) { //assert (rowActivity[i]>rowLower[i]-1000.0*primalTolerance); rowActivity[i] = rowLower[i]; } else if (rowActivity[i] > rowUpper[i]) { //assert (rowActivity[i] integerTolerance) { double below = floor(value); double newValue = newSolution[iColumn]; double cost = direction * objective[iColumn]; double move; if (cost > 0.0) { // try up move = 1.0 - (value - below); } else if (cost < 0.0) { // try down move = below - value; } else { // won't be able to move unless we can grab another variable double randomNumber = randomNumberGenerator_.randomDouble(); // which way? if (randomNumber < 0.5) move = below - value; else move = 1.0 - (value - below); } newValue += move; newSolution[iColumn] = newValue; newSolutionValue += move * cost; int j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += move * element[j]; } } } double penalty = 0.0; const char * integerType = model_->integerType(); // see if feasible - just using singletons for (i = 0; i < numberRows; i++) { double value = rowActivity[i]; double thisInfeasibility = 0.0; if (value < rowLower[i] - primalTolerance) thisInfeasibility = value - rowLower[i]; else if (value > rowUpper[i] + primalTolerance) thisInfeasibility = value - rowUpper[i]; if (thisInfeasibility) { // See if there are any slacks I can use to fix up // maybe put in coding for multiple slacks? double bestCost = 1.0e50; int k; int iBest = -1; double addCost = 0.0; double newValue = 0.0; double changeRowActivity = 0.0; double absInfeasibility = fabs(thisInfeasibility); for (k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) { int iColumn = column[k]; // See if all elements help if (columnLength[iColumn] == 1) { double currentValue = newSolution[iColumn]; double elementValue = elementByRow[k]; double lowerValue = lower[iColumn]; double upperValue = upper[iColumn]; double gap = rowUpper[i] - rowLower[i]; double absElement = fabs(elementValue); if (thisInfeasibility*elementValue > 0.0) { // we want to reduce if ((currentValue - lowerValue)*absElement >= absInfeasibility) { // possible - check if integer double distance = absInfeasibility / absElement; double thisCost = -direction * objective[iColumn] * distance; if (integerType[iColumn]) { distance = ceil(distance - primalTolerance); if (currentValue - distance >= lowerValue - primalTolerance) { if (absInfeasibility - distance*absElement < -gap - primalTolerance) thisCost = 1.0e100; // no good else thisCost = -direction * objective[iColumn] * distance; } else { thisCost = 1.0e100; // no good } } if (thisCost < bestCost) { bestCost = thisCost; iBest = iColumn; addCost = thisCost; newValue = currentValue - distance; changeRowActivity = -distance * elementValue; } } } else { // we want to increase if ((upperValue - currentValue)*absElement >= absInfeasibility) { // possible - check if integer double distance = absInfeasibility / absElement; double thisCost = direction * objective[iColumn] * distance; if (integerType[iColumn]) { distance = ceil(distance - 1.0e-7); assert (currentValue - distance <= upperValue + primalTolerance); if (absInfeasibility - distance*absElement < -gap - primalTolerance) thisCost = 1.0e100; // no good else thisCost = direction * objective[iColumn] * distance; } if (thisCost < bestCost) { bestCost = thisCost; iBest = iColumn; addCost = thisCost; newValue = currentValue + distance; changeRowActivity = distance * elementValue; } } } } } if (iBest >= 0) { /*printf("Infeasibility of %g on row %d cost %g\n", thisInfeasibility,i,addCost);*/ newSolution[iBest] = newValue; thisInfeasibility = 0.0; newSolutionValue += addCost; rowActivity[i] += changeRowActivity; } penalty += fabs(thisInfeasibility); } } if (penalty) { // see if feasible using any // first continuous double penaltyChange = 0.0; int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (integerType[iColumn]) continue; double currentValue = newSolution[iColumn]; double lowerValue = lower[iColumn]; double upperValue = upper[iColumn]; int j; int anyBadDown = 0; int anyBadUp = 0; double upImprovement = 0.0; double downImprovement = 0.0; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (rowUpper[iRow] > rowLower[iRow]) { double value = element[j]; if (rowActivity[iRow] > rowUpper[iRow] + primalTolerance) { // infeasible above downImprovement += value; upImprovement -= value; if (value > 0.0) anyBadUp++; else anyBadDown++; } else if (rowActivity[iRow] > rowUpper[iRow] - primalTolerance) { // feasible at ub if (value > 0.0) { upImprovement -= value; anyBadUp++; } else { downImprovement += value; anyBadDown++; } } else if (rowActivity[iRow] > rowLower[iRow] + primalTolerance) { // feasible in interior } else if (rowActivity[iRow] > rowLower[iRow] - primalTolerance) { // feasible at lb if (value < 0.0) { upImprovement += value; anyBadUp++; } else { downImprovement -= value; anyBadDown++; } } else { // infeasible below downImprovement -= value; upImprovement += value; if (value < 0.0) anyBadUp++; else anyBadDown++; } } else { // equality row double value = element[j]; if (rowActivity[iRow] > rowUpper[iRow] + primalTolerance) { // infeasible above downImprovement += value; upImprovement -= value; if (value > 0.0) anyBadUp++; else anyBadDown++; } else if (rowActivity[iRow] < rowLower[iRow] - primalTolerance) { // infeasible below downImprovement -= value; upImprovement += value; if (value < 0.0) anyBadUp++; else anyBadDown++; } else { // feasible - no good anyBadUp = -1; anyBadDown = -1; break; } } } // could change tests for anyBad if (anyBadUp) upImprovement = 0.0; if (anyBadDown) downImprovement = 0.0; double way = 0.0; double improvement = 0.0; if (downImprovement > 0.0 && currentValue > lowerValue) { way = -1.0; improvement = downImprovement; } else if (upImprovement > 0.0 && currentValue < upperValue) { way = 1.0; improvement = upImprovement; } if (way) { // can improve double distance; if (way > 0.0) distance = upperValue - currentValue; else distance = currentValue - lowerValue; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j] * way; if (rowActivity[iRow] > rowUpper[iRow] + primalTolerance) { // infeasible above assert (value < 0.0); double gap = rowActivity[iRow] - rowUpper[iRow]; if (gap + value*distance < 0.0) distance = -gap / value; } else if (rowActivity[iRow] < rowLower[iRow] - primalTolerance) { // infeasible below assert (value > 0.0); double gap = rowActivity[iRow] - rowLower[iRow]; if (gap + value*distance > 0.0) distance = -gap / value; } else { // feasible if (value > 0) { double gap = rowActivity[iRow] - rowUpper[iRow]; if (gap + value*distance > 0.0) distance = -gap / value; } else { double gap = rowActivity[iRow] - rowLower[iRow]; if (gap + value*distance < 0.0) distance = -gap / value; } } } //move penaltyChange += improvement * distance; distance *= way; newSolution[iColumn] += distance; newSolutionValue += direction * objective[iColumn] * distance; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j]; rowActivity[iRow] += distance * value; } } } // and now all if improving double lastChange = penaltyChange ? 1.0 : 0.0; while (lastChange > 1.0e-2) { lastChange = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { bool isInteger = (integerType[iColumn] != 0); double currentValue = newSolution[iColumn]; double lowerValue = lower[iColumn]; double upperValue = upper[iColumn]; int j; int anyBadDown = 0; int anyBadUp = 0; double upImprovement = 0.0; double downImprovement = 0.0; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j]; if (isInteger) { if (value > 0.0) { if (rowActivity[iRow] + value > rowUpper[iRow] + primalTolerance) anyBadUp++; if (rowActivity[iRow] - value < rowLower[iRow] - primalTolerance) anyBadDown++; } else { if (rowActivity[iRow] - value > rowUpper[iRow] + primalTolerance) anyBadDown++; if (rowActivity[iRow] + value < rowLower[iRow] - primalTolerance) anyBadUp++; } } if (rowUpper[iRow] > rowLower[iRow]) { if (rowActivity[iRow] > rowUpper[iRow] + primalTolerance) { // infeasible above downImprovement += value; upImprovement -= value; if (value > 0.0) anyBadUp++; else anyBadDown++; } else if (rowActivity[iRow] > rowUpper[iRow] - primalTolerance) { // feasible at ub if (value > 0.0) { upImprovement -= value; anyBadUp++; } else { downImprovement += value; anyBadDown++; } } else if (rowActivity[iRow] > rowLower[iRow] + primalTolerance) { // feasible in interior } else if (rowActivity[iRow] > rowLower[iRow] - primalTolerance) { // feasible at lb if (value < 0.0) { upImprovement += value; anyBadUp++; } else { downImprovement -= value; anyBadDown++; } } else { // infeasible below downImprovement -= value; upImprovement += value; if (value < 0.0) anyBadUp++; else anyBadDown++; } } else { // equality row if (rowActivity[iRow] > rowUpper[iRow] + primalTolerance) { // infeasible above downImprovement += value; upImprovement -= value; if (value > 0.0) anyBadUp++; else anyBadDown++; } else if (rowActivity[iRow] < rowLower[iRow] - primalTolerance) { // infeasible below downImprovement -= value; upImprovement += value; if (value < 0.0) anyBadUp++; else anyBadDown++; } else { // feasible - no good anyBadUp = -1; anyBadDown = -1; break; } } } // could change tests for anyBad if (anyBadUp) upImprovement = 0.0; if (anyBadDown) downImprovement = 0.0; double way = 0.0; double improvement = 0.0; if (downImprovement > 0.0 && currentValue > lowerValue) { way = -1.0; improvement = downImprovement; } else if (upImprovement > 0.0 && currentValue < upperValue) { way = 1.0; improvement = upImprovement; } if (way) { // can improve double distance = COIN_DBL_MAX; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j] * way; if (rowActivity[iRow] > rowUpper[iRow] + primalTolerance) { // infeasible above assert (value < 0.0); double gap = rowActivity[iRow] - rowUpper[iRow]; if (gap + value*distance < 0.0) { // If integer then has to move by 1 if (!isInteger) distance = -gap / value; else distance = CoinMax(-gap / value, 1.0); } } else if (rowActivity[iRow] < rowLower[iRow] - primalTolerance) { // infeasible below assert (value > 0.0); double gap = rowActivity[iRow] - rowLower[iRow]; if (gap + value*distance > 0.0) { // If integer then has to move by 1 if (!isInteger) distance = -gap / value; else distance = CoinMax(-gap / value, 1.0); } } else { // feasible if (value > 0) { double gap = rowActivity[iRow] - rowUpper[iRow]; if (gap + value*distance > 0.0) distance = -gap / value; } else { double gap = rowActivity[iRow] - rowLower[iRow]; if (gap + value*distance < 0.0) distance = -gap / value; } } } if (isInteger) distance = floor(distance + 1.05e-8); if (!distance) { // should never happen //printf("zero distance in CbcRounding - debug\n"); } //move lastChange += improvement * distance; distance *= way; newSolution[iColumn] += distance; newSolutionValue += direction * objective[iColumn] * distance; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j]; rowActivity[iRow] += distance * value; } } } penaltyChange += lastChange; } penalty -= penaltyChange; if (penalty < 1.0e-5*fabs(penaltyChange)) { // recompute penalty = 0.0; for (i = 0; i < numberRows; i++) { double value = rowActivity[i]; if (value < rowLower[i] - primalTolerance) penalty += rowLower[i] - value; else if (value > rowUpper[i] + primalTolerance) penalty += value - rowUpper[i]; } } } // Could also set SOS (using random) and repeat if (!penalty) { // See if we can do better //seed_++; //CoinSeedRandom(seed_); // Random number between 0 and 1. double randomNumber = randomNumberGenerator_.randomDouble(); int iPass; int start[2]; int end[2]; int iRandom = static_cast (randomNumber * (static_cast (numberIntegers))); start[0] = iRandom; end[0] = numberIntegers; start[1] = 0; end[1] = iRandom; for (iPass = 0; iPass < 2; iPass++) { int i; for (i = start[iPass]; i < end[iPass]; i++) { int iColumn = integerVariable[i]; #ifndef NDEBUG double value = newSolution[iColumn]; assert (fabs(floor(value + 0.5) - value) < integerTolerance); #endif double cost = direction * objective[iColumn]; double move = 0.0; if (cost > 0.0) move = -1.0; else if (cost < 0.0) move = 1.0; while (move) { bool good = true; double newValue = newSolution[iColumn] + move; if (newValue < lower[iColumn] - primalTolerance || newValue > upper[iColumn] + primalTolerance) { move = 0.0; } else { // see if we can move int j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double newActivity = rowActivity[iRow] + move * element[j]; if (newActivity < rowLower[iRow] - primalTolerance || newActivity > rowUpper[iRow] + primalTolerance) { good = false; break; } } if (good) { newSolution[iColumn] = newValue; newSolutionValue += move * cost; int j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += move * element[j]; } } else { move = 0.0; } } } } } // Just in case of some stupidity double objOffset = 0.0; solver->getDblParam(OsiObjOffset, objOffset); newSolutionValue = -objOffset; for ( i = 0 ; i < numberColumns ; i++ ) newSolutionValue += objective[i] * newSolution[i]; newSolutionValue *= direction; //printf("new solution value %g %g\n",newSolutionValue,solutionValue); if (newSolutionValue < solutionValue) { // paranoid check memset(rowActivity, 0, numberRows*sizeof(double)); for (i = 0; i < numberColumns; i++) { int j; double value = newSolution[i]; if (value) { for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } // check was approximately feasible bool feasible = true; for (i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i]) { if (rowActivity[i] < rowLower[i] - 1000.0*primalTolerance) feasible = false; } else if (rowActivity[i] > rowUpper[i]) { if (rowActivity[i] > rowUpper[i] + 1000.0*primalTolerance) feasible = false; } } if (feasible) { // new solution memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); solutionValue = newSolutionValue; //printf("** Solution of %g found by rounding\n",newSolutionValue); returnCode = 1; } else { // Can easily happen //printf("Debug CbcRounding giving bad solution\n"); } } } #ifdef NEW_ROUNDING if (!returnCode) { #ifdef JJF_ZERO // back to starting point memcpy(newSolution, solution, numberColumns*sizeof(double)); memset(rowActivity, 0, numberRows*sizeof(double)); for (i = 0; i < numberColumns; i++) { int j; double value = newSolution[i]; if (value < lower[i]) { value = lower[i]; newSolution[i] = value; } else if (value > upper[i]) { value = upper[i]; newSolution[i] = value; } if (value) { for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } // check was feasible - if not adjust (cleaning may move) for (i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i]) { //assert (rowActivity[i]>rowLower[i]-1000.0*primalTolerance); rowActivity[i] = rowLower[i]; } else if (rowActivity[i] > rowUpper[i]) { //assert (rowActivity[i] 1.0e-8) candidate[nCandidate++] = iColumn; } } if (true) { // Rounding as in Berthold while (nCandidate) { double infeasibility = 1.0e-7; int iRow = -1; for (i = 0; i < numberRows; i++) { double value = 0.0; if (rowActivity[i] < rowLower[i]) { value = rowLower[i] - rowActivity[i]; } else if (rowActivity[i] > rowUpper[i]) { value = rowActivity[i] - rowUpper[i]; } if (value > infeasibility) { infeasibility = value; iRow = i; } } if (iRow >= 0) { // infeasible } else { // feasible } } } else { // Shifting as in Berthold } delete [] candidate; } #endif delete [] newSolution; delete [] rowActivity; return returnCode; } // update model void CbcRounding::setModel(CbcModel * model) { model_ = model; // Get a copy of original matrix (and by row for rounding); assert(model_->solver()); if (model_->solver()->getNumRows()) { matrix_ = *model_->solver()->getMatrixByCol(); matrixByRow_ = *model_->solver()->getMatrixByRow(); // make sure model okay for heuristic validate(); } } // Validate model i.e. sets when_ to 0 if necessary (may be NULL) void CbcRounding::validate() { if (model_ && (when() % 100) < 10) { if (model_->numberIntegers() != model_->numberObjects() && (model_->numberObjects() || (model_->specialOptions()&1024) == 0)) { int numberOdd = 0; for (int i = 0; i < model_->numberObjects(); i++) { if (!model_->object(i)->canDoHeuristics()) numberOdd++; } if (numberOdd) setWhen(0); } } #ifdef NEW_ROUNDING int numberColumns = matrix_.getNumCols(); down_ = new unsigned short [numberColumns]; up_ = new unsigned short [numberColumns]; equal_ = new unsigned short [numberColumns]; // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); const double * rowLower = model.solver()->getRowLower(); const double * rowUpper = model.solver()->getRowUpper(); for (int i = 0; i < numberColumns; i++) { int down = 0; int up = 0; int equal = 0; if (columnLength[i] > 65535) { equal[0] = 65535; break; // unlikely to work } for (CoinBigIndex j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; if (rowLower[iRow] > -1.0e20 && rowUpper[iRow] < 1.0e20) { equal++; } else if (element[j] > 0.0) { if (rowUpper[iRow] < 1.0e20) up++; else down--; } else { if (rowLower[iRow] > -1.0e20) up++; else down--; } } down_[i] = (unsigned short) down; up_[i] = (unsigned short) up; equal_[i] = (unsigned short) equal; } #else down_ = NULL; up_ = NULL; equal_ = NULL; #endif } // Default Constructor CbcHeuristicPartial::CbcHeuristicPartial() : CbcHeuristic() { fixPriority_ = 10000; } // Constructor from model CbcHeuristicPartial::CbcHeuristicPartial(CbcModel & model, int fixPriority, int numberNodes) : CbcHeuristic(model) { fixPriority_ = fixPriority; setNumberNodes(numberNodes); validate(); } // Destructor CbcHeuristicPartial::~CbcHeuristicPartial () { } // Clone CbcHeuristic * CbcHeuristicPartial::clone() const { return new CbcHeuristicPartial(*this); } // Create C++ lines to get to current state void CbcHeuristicPartial::generateCpp( FILE * fp) { CbcHeuristicPartial other; fprintf(fp, "0#include \"CbcHeuristic.hpp\"\n"); fprintf(fp, "3 CbcHeuristicPartial partial(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "partial"); if (fixPriority_ != other.fixPriority_) fprintf(fp, "3 partial.setFixPriority(%d);\n", fixPriority_); else fprintf(fp, "4 partial.setFixPriority(%d);\n", fixPriority_); fprintf(fp, "3 cbcModel->addHeuristic(&partial);\n"); } //#define NEW_PARTIAL // Copy constructor CbcHeuristicPartial::CbcHeuristicPartial(const CbcHeuristicPartial & rhs) : CbcHeuristic(rhs), fixPriority_(rhs.fixPriority_) { } // Assignment operator CbcHeuristicPartial & CbcHeuristicPartial::operator=( const CbcHeuristicPartial & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); fixPriority_ = rhs.fixPriority_; } return *this; } // Resets stuff if model changes void CbcHeuristicPartial::resetModel(CbcModel * model) { model_ = model; // Get a copy of original matrix (and by row for partial); assert(model_->solver()); validate(); } // See if partial will give solution // Sets value of solution // Assumes rhs for original matrix still okay // At present only works with integers // Fix values if asked for // Returns 1 if solution, 0 if not int CbcHeuristicPartial::solution(double & solutionValue, double * betterSolution) { // Return if already done if (fixPriority_ < 0) return 0; // switched off const double * hotstartSolution = model_->hotstartSolution(); const int * hotstartPriorities = model_->hotstartPriorities(); if (!hotstartSolution) return 0; OsiSolverInterface * solver = model_->solver(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); OsiSolverInterface * newSolver = model_->continuousSolver()->clone(); const double * colLower = newSolver->getColLower(); const double * colUpper = newSolver->getColUpper(); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); int i; int numberFixed = 0; int returnCode = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (abs(hotstartPriorities[iColumn]) <= fixPriority_) { double value = hotstartSolution[iColumn]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; value = CoinMax(value, lower); value = CoinMin(value, upper); if (fabs(value - floor(value + 0.5)) < 1.0e-8) { value = floor(value + 0.5); newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); numberFixed++; } } } if (numberFixed > numberIntegers / 5 - 100000000) { #ifdef COIN_DEVELOP printf("%d integers fixed\n", numberFixed); #endif returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicPartial"); if (returnCode < 0) returnCode = 0; // returned on size //printf("return code %d",returnCode); if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; //printf("could add cut with %d elements (if all 0-1)\n",nFix); } else { //printf("\n"); } } fixPriority_ = -1; // switch off delete newSolver; return returnCode; } // update model void CbcHeuristicPartial::setModel(CbcModel * model) { model_ = model; assert(model_->solver()); // make sure model okay for heuristic validate(); } // Validate model i.e. sets when_ to 0 if necessary (may be NULL) void CbcHeuristicPartial::validate() { if (model_ && (when() % 100) < 10) { if (model_->numberIntegers() != model_->numberObjects()) setWhen(0); } } bool CbcHeuristicPartial::shouldHeurRun(int /*whereFrom*/) { return true; } // Default Constructor CbcSerendipity::CbcSerendipity() : CbcHeuristic() { } // Constructor from model CbcSerendipity::CbcSerendipity(CbcModel & model) : CbcHeuristic(model) { } // Destructor CbcSerendipity::~CbcSerendipity () { } // Clone CbcHeuristic * CbcSerendipity::clone() const { return new CbcSerendipity(*this); } // Create C++ lines to get to current state void CbcSerendipity::generateCpp( FILE * fp) { fprintf(fp, "0#include \"CbcHeuristic.hpp\"\n"); fprintf(fp, "3 CbcSerendipity serendipity(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "serendipity"); fprintf(fp, "3 cbcModel->addHeuristic(&serendipity);\n"); } // Copy constructor CbcSerendipity::CbcSerendipity(const CbcSerendipity & rhs) : CbcHeuristic(rhs) { } // Assignment operator CbcSerendipity & CbcSerendipity::operator=( const CbcSerendipity & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); } return *this; } // Returns 1 if solution, 0 if not int CbcSerendipity::solution(double & solutionValue, double * betterSolution) { if (!model_) return 0; if (!inputSolution_) { // get information on solver type OsiAuxInfo * auxInfo = model_->solver()->getAuxiliaryInfo(); OsiBabSolver * auxiliaryInfo = dynamic_cast< OsiBabSolver *> (auxInfo); if (auxiliaryInfo) { return auxiliaryInfo->solution(solutionValue, betterSolution, model_->solver()->getNumCols()); } else { return 0; } } else { int numberColumns = model_->getNumCols(); double value = inputSolution_[numberColumns]; int returnCode = 0; if (value < solutionValue) { solutionValue = value; memcpy(betterSolution, inputSolution_, numberColumns*sizeof(double)); returnCode = 1; } delete [] inputSolution_; inputSolution_ = NULL; model_ = NULL; // switch off return returnCode; } } // update model void CbcSerendipity::setModel(CbcModel * model) { model_ = model; } // Resets stuff if model changes void CbcSerendipity::resetModel(CbcModel * model) { model_ = model; } // Default Constructor CbcHeuristicJustOne::CbcHeuristicJustOne() : CbcHeuristic(), probabilities_(NULL), heuristic_(NULL), numberHeuristics_(0) { } // Constructor from model CbcHeuristicJustOne::CbcHeuristicJustOne(CbcModel & model) : CbcHeuristic(model), probabilities_(NULL), heuristic_(NULL), numberHeuristics_(0) { } // Destructor CbcHeuristicJustOne::~CbcHeuristicJustOne () { for (int i = 0; i < numberHeuristics_; i++) delete heuristic_[i]; delete [] heuristic_; delete [] probabilities_; } // Clone CbcHeuristicJustOne * CbcHeuristicJustOne::clone() const { return new CbcHeuristicJustOne(*this); } // Create C++ lines to get to current state void CbcHeuristicJustOne::generateCpp( FILE * fp) { CbcHeuristicJustOne other; fprintf(fp, "0#include \"CbcHeuristicJustOne.hpp\"\n"); fprintf(fp, "3 CbcHeuristicJustOne heuristicJustOne(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicJustOne"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicJustOne);\n"); } // Copy constructor CbcHeuristicJustOne::CbcHeuristicJustOne(const CbcHeuristicJustOne & rhs) : CbcHeuristic(rhs), probabilities_(NULL), heuristic_(NULL), numberHeuristics_(rhs.numberHeuristics_) { if (numberHeuristics_) { probabilities_ = CoinCopyOfArray(rhs.probabilities_, numberHeuristics_); heuristic_ = new CbcHeuristic * [numberHeuristics_]; for (int i = 0; i < numberHeuristics_; i++) heuristic_[i] = rhs.heuristic_[i]->clone(); } } // Assignment operator CbcHeuristicJustOne & CbcHeuristicJustOne::operator=( const CbcHeuristicJustOne & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); for (int i = 0; i < numberHeuristics_; i++) delete heuristic_[i]; delete [] heuristic_; delete [] probabilities_; probabilities_ = NULL; heuristic_ = NULL; numberHeuristics_ = rhs.numberHeuristics_; if (numberHeuristics_) { probabilities_ = CoinCopyOfArray(rhs.probabilities_, numberHeuristics_); heuristic_ = new CbcHeuristic * [numberHeuristics_]; for (int i = 0; i < numberHeuristics_; i++) heuristic_[i] = rhs.heuristic_[i]->clone(); } } return *this; } // Sets value of solution // Returns 1 if solution, 0 if not int CbcHeuristicJustOne::solution(double & solutionValue, double * betterSolution) { #ifdef DIVE_DEBUG std::cout << "solutionValue = " << solutionValue << std::endl; #endif ++numCouldRun_; // test if the heuristic can run if (!shouldHeurRun_randomChoice() || !numberHeuristics_) return 0; double randomNumber = randomNumberGenerator_.randomDouble(); int i; for (i = 0; i < numberHeuristics_; i++) { if (randomNumber < probabilities_[i]) break; } assert (i < numberHeuristics_); int returnCode; //model_->unsetDivingHasRun(); #ifdef COIN_DEVELOP printf("JustOne running %s\n", heuristic_[i]->heuristicName()); #endif returnCode = heuristic_[i]->solution(solutionValue, betterSolution); #ifdef COIN_DEVELOP if (returnCode) printf("JustOne running %s found solution\n", heuristic_[i]->heuristicName()); #endif return returnCode; } // Resets stuff if model changes void CbcHeuristicJustOne::resetModel(CbcModel * model) { CbcHeuristic::resetModel(model); for (int i = 0; i < numberHeuristics_; i++) heuristic_[i]->resetModel(model); } // update model (This is needed if cliques update matrix etc) void CbcHeuristicJustOne::setModel(CbcModel * model) { CbcHeuristic::setModel(model); for (int i = 0; i < numberHeuristics_; i++) heuristic_[i]->setModel(model); } // Validate model i.e. sets when_ to 0 if necessary (may be NULL) void CbcHeuristicJustOne::validate() { CbcHeuristic::validate(); for (int i = 0; i < numberHeuristics_; i++) heuristic_[i]->validate(); } // Adds an heuristic with probability void CbcHeuristicJustOne::addHeuristic(const CbcHeuristic * heuristic, double probability) { CbcHeuristic * thisOne = heuristic->clone(); thisOne->setWhen(-999); CbcHeuristic ** tempH = CoinCopyOfArrayPartial(heuristic_, numberHeuristics_ + 1, numberHeuristics_); delete [] heuristic_; heuristic_ = tempH; heuristic_[numberHeuristics_] = thisOne; double * tempP = CoinCopyOfArrayPartial(probabilities_, numberHeuristics_ + 1, numberHeuristics_); delete [] probabilities_; probabilities_ = tempP; probabilities_[numberHeuristics_] = probability; numberHeuristics_++; } // Normalize probabilities void CbcHeuristicJustOne::normalizeProbabilities() { double sum = 0.0; for (int i = 0; i < numberHeuristics_; i++) sum += probabilities_[i]; double multiplier = 1.0 / sum; sum = 0.0; for (int i = 0; i < numberHeuristics_; i++) { sum += probabilities_[i]; probabilities_[i] = sum * multiplier; } assert (fabs(probabilities_[numberHeuristics_-1] - 1.0) < 1.0e-5); probabilities_[numberHeuristics_-1] = 1.000001; } Cbc-2.8.12/src/CbcGeneralDepth.hpp0000644000076600007660000002077312131315050015223 0ustar coincoin// $Id: CbcGeneralDepth.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #ifndef CbcGeneralDepth_H #define CbcGeneralDepth_H #include "CbcGeneral.hpp" #include "CbcBranchBase.hpp" #include "CbcSubProblem.hpp" #ifdef COIN_HAS_CLP /** Define a catch all class. This will create a list of subproblems using partial evaluation */ #include "ClpSimplex.hpp" #include "ClpNode.hpp" class CbcGeneralDepth : public CbcGeneral { public: // Default Constructor CbcGeneralDepth (); /** Useful constructor Just needs to point to model. Initial version does evaluation to depth N This is stored in CbcModel but may be better here */ CbcGeneralDepth (CbcModel * model, int maximumDepth); // Copy constructor CbcGeneralDepth ( const CbcGeneralDepth &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcGeneralDepth & operator=( const CbcGeneralDepth& rhs); // Destructor ~CbcGeneralDepth (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /// This looks at solution and sets bounds to contain solution virtual void feasibleRegion(); /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Return maximum number of nodes inline int maximumNodes() const { return maximumNodes_; } /// Get maximum depth inline int maximumDepth() const { return maximumDepth_; } /// Set maximum depth inline void setMaximumDepth(int value) { maximumDepth_ = value; } /// Return number of nodes inline int numberNodes() const { return numberNodes_; } /// Get which solution inline int whichSolution() const { return whichSolution_; } /// Get ClpNode info inline ClpNode * nodeInfo(int which) { return nodeInfo_->nodeInfo_[which]; } /// Redoes data when sequence numbers change virtual void redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns); protected: /// data /// Maximum depth int maximumDepth_; /// Maximum nodes int maximumNodes_; /// Which node has solution (or -1) mutable int whichSolution_; /// Number of valid nodes (including whichSolution_) mutable int numberNodes_; /// For solving nodes mutable ClpNodeStuff * nodeInfo_; }; /** Branching object for general objects */ class CbcNode; class CbcGeneralBranchingObject : public CbcBranchingObject { public: // Default Constructor CbcGeneralBranchingObject (); // Useful constructor CbcGeneralBranchingObject (CbcModel * model); // Copy constructor CbcGeneralBranchingObject ( const CbcGeneralBranchingObject &); // Assignment operator CbcGeneralBranchingObject & operator=( const CbcGeneralBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; // Destructor virtual ~CbcGeneralBranchingObject (); using CbcBranchingObject::branch ; /// Does next branch and updates state virtual double branch(); /** Double checks in case node can change its mind! Can change objective etc */ virtual void checkIsCutoff(double cutoff); using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /// Fill in current objective etc void state(double & objectiveValue, double & sumInfeasibilities, int & numberUnsatisfied, int which) const; /// Set CbcNode inline void setNode(CbcNode * node) { node_ = node; } /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return GeneralDepthBranchObj; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const; /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); /// Number of subproblems inline int numberSubProblems() const { return numberSubProblems_; } /// Decrement number left and return number inline int decrementNumberLeft() { numberSubLeft_--; return numberSubLeft_; } /// Which node we want to use inline int whichNode() const { return whichNode_; } /// Set which node we want to use inline void setWhichNode(int value) { whichNode_ = value; } // Sub problem const CbcSubProblem * subProblem(int which) const { return subProblems_ + which; } public: /// data // Sub problems CbcSubProblem * subProblems_; /// Node CbcNode * node_; /// Number of subproblems int numberSubProblems_; /// Number of subproblems left int numberSubLeft_; /// Which node we want to use (-1 for default) int whichNode_; /// Number of rows int numberRows_; }; /** Branching object for general objects - just one */ class CbcOneGeneralBranchingObject : public CbcBranchingObject { public: // Default Constructor CbcOneGeneralBranchingObject (); // Useful constructor CbcOneGeneralBranchingObject (CbcModel * model, CbcGeneralBranchingObject * object, int whichOne); // Copy constructor CbcOneGeneralBranchingObject ( const CbcOneGeneralBranchingObject &); // Assignment operator CbcOneGeneralBranchingObject & operator=( const CbcOneGeneralBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; // Destructor virtual ~CbcOneGeneralBranchingObject (); using CbcBranchingObject::branch ; /// Does next branch and updates state virtual double branch(); /** Double checks in case node can change its mind! Can change objective etc */ virtual void checkIsCutoff(double cutoff); using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return OneGeneralBranchingObj; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const; /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); public: /// data /// Object CbcGeneralBranchingObject * object_; /// Which one int whichOne_; }; #endif //COIN_HAS_CLP #endif Cbc-2.8.12/src/CbcCompareEstimate.cpp0000644000076600007660000000354012131315050015727 0ustar coincoin// $Id: CbcCompareEstimate.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCompareActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CbcMessage.hpp" #include "CbcModel.hpp" #include "CbcTree.hpp" #include "CbcCompareActual.hpp" #include "CoinError.hpp" #include "CbcCompareEstimate.hpp" /** Default Constructor */ CbcCompareEstimate::CbcCompareEstimate () : CbcCompareBase() { test_ = this; } // Copy constructor CbcCompareEstimate::CbcCompareEstimate ( const CbcCompareEstimate & rhs) : CbcCompareBase(rhs) { } // Clone CbcCompareBase * CbcCompareEstimate::clone() const { return new CbcCompareEstimate(*this); } // Assignment operator CbcCompareEstimate & CbcCompareEstimate::operator=( const CbcCompareEstimate & rhs) { if (this != &rhs) { CbcCompareBase::operator=(rhs); } return *this; } // Destructor CbcCompareEstimate::~CbcCompareEstimate () { } // Returns true if y better than x bool CbcCompareEstimate::test (CbcNode * x, CbcNode * y) { double testX = x->guessedObjectiveValue(); double testY = y->guessedObjectiveValue(); if (testX != testY) return testX > testY; else return equalityTest(x, y); // so ties will be broken in consistent manner } // Create C++ lines to get to current state void CbcCompareEstimate::generateCpp( FILE * fp) { fprintf(fp, "0#include \"CbcCompareActual.hpp\"\n"); fprintf(fp, "3 CbcCompareEstimate compare;\n"); fprintf(fp, "3 cbcModel->setNodeComparison(compare);\n"); } Cbc-2.8.12/src/CbcCompareBase.hpp0000644000076600007660000001013011510742604015035 0ustar coincoin/* $Id: CbcCompareBase.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcCompareBase_H #define CbcCompareBase_H //############################################################################# /* These are alternative strategies for node traversal. They can take data etc for fine tuning At present the node list is stored as a heap and the "test" comparison function returns true if node y is better than node x. This is rather inflexible so if the comparison functions wants it can signal to use alternative criterion on a complete pass throgh tree. */ #include "CbcNode.hpp" #include "CbcConfig.h" class CbcModel; class CbcTree; class CbcCompareBase { public: // Default Constructor CbcCompareBase () { test_ = NULL; threaded_ = false; } /*! \brief Reconsider behaviour after discovering a new solution. This allows any method to change its behaviour. It is called after each solution. The method should return true if changes are made which will alter the evaluation criteria applied to a node. (So that in cases where the search tree is sorted, it can be properly rebuilt.) */ virtual bool newSolution(CbcModel * ) { return (false) ; } /*! \brief Reconsider behaviour after discovering a new solution. This allows any method to change its behaviour. It is called after each solution. The method should return true if changes are made which will alter the evaluation criteria applied to a node. (So that in cases where the search tree is sorted, it can be properly rebuilt.) */ virtual bool newSolution(CbcModel * , double , int ) { return (false) ; } // This allows any method to change behavior as it is called // after every 1000 nodes. // Return true if want tree re-sorted virtual bool every1000Nodes(CbcModel * , int ) { return false; } /** Returns true if wants code to do scan with alternate criterion NOTE - this is temporarily disabled */ virtual bool fullScan() const { return false; } virtual ~CbcCompareBase() {} /// Create C++ lines to get to current state virtual void generateCpp( FILE * ) {} // Copy constructor CbcCompareBase ( const CbcCompareBase & rhs) { test_ = rhs.test_; threaded_ = rhs.threaded_; } // Assignment operator CbcCompareBase & operator=( const CbcCompareBase& rhs) { if (this != &rhs) { test_ = rhs.test_; threaded_ = rhs.threaded_; } return *this; } /// Clone virtual CbcCompareBase * clone() const { abort(); return NULL; } /// This is test function virtual bool test (CbcNode * , CbcNode * ) { return true; } /// This is alternate test function virtual bool alternateTest (CbcNode * x, CbcNode * y) { return test(x, y); } bool operator() (CbcNode * x, CbcNode * y) { return test(x, y); } /// Further test if everything else equal inline bool equalityTest (CbcNode * x, CbcNode * y) const { assert (x); assert (y); if (!threaded_) { CbcNodeInfo * infoX = x->nodeInfo(); assert (infoX); int nodeNumberX = infoX->nodeNumber(); CbcNodeInfo * infoY = y->nodeInfo(); assert (infoY); int nodeNumberY = infoY->nodeNumber(); assert (nodeNumberX != nodeNumberY); return (nodeNumberX > nodeNumberY); } else { assert (x->nodeNumber() != y->nodeNumber()); return (x->nodeNumber() > y->nodeNumber()); } } /// Say threaded inline void sayThreaded() { threaded_ = true; } protected: CbcCompareBase * test_; // If not threaded we can use better way to break ties bool threaded_; }; #endif Cbc-2.8.12/src/CbcCompare.hpp0000644000076600007660000000164012131315050014237 0ustar coincoin/* $Id: CbcCompare.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcCompare_H #define CbcCompare_H class CbcCompareBase; class CbcCompare { public: CbcCompareBase * test_; // Default Constructor CbcCompare () { test_ = NULL; } virtual ~CbcCompare() {} bool operator() (CbcNode * x, CbcNode * y) { return test_->test(x, y); } bool compareNodes (CbcNode * x, CbcNode * y) { return test_->test(x, y); } /// This is alternate test function inline bool alternateTest (CbcNode * x, CbcNode * y) { return test_->alternateTest(x, y); } /// return comparison object inline CbcCompareBase * comparisonObject() const { return test_; } }; #endif Cbc-2.8.12/src/CbcHeuristicDiveLineSearch.hpp0000644000076600007660000000315412131315050017360 0ustar coincoin/* $Id: CbcHeuristicDiveLineSearch.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicDiveLineSearch_H #define CbcHeuristicDiveLineSearch_H #include "CbcHeuristicDive.hpp" /** DiveLineSearch class */ class CbcHeuristicDiveLineSearch : public CbcHeuristicDive { public: // Default Constructor CbcHeuristicDiveLineSearch (); // Constructor with model - assumed before cuts CbcHeuristicDiveLineSearch (CbcModel & model); // Copy constructor CbcHeuristicDiveLineSearch ( const CbcHeuristicDiveLineSearch &); // Destructor ~CbcHeuristicDiveLineSearch (); /// Clone virtual CbcHeuristicDiveLineSearch * clone() const; /// Assignment operator CbcHeuristicDiveLineSearch & operator=(const CbcHeuristicDiveLineSearch& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Selects the next variable to branch on /** Returns true if all the fractional variables can be trivially rounded. Returns false, if there is at least one fractional variable that is not trivially roundable. In this case, the bestColumn returned will not be trivially roundable. */ virtual bool selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound); }; #endif Cbc-2.8.12/src/CbcParam.hpp0000644000076600007660000002304011510742604013720 0ustar coincoin/* $Id: CbcParam.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcParam_H #define CbcParam_H #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" class ClpSimplex; /*! \brief Parameter codes Parameter type ranges are allocated as follows
  • 1 -- 100 double parameters
  • 101 -- 200 integer parameters
  • 201 -- 250 string parameters
  • 251 -- 300 cuts etc(string but broken out for clarity)
  • 301 -- 400 `actions'
`Actions' do not necessarily invoke an immediate action; it's just that they don't fit neatly into the parameters array. This coding scheme is in flux. CBC_PARAM_STR_NODESTRATEGY, CBC_PARAM_STR_BRANCHSTRATEGY, CBC_PARAM_NOTUSED_ADDCUTSSTRATEGY, CLP_PARAM_ACTION_CLEARCUTS, CBC_PARAM_NOTUSED_OSLSTUFF, CBC_PARAM_NOTUSED_CBCSTUFF are not used at present (03.10.24). */ enum CbcParameterType { CBC_PARAM_GENERALQUERY = -100, CBC_PARAM_FULLGENERALQUERY, CLP_PARAM_DBL_PRIMALTOLERANCE = 1, CLP_PARAM_DBL_DUALTOLERANCE, CBC_PARAM_DBL_CUTOFF, CLP_PARAM_DBL_TIMELIMIT, CLP_PARAM_DBL_DUALBOUND, CLP_PARAM_DBL_PRIMALWEIGHT, CLP_PARAM_DBL_OBJSCALE, CLP_PARAM_DBL_RHSSCALE, CBC_PARAM_DBL_INFEASIBILITYWEIGHT = 51, CBC_PARAM_DBL_INTEGERTOLERANCE, CBC_PARAM_DBL_INCREMENT, CBC_PARAM_DBL_ALLOWABLEGAP, CBC_PARAM_DBL_DJFIX = 81, CBC_PARAM_DBL_GAPRATIO, CBC_PARAM_DBL_TIGHTENFACTOR, CLP_PARAM_INT_LOGLEVEL = 101, CLP_PARAM_INT_SOLVERLOGLEVEL, CBC_PARAM_INT_MAXNODES, CBC_PARAM_INT_STRONGBRANCHING, CLP_PARAM_INT_MAXFACTOR, CLP_PARAM_INT_PERTVALUE, CLP_PARAM_INT_MAXITERATION, CLP_PARAM_INT_PRESOLVEPASS, CLP_PARAM_INT_IDIOT, CLP_PARAM_INT_SPRINT, CLP_PARAM_INT_OUTPUTFORMAT, CLP_PARAM_INT_SLPVALUE, CLP_PARAM_INT_PRESOLVEOPTIONS, CLP_PARAM_INT_PRINTOPTIONS, CLP_PARAM_INT_SPECIALOPTIONS, CLP_PARAM_STR_DIRECTION = 201, CLP_PARAM_STR_DUALPIVOT, CLP_PARAM_STR_SCALING, CLP_PARAM_STR_ERRORSALLOWED, CLP_PARAM_STR_KEEPNAMES, CLP_PARAM_STR_SPARSEFACTOR, CLP_PARAM_STR_PRIMALPIVOT, CLP_PARAM_STR_PRESOLVE, CLP_PARAM_STR_CRASH, CLP_PARAM_STR_BIASLU, CLP_PARAM_STR_PERTURBATION, CLP_PARAM_STR_MESSAGES, CLP_PARAM_STR_AUTOSCALE, CLP_PARAM_STR_CHOLESKY, CLP_PARAM_STR_KKT, CLP_PARAM_STR_BARRIERSCALE, CLP_PARAM_STR_GAMMA, CLP_PARAM_STR_CROSSOVER, CLP_PARAM_STR_PFI, CLP_PARAM_NOTUSED_ALGORITHM, CBC_PARAM_STR_NODESTRATEGY = 251, CBC_PARAM_STR_BRANCHSTRATEGY, CBC_PARAM_NOTUSED_ADDCUTSSTRATEGY, CBC_PARAM_STR_GOMORYCUTS, CBC_PARAM_STR_PROBINGCUTS, CBC_PARAM_STR_KNAPSACKCUTS, CBC_PARAM_NOTUSED_ODDHOLECUTS, CBC_PARAM_STR_ROUNDING, CBC_PARAM_STR_SOLVER, CBC_PARAM_STR_CLIQUECUTS, CBC_PARAM_STR_COSTSTRATEGY, CBC_PARAM_STR_FLOWCUTS, CBC_PARAM_STR_MIXEDCUTS, CBC_PARAM_STR_TWOMIRCUTS, CBC_PARAM_STR_PREPROCESS, CLP_PARAM_ACTION_DIRECTORY = 301, CLP_PARAM_ACTION_IMPORT, CLP_PARAM_ACTION_EXPORT, CLP_PARAM_ACTION_RESTORE, CLP_PARAM_ACTION_SAVE, CLP_PARAM_ACTION_DUALSIMPLEX, CLP_PARAM_ACTION_PRIMALSIMPLEX, CLP_PARAM_ACTION_MAXIMIZE, CLP_PARAM_ACTION_MINIMIZE, CLP_PARAM_ACTION_EXIT, CLP_PARAM_ACTION_STDIN, CLP_PARAM_ACTION_UNITTEST, CLP_PARAM_ACTION_NETLIB_DUAL, CLP_PARAM_ACTION_NETLIB_PRIMAL, CLP_PARAM_ACTION_SOLUTION, CLP_PARAM_ACTION_TIGHTEN, CLP_PARAM_ACTION_FAKEBOUND, CLP_PARAM_ACTION_HELP, CLP_PARAM_ACTION_PLUSMINUS, CLP_PARAM_ACTION_NETWORK, CLP_PARAM_ACTION_ALLSLACK, CLP_PARAM_ACTION_REVERSE, CLP_PARAM_ACTION_BARRIER, CLP_PARAM_ACTION_NETLIB_BARRIER, CLP_PARAM_ACTION_REALLY_SCALE, CLP_PARAM_ACTION_BASISIN, CLP_PARAM_ACTION_BASISOUT, CLP_PARAM_ACTION_SOLVECONTINUOUS, CBC_PARAM_ACTION_BAB, CBC_PARAM_ACTION_MIPLIB, CLP_PARAM_ACTION_CLEARCUTS, CLP_VERSION_NOTUSED_PRINTVERSION, CBC_PARAM_NOTUSED_OSLSTUFF = 401, CBC_PARAM_NOTUSED_CBCSTUFF, CBC_PARAM_NOTUSED_INVALID = 1000 }; /// Very simple class for setting parameters class CbcParam { public: /**@name Constructor and destructor */ //@{ /// Constructors CbcParam ( ); CbcParam (std::string name, std::string help, double lower, double upper, CbcParameterType type, bool display = true); CbcParam (std::string name, std::string help, int lower, int upper, CbcParameterType type, bool display = true); // Other strings will be added by insert CbcParam (std::string name, std::string help, std::string firstValue, CbcParameterType type, int defaultIndex = 0, bool display = true); // Action CbcParam (std::string name, std::string help, CbcParameterType type, int indexNumber = -1, bool display = true); /// Copy constructor. CbcParam(const CbcParam &); /// Assignment operator. This copies the data CbcParam & operator=(const CbcParam & rhs); /// Destructor ~CbcParam ( ); //@} /**@name stuff */ //@{ /// Insert string (only valid for keywords) void append(std::string keyWord); /// Adds one help line void addHelp(std::string keyWord); /// Returns name inline std::string name( ) const { return name_; }; /// Returns short help inline std::string shortHelp( ) const { return shortHelp_; }; /// Sets a double parameter (nonzero code if error) int setDoubleParameter(CbcModel & model, double value) const; /// Gets a double parameter double doubleParameter(CbcModel & model) const; /// Sets a int parameter (nonzero code if error) int setIntParameter(CbcModel & model, int value) const; /// Gets a int parameter int intParameter(CbcModel & model) const; /// Sets a double parameter (nonzero code if error) int setDoubleParameter(ClpSimplex * model, double value) const; /// Gets a double parameter double doubleParameter(ClpSimplex * model) const; /// Sets a int parameter (nonzero code if error) int setIntParameter(ClpSimplex * model, int value) const; /// Gets a int parameter int intParameter(ClpSimplex * model) const; /// Sets a double parameter (nonzero code if error) int setDoubleParameter(OsiSolverInterface * model, double value) const; /// Gets a double parameter double doubleParameter(OsiSolverInterface * model) const; /// Sets a int parameter (nonzero code if error) int setIntParameter(OsiSolverInterface * model, int value) const; /// Gets a int parameter int intParameter(OsiSolverInterface * model) const; /// Checks a double parameter (nonzero code if error) int checkDoubleParameter(double value) const; /// Returns name which could match std::string matchName ( ) const; /// Returns parameter option which matches (-1 if none) int parameterOption ( std::string check ) const; /// Prints parameter options void printOptions ( ) const; /// Returns current parameter option inline std::string currentOption ( ) const { return definedKeyWords_[currentKeyWord_]; } /// Sets current parameter option inline void setCurrentOption ( int value ) { currentKeyWord_ = value; } /// Sets int value inline void setIntValue ( int value ) { intValue_ = value; } inline int intValue () const { return intValue_; } /// Sets double value inline void setDoubleValue ( double value ) { doubleValue_ = value; } inline double doubleValue () const { return doubleValue_; } /// Sets string value inline void setStringValue ( std::string value ) { stringValue_ = value; } inline std::string stringValue () const { return stringValue_; } /// Returns 1 if matches minimum, 2 if matches less, 0 if not matched int matches (std::string input) const; /// type inline CbcParameterType type() const { return type_; } /// whether to display inline bool displayThis() const { return display_; } /// Set Long help inline void setLonghelp(const std::string help) { longHelp_ = help; } /// Print Long help void printLongHelp() const; /// Print action and string void printString() const; /// type for classification inline int indexNumber() const { return indexNumber_; } private: /// gutsOfConstructor void gutsOfConstructor(); //@} ////////////////// data ////////////////// private: /**@name data We might as well throw all type data in - could derive? */ //@{ // Type see CbcParameterType CbcParameterType type_; /// If double == okay double lowerDoubleValue_; double upperDoubleValue_; /// If int == okay int lowerIntValue_; int upperIntValue_; // Length of name unsigned int lengthName_; // Minimum match unsigned int lengthMatch_; /// set of valid strings std::vector definedKeyWords_; /// Name std::string name_; /// Short help std::string shortHelp_; /// Long help std::string longHelp_; /// Action CbcParameterType action_; /// Current keyWord (if a keyword parameter) int currentKeyWord_; /// Display on ? bool display_; /// Integer parameter - current value int intValue_; /// Double parameter - current value double doubleValue_; /// String parameter - current value std::string stringValue_; /// index number to use for display purposes int indexNumber_; //@} }; #endif /* CbcParam_H */ Cbc-2.8.12/src/CbcThread.cpp0000644000076600007660000021011312230526160014056 0ustar coincoin/* $Id: CbcThread.cpp 1973 2013-10-19 15:59:44Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" //#define THREAD_DEBUG #include #include #include #include #include "CbcEventHandler.hpp" #include "OsiSolverInterface.hpp" #include "OsiRowCutDebugger.hpp" #include "CbcThread.hpp" #include "CbcTree.hpp" #include "CbcHeuristic.hpp" #include "CbcCutGenerator.hpp" #include "CbcModel.hpp" #include "CbcFathom.hpp" #include "CbcSimpleIntegerDynamicPseudoCost.hpp" #include "ClpDualRowDantzig.hpp" #include "OsiAuxInfo.hpp" #include "CoinTime.hpp" #ifdef CBC_THREAD /// Thread functions static void * doNodesThread(void * voidInfo); static void * doCutsThread(void * voidInfo); static void * doHeurThread(void * voidInfo); // Default Constructor CbcSpecificThread::CbcSpecificThread () : basePointer_(NULL), masterMutex_(NULL), locked_(false) { #ifdef CBC_PTHREAD pthread_mutex_init(&mutex2_, NULL); pthread_cond_init(&condition2_, NULL); threadId_.status = 0; #else #endif } // Useful Constructor CbcSpecificThread::CbcSpecificThread (CbcSpecificThread * master, pthread_mutex_t * masterMutex) : basePointer_(master), masterMutex_(masterMutex), locked_(false) { #ifdef CBC_PTHREAD pthread_mutex_init(&mutex2_, NULL); pthread_cond_init(&condition2_, NULL); threadId_.status = 0; #else #endif } // Useful stuff void CbcSpecificThread::setUsefulStuff (CbcSpecificThread * master, void *& masterMutex) { #ifdef CBC_PTHREAD basePointer_ = master; if (masterMutex) { masterMutex_ = reinterpret_cast(masterMutex); } else { // create master mutex masterMutex_ = new pthread_mutex_t; pthread_mutex_init(masterMutex_, NULL); masterMutex = reinterpret_cast(masterMutex_); } #else #endif } CbcSpecificThread::~CbcSpecificThread() { #ifdef CBC_PTHREAD pthread_mutex_destroy (&mutex2_); if (basePointer_ == this) { pthread_mutex_destroy (masterMutex_); delete masterMutex_; } #else #endif } /* Locks a thread if parallel so that stuff like cut pool can be updated and/or used. */ void CbcSpecificThread::lockThread() { #ifdef CBC_PTHREAD // Use master mutex assert (basePointer_->masterMutex_ == masterMutex_); pthread_mutex_lock (masterMutex_); #else #endif } /* Unlocks a thread if parallel to say cut pool stuff not needed */ void CbcSpecificThread::unlockThread() { #ifdef CBC_PTHREAD // Use master mutex pthread_mutex_unlock (masterMutex_); #else #endif } // Locks a thread for testing whether to start etc void CbcSpecificThread::lockThread2(bool doAnyway) { if (!locked_ || doAnyway) { #ifdef CBC_PTHREAD pthread_mutex_lock (&mutex2_); #else #endif locked_ = true; } } // Unlocks a thread for testing whether to start etc void CbcSpecificThread::unlockThread2(bool doAnyway) { if (locked_ || doAnyway) { #ifdef CBC_PTHREAD pthread_mutex_unlock (&mutex2_); #else #endif locked_ = false; } } #ifdef HAVE_CLOCK_GETTIME inline int my_gettime(struct timespec* tp) { return clock_gettime(CLOCK_REALTIME, tp); } #else #ifndef _MSC_VER inline int my_gettime(struct timespec* tp) { struct timeval tv; int ret = gettimeofday(&tv, NULL); tp->tv_sec = tv.tv_sec; tp->tv_nsec = tv.tv_usec * 1000; return ret; } #else inline int my_gettime(struct timespec* tp) { double t = CoinGetTimeOfDay(); tp->tv_sec = (int)floor(t); tp->tv_nsec = (int)((tp->tv_sec - floor(t)) / 1000000.0); return 0; } #endif #endif // Get time static double getTime() { struct timespec absTime2; my_gettime(&absTime2); double time2 = (double)absTime2.tv_sec + 1.0e-9 * (double)absTime2.tv_nsec; return time2; } // Timed wait in nanoseconds - if negative then seconds void CbcSpecificThread::timedWait(int time) { #ifdef CBC_PTHREAD struct timespec absTime; my_gettime(&absTime); if (time > 0) { absTime.tv_nsec += time; if (absTime.tv_nsec >= 1000000000) { absTime.tv_nsec -= 1000000000; absTime.tv_sec++; } } else { absTime.tv_sec -= time; } pthread_cond_timedwait(&condition2_, &mutex2_, &absTime); #else #endif } // Signal void CbcSpecificThread::signal() { #ifdef CBC_PTHREAD pthread_cond_signal(&condition2_); #else #endif } // Actually starts a thread void CbcSpecificThread::startThread(void * (*routine ) (void *), CbcThread * thread) { #ifdef CBC_PTHREAD pthread_create(&(threadId_.thr), NULL, routine, thread); threadId_.status = 1; #else #endif } // Exits thread (from master) int CbcSpecificThread::exit() { #ifdef CBC_PTHREAD pthread_cond_signal(&condition2_); // unlock return pthread_join(threadId_.thr, NULL); #else #endif } // Exits thread void CbcSpecificThread::exitThread() { #ifdef CBC_PTHREAD pthread_mutex_unlock(&mutex2_); pthread_exit(NULL); #else #endif } // Get status int CbcSpecificThread::status() const { #ifdef CBC_PTHREAD return static_cast(threadId_.status); #else #endif } // Set status void CbcSpecificThread::setStatus(int value) { #ifdef CBC_PTHREAD threadId_.status = value; #else #endif } // Parallel heuristics void parallelHeuristics (int numberThreads, int sizeOfData, void * argBundle) { Coin_pthread_t * threadId = new Coin_pthread_t [numberThreads]; char * args = reinterpret_cast(argBundle); for (int i = 0; i < numberThreads; i++) { pthread_create(&(threadId[i].thr), NULL, doHeurThread, args + i*sizeOfData); } // now wait for (int i = 0; i < numberThreads; i++) { pthread_join(threadId[i].thr, NULL); } delete [] threadId; } // End of specific thread stuff /// Default constructor CbcThread::CbcThread() : baseModel_(NULL), thisModel_(NULL), node_(NULL), // filled in every time createdNode_(NULL), // filled in every time on return returnCode_(-1), // -1 available, 0 busy, 1 finished , 2?? timeLocked_(0.0), timeWaitingToLock_(0.0), timeWaitingToStart_(0.0), timeInThread_(0.0), numberTimesLocked_(0), numberTimesUnlocked_(0), numberTimesWaitingToStart_(0), dantzigState_(0), // 0 unset, -1 waiting to be set, 1 set locked_(false), nDeleteNode_(0), delNode_(NULL), maxDeleteNode_(0), nodesThisTime_(0), iterationsThisTime_(0), deterministic_(0) { } void CbcThread::gutsOfDelete() { baseModel_ = NULL; thisModel_ = NULL; node_ = NULL; createdNode_ = NULL; delNode_ = NULL; } // Destructor CbcThread::~CbcThread() { } // Fills in useful stuff void CbcThread::setUsefulStuff (CbcModel * model, int deterministic, CbcModel * baseModel, CbcThread * master, void *& masterMutex) { baseModel_ = baseModel; thisModel_ = model; deterministic_ = deterministic; threadStuff_.setUsefulStuff(&master->threadStuff_, masterMutex); node_ = NULL; createdNode_ = NULL; master_ = master; returnCode_ = -1; timeLocked_ = 0.0; timeWaitingToLock_ = 0.0; timeWaitingToStart_ = 0.0; timeInThread_ = 0.0; numberTimesLocked_ = 0; numberTimesUnlocked_ = 0; numberTimesWaitingToStart_ = 0; dantzigState_ = 0; // 0 unset, -1 waiting to be set, 1 set locked_ = false; delNode_ = NULL; maxDeleteNode_ = 0; nDeleteNode_ = 0; nodesThisTime_ = 0; iterationsThisTime_ = 0; if (model != baseModel) { // thread thisModel_->setInfoInChild(-3, this); if (deterministic_ >= 0) thisModel_->moveToModel(baseModel, -1); if (deterministic == -1) threadStuff_.startThread( doCutsThread, this); else threadStuff_.startThread( doNodesThread, this); } } /* Locks a thread if parallel so that stuff like cut pool can be updated and/or used. */ void CbcThread::lockThread() { if (!locked_) { double time2 = getTime(); threadStuff_.lockThread(); locked_ = true; timeWhenLocked_ = getTime(); timeWaitingToLock_ += timeWhenLocked_ - time2;; numberTimesLocked_++; #ifdef THREAD_DEBUG lockCount_ ++; #if THREAD_DEBUG>1 if (threadNumber_ == -1) printf("locking master %d\n", lockCount_); else printf("locking thread %d %d\n", threadNumber_, lockCount_); #endif } else { if (threadNumber_ == -1) printf("master already locked %d\n", lockCount_); else printf("thread already locked %d %d\n", threadNumber_, lockCount_); #endif } } /* Unlocks a thread if parallel */ void CbcThread::unlockThread() { if (locked_) { locked_ = false; threadStuff_.unlockThread(); double time2 = getTime(); timeLocked_ += time2 - timeWhenLocked_; numberTimesUnlocked_++; #ifdef THREAD_DEBUG #if THREAD_DEBUG>1 if (threadNumber_ == -1) printf("unlocking master %d\n", lockCount_); else printf("unlocking thread %d %d\n", threadNumber_, lockCount_); #endif } else { if (threadNumber_ == -1) printf("master already unlocked %d\n", lockCount_); else printf("thread already unlocked %d %d\n", threadNumber_, lockCount_); #endif } } /* Wait for child to have return code NOT == to currentCode type - 0 timed wait 1 wait returns true if return code changed */ bool CbcThread::wait(int type, int currentCode) { if (!type) { // just timed wait master_->threadStuff_.lockThread2(); master_->threadStuff_.timedWait(1000000); master_->threadStuff_.unlockThread2(); } else { // wait until return code changes while (returnCode_ == currentCode) { threadStuff_.signal(); master_->threadStuff_.lockThread2(); master_->threadStuff_.timedWait(1000000); master_->threadStuff_.unlockThread2(); } } return (returnCode_ != currentCode); } #if 0 pthread_cond_signal(&condition2_); - if (!locked_) { pthread_mutex_lock (&mutex2_); locked_ = true; } - pthread_cond_timedwait(&condition2_, &mutex2_, &absTime); - if (locked_) { pthread_mutex_unlock (&mutex2_); locked_ = false; } #endif // Waits until returnCode_ goes to zero void CbcThread::waitThread() { double time = getTime(); threadStuff_.lockThread2(); while (returnCode_) { threadStuff_.timedWait(-10); // 10 seconds } timeWaitingToStart_ += getTime() - time; numberTimesWaitingToStart_++; } // Just wait for so many nanoseconds void CbcThread::waitNano(int time) { threadStuff_.lockThread2(); threadStuff_.timedWait(time); threadStuff_.unlockThread2(); } // Signal child to carry on void CbcThread::signal() { threadStuff_.signal(); } // Lock from master with mutex2 and signal before lock void CbcThread::lockFromMaster() { threadStuff_.signal(); master_->threadStuff_.lockThread2(true); } // Unlock from master with mutex2 and signal after unlock void CbcThread::unlockFromMaster() { master_->threadStuff_.unlockThread2(true); // unlock anyway threadStuff_.signal(); } // Lock from thread with mutex2 and signal before lock void CbcThread::lockFromThread() { master_->threadStuff_.signal(); threadStuff_.lockThread2(); } // Unlock from thread with mutex2 and signal after unlock void CbcThread::unlockFromThread() { master_->threadStuff_.signal(); threadStuff_.unlockThread2(); } // Exits thread (from master) int CbcThread::exit() { return threadStuff_.exit(); } // Exits thread void CbcThread::exitThread() { threadStuff_.exitThread(); } // Default constructor CbcBaseModel::CbcBaseModel() : numberThreads_(0), children_(NULL), type_(0), threadCount_(NULL), threadModel_(NULL), numberObjects_(0), saveObjects_(NULL), defaultParallelIterations_(400), defaultParallelNodes_(2) { } // Constructor with model CbcBaseModel::CbcBaseModel (CbcModel & model, int type) : children_(NULL), type_(type), threadCount_(NULL), threadModel_(NULL), numberObjects_(0), saveObjects_(NULL), defaultParallelIterations_(400), defaultParallelNodes_(2) { numberThreads_ = model.getNumberThreads(); if (numberThreads_) { children_ = new CbcThread [numberThreads_+1]; // Do a partial one for base model void * mutex_main = NULL; children_[numberThreads_].setUsefulStuff(&model, type_, &model, children_ + numberThreads_, mutex_main); #ifdef THREAD_DEBUG children_[numberThreads_].threadNumber_ = -1; children_[numberThreads_].lockCount_ = 0; #endif threadCount_ = new int [numberThreads_]; CoinZeroN(threadCount_, numberThreads_); threadModel_ = new CbcModel * [numberThreads_+1]; memset(threadStats_, 0, sizeof(threadStats_)); if (type_ > 0) { // May need for deterministic numberObjects_ = model.numberObjects(); saveObjects_ = new OsiObject * [numberObjects_]; for (int i = 0; i < numberObjects_; i++) { saveObjects_[i] = model.object(i)->clone(); } } // we don't want a strategy object CbcStrategy * saveStrategy = model.strategy(); model.setStrategy(NULL); for (int i = 0; i < numberThreads_; i++) { //threadModel_[i] = new CbcModel(model, true); threadModel_[i] = model. clone (true); threadModel_[i]->synchronizeHandlers(1); #ifdef COIN_HAS_CLP // Solver may need to know about model CbcModel * thisModel = threadModel_[i]; CbcOsiSolver * solver = dynamic_cast(thisModel->solver()) ; if (solver) solver->setCbcModel(thisModel); #endif children_[i].setUsefulStuff(threadModel_[i], type_, &model, children_ + numberThreads_, mutex_main); #ifdef THREAD_DEBUG children_[i].threadNumber_ = i; children_[i].lockCount_ = 0; #endif } model.setStrategy(saveStrategy); } } // Stop threads void CbcBaseModel::stopThreads(int type) { if (type < 0) { // max nodes ? bool finished = false; while (!finished) { finished = true; for (int i = 0; i < numberThreads_; i++) { if (abs(children_[i].returnCode()) != 1) { children_[i].wait(1, 0); finished=false; } } } return; } for (int i = 0; i < numberThreads_; i++) { children_[i].wait(1, 0); assert (children_[i].returnCode() == -1); threadModel_[i]->setInfoInChild(-2, NULL); children_[i].setReturnCode( 0); children_[i].exit(); children_[i].setStatus( 0); } // delete models and solvers for (int i = 0; i < numberThreads_; i++) { threadModel_[i]->setInfoInChild(type_, NULL); delete threadModel_[i]; } delete [] children_; delete [] threadModel_; for (int i = 0; i < numberObjects_; i++) delete saveObjects_[i]; delete [] saveObjects_; children_ = NULL; threadModel_ = NULL; saveObjects_ = NULL; numberObjects_ = 0; numberThreads_ = 0; } // Wait for threads in tree int CbcBaseModel::waitForThreadsInTree(int type) { CbcModel * baseModel = children_[0].baseModel(); int anyLeft = 0; // May be able to combine parts later if (type == 0) { bool locked = true; #ifdef COIN_DEVELOP printf("empty\n"); #endif // may still be outstanding nodes while (true) { int iThread; for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].status()) { if (children_[iThread].returnCode() == 0) break; } } if (iThread < numberThreads_) { #ifdef COIN_DEVELOP printf("waiting for thread %d code 0\n", iThread); #endif unlockThread(); locked = false; children_[iThread].wait(1, 0); assert(children_[iThread].returnCode() == 1); threadModel_[iThread]->moveToModel(baseModel, 1); #ifdef THREAD_PRINT printf("off thread2 %d node %x\n", iThread, children_[iThread].node()); #endif children_[iThread].setNode(NULL); anyLeft = 1; assert (children_[iThread].returnCode() == 1); if (children_[iThread].dantzigState() == -1) { // 0 unset, -1 waiting to be set, 1 set children_[iThread].setDantzigState(1); CbcModel * model = children_[iThread].thisModel(); OsiClpSolverInterface * clpSolver2 = dynamic_cast (model->solver()); assert (clpSolver2); ClpSimplex * simplex2 = clpSolver2->getModelPtr(); ClpDualRowDantzig dantzig; simplex2->setDualRowPivotAlgorithm(dantzig); } // say available children_[iThread].setReturnCode( -1); threadStats_[4]++; #ifdef COIN_DEVELOP printf("thread %d code now -1\n", iThread); #endif break; } else { #ifdef COIN_DEVELOP printf("no threads at code 0 \n"); #endif // now check if any have just finished for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].status()) { if (children_[iThread].returnCode() == 1) break; } } if (iThread < numberThreads_) { unlockThread(); locked = false; threadModel_[iThread]->moveToModel(baseModel, 1); #ifdef THREAD_PRINT printf("off thread3 %d node %x\n", iThread, children_[iThread].node()); #endif children_[iThread].setNode(NULL); anyLeft = 1; assert (children_[iThread].returnCode() == 1); // say available children_[iThread].setReturnCode( -1); threadStats_[4]++; #ifdef COIN_DEVELOP printf("thread %d code now -1\n", iThread); #endif break; } } if (!baseModel->tree()->empty()) { #ifdef COIN_DEVELOP printf("tree not empty!!!!!!\n"); #endif if (locked) unlockThread(); return 1; break; } for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].status()) { if (children_[iThread].returnCode() != -1) { printf("bad end of tree\n"); abort(); } } } break; } #ifdef COIN_DEVELOP printf("finished ************\n"); #endif if (locked) unlockThread(); return anyLeft; } else if (type == 1) { // normal double cutoff = baseModel->getCutoff(); CbcNode * node = baseModel->tree()->bestNode(cutoff) ; // Possible one on tree worse than cutoff if (!node || node->objectiveValue() > cutoff) return 1; threadStats_[0]++; //need to think int iThread; // Start one off if any available for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].returnCode() == -1) break; } if (iThread < numberThreads_) { children_[iThread].setNode(node); #ifdef THREAD_PRINT printf("empty thread %d node %x\n", iThread, children_[iThread].node()); #endif assert (children_[iThread].returnCode() == -1); // say in use threadModel_[iThread]->moveToModel(baseModel, 0); // This has to be AFTER moveToModel children_[iThread].setReturnCode( 0); children_[iThread].signal(); threadCount_[iThread]++; } lockThread(); // see if any finished for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].returnCode() > 0) break; } unlockThread(); if (iThread < numberThreads_) { threadModel_[iThread]->moveToModel(baseModel, 1); #ifdef THREAD_PRINT printf("off thread4 %d node %x\n", iThread, children_[iThread].node()); #endif children_[iThread].setNode(NULL); anyLeft = 1; assert (children_[iThread].returnCode() == 1); // say available children_[iThread].setReturnCode( -1); // carry on threadStats_[3]++; } else { // Start one off if any available for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].returnCode() == -1) break; } if (iThread < numberThreads_) { // If any on tree get if (!baseModel->tree()->empty()) { //node = baseModel->tree()->bestNode(cutoff) ; //assert (node); threadStats_[1]++; return 1; // ** get another node } } // wait (for debug could sleep and use test) bool finished = false; while (!finished) { double time = getTime(); children_[numberThreads_].wait(0, 0); children_[numberThreads_].incrementTimeInThread(getTime() - time); for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].returnCode() > 0) { finished = true; break; } else if (children_[iThread].returnCode() == 0) { children_[iThread].signal(); // unlock } } } assert (iThread < numberThreads_); // move information to model threadModel_[iThread]->moveToModel(baseModel, 1); anyLeft = 1; #ifdef THREAD_PRINT printf("off thread %d node %x\n", iThread, children_[iThread].node()); #endif children_[iThread].setNode(NULL); assert (children_[iThread].returnCode() == 1); // say available children_[iThread].setReturnCode( -1); } // carry on threadStats_[2]++; for (int iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].status()) { if (children_[iThread].returnCode() != -1) { anyLeft = 1; break; } } } return anyLeft; } else if (type == 2) { if (!baseModel->tree()->empty()) { // max nodes ? bool finished = false; while (!finished) { finished = true; for (int iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].returnCode() == 0) { double time = getTime(); children_[numberThreads_].wait(0, 0); children_[numberThreads_].incrementTimeInThread(getTime() - time); finished = false; children_[iThread].signal(); // unlock } } } } int i; // do statistics // Seems to be bug in CoinCpu on Linux - does threads as well despite documentation double time = 0.0; for (i = 0; i < numberThreads_; i++) time += children_[i].timeInThread(); bool goodTimer = time < (baseModel->getCurrentSeconds()); for (i = 0; i < numberThreads_; i++) { while (children_[i].returnCode() == 0) { children_[i].signal(); double time = getTime(); children_[numberThreads_].wait(0, 0); children_[numberThreads_].incrementTimeInThread(getTime() - time); } children_[i].lockFromMaster(); threadModel_[i]->setNumberThreads(0); // say exit if (children_[i].deterministic() > 0) delete [] children_[i].delNode(); children_[i].setReturnCode( 0); children_[i].unlockFromMaster(); #ifndef NDEBUG int returnCode = children_[i].exit(); assert (!returnCode); #else children_[i].exit(); #endif children_[i].setStatus( 0); //else threadModel_[i]->moveToModel(baseModel, 2); assert (children_[i].numberTimesLocked() == children_[i].numberTimesUnlocked()); baseModel->messageHandler()->message(CBC_THREAD_STATS, baseModel->messages()) << "Thread"; baseModel->messageHandler()->printing(true) << i << threadCount_[i] << children_[i].timeWaitingToStart(); baseModel->messageHandler()->printing(goodTimer) << children_[i].timeInThread(); baseModel->messageHandler()->printing(false) << 0.0; baseModel->messageHandler()->printing(true) << children_[i].numberTimesLocked() << children_[i].timeLocked() << children_[i].timeWaitingToLock() << CoinMessageEol; } assert (children_[numberThreads_].numberTimesLocked() == children_[numberThreads_].numberTimesUnlocked()); baseModel->messageHandler()->message(CBC_THREAD_STATS, baseModel->messages()) << "Main thread"; baseModel->messageHandler()->printing(false) << 0 << 0 << 0.0; baseModel->messageHandler()->printing(false) << 0.0; baseModel->messageHandler()->printing(true) << children_[numberThreads_].timeInThread(); baseModel->messageHandler()->printing(true) << children_[numberThreads_].numberTimesLocked() << children_[numberThreads_].timeLocked() << children_[numberThreads_].timeWaitingToLock() << CoinMessageEol; // delete models (here in case some point to others) for (i = 0; i < numberThreads_; i++) { // make sure handler will be deleted threadModel_[i]->setDefaultHandler(true); //delete threadModel_[i]; } } else { abort(); } return 0; } void CbcBaseModel::waitForThreadsInCuts(int type, OsiCuts * eachCuts, int whichGenerator) { if (type == 0) { // cuts while doing bool finished = false; int iThread = -1; // see if any available for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].returnCode()) { finished = true; break; } else if (children_[iThread].returnCode() == 0) { children_[iThread].signal(); } } while (!finished) { children_[numberThreads_].waitNano(1000000); for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].returnCode() > 0) { finished = true; break; } else if (children_[iThread].returnCode() == 0) { children_[iThread].signal(); } } } assert (iThread < numberThreads_); assert (children_[iThread].returnCode()); // Use dantzigState to signal which generator children_[iThread].setDantzigState(whichGenerator); // and delNode for eachCuts children_[iThread].fakeDelNode(reinterpret_cast (eachCuts)); // allow to start children_[iThread].setReturnCode( 0); children_[iThread].signal(); } else if (type == 1) { // cuts - finish up for (int iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].returnCode() == 0) { bool finished = false; while (!finished) { children_[numberThreads_].wait(0, 0); if (children_[iThread].returnCode() > 0) { finished = true; break; //#ifndef NEW_STYLE_PTHREAD //} else if (children_[iThread].returnCode_ == 0) { //pthread_cond_signal(&children_[iThread].threadStuff_.condition2_); // unlock //#endif } } } assert (children_[iThread].returnCode()); // say available children_[iThread].setReturnCode( -1); //delete threadModel_[iThread]->solver(); //threadModel_[iThread]->setSolver(NULL); } } else { abort(); } } // Returns pointer to master thread CbcThread * CbcBaseModel::masterThread() const { return children_ + numberThreads_; } // Split model and do work in deterministic parallel void CbcBaseModel::deterministicParallel() { CbcModel * baseModel = children_[0].baseModel(); for (int i = 0; i < numberThreads_; i++) threadCount_[i]++; int saveTreeSize = baseModel->tree()->size(); // For now create threadModel - later modify splitModel CbcModel ** threadModel = new CbcModel * [numberThreads_]; int iThread; for (iThread = 0; iThread < numberThreads_; iThread++) threadModel[iThread] = children_[iThread].thisModel(); int nAffected = baseModel->splitModel(numberThreads_, threadModel, defaultParallelNodes_); // do all until finished for (iThread = 0; iThread < numberThreads_; iThread++) { // obviously tune children_[iThread].setNDeleteNode(defaultParallelIterations_); } // Save current state int iObject; OsiObject ** object = baseModel->objects(); for (iObject = 0; iObject < numberObjects_; iObject++) { saveObjects_[iObject]->updateBefore(object[iObject]); } //#define FAKE_PARALLEL #ifndef FAKE_PARALLEL for (iThread = 0; iThread < numberThreads_; iThread++) { children_[iThread].setReturnCode( 0); children_[iThread].signal(); } // wait bool finished = false; double time = getTime(); while (!finished) { children_[numberThreads_].waitNano( 1000000); // millisecond finished = true; for (iThread = 0; iThread < numberThreads_; iThread++) { if (children_[iThread].returnCode() <= 0) { finished = false; } } } for (iThread = 0; iThread < numberThreads_; iThread++) children_[iThread].setReturnCode(-1); #else // wait bool finished = false; double time = getTime(); for (iThread = 0; iThread < numberThreads_; iThread++) { children_[iThread].setReturnCode( 0); children_[iThread].signal(); while (!finished) { children_[numberThreads_].waitNano( 1000000); // millisecond finished = (children_[iThread].returnCode() >0); } children_[iThread].setReturnCode(-1); finished=false; } #endif children_[numberThreads_].incrementTimeInThread(getTime() - time); // Unmark marked for (int i = 0; i < nAffected; i++) { baseModel->walkback()[i]->unmark(); } int iModel; double scaleFactor = 1.0; for (iModel = 0; iModel < numberThreads_; iModel++) { //printf("model %d tree size %d\n",iModel,threadModel[iModel]->baseModel->tree()->size()); if (saveTreeSize > 4*numberThreads_*defaultParallelNodes_) { if (!threadModel[iModel]->tree()->size()) { scaleFactor *= 1.05; } } threadModel[iModel]->moveToModel(baseModel, 11); // Update base model OsiObject ** threadObject = threadModel[iModel]->objects(); for (iObject = 0; iObject < numberObjects_; iObject++) { object[iObject]->updateAfter(threadObject[iObject], saveObjects_[iObject]); } } if (scaleFactor != 1.0) { int newNumber = static_cast (defaultParallelNodes_ * scaleFactor + 0.5001); if (newNumber*2 < defaultParallelIterations_) { if (defaultParallelNodes_ == 1) newNumber = 2; if (newNumber != defaultParallelNodes_) { char general[200]; sprintf(general, "Changing tree size from %d to %d", defaultParallelNodes_, newNumber); baseModel->messageHandler()->message(CBC_GENERAL, baseModel->messages()) << general << CoinMessageEol ; defaultParallelNodes_ = newNumber; } } } delete [] threadModel; } // Destructor CbcBaseModel::~CbcBaseModel() { delete [] threadCount_; #if 1 for (int i = 0; i < numberThreads_; i++) delete threadModel_[i]; delete [] threadModel_; delete [] children_; #endif for (int i = 0; i < numberObjects_; i++) delete saveObjects_[i]; delete [] saveObjects_; } // Sets Dantzig state in children void CbcBaseModel::setDantzigState() { for (int i = 0; i < numberThreads_; i++) { children_[i].setDantzigState(-1); } } static void * doNodesThread(void * voidInfo) { CbcThread * stuff = reinterpret_cast (voidInfo); CbcModel * thisModel = stuff->thisModel(); CbcModel * baseModel = stuff->baseModel(); while (true) { stuff->waitThread(); //printf("start node %x\n",stuff->node); int mode = thisModel->getNumberThreads(); if (mode) { // normal double time2 = CoinCpuTime(); assert (stuff->returnCode() == 0); if (thisModel->parallelMode() >= 0) { CbcNode * node = stuff->node(); //assert (node->nodeInfo()); CbcNode * createdNode = stuff->createdNode(); // try and see if this has slipped through if (node) { thisModel->doOneNode(baseModel, node, createdNode); } else { //printf("null node\n"); createdNode=NULL; } stuff->setNode(node); stuff->setCreatedNode(createdNode); stuff->setReturnCode( 1); } else { assert (!stuff->node()); assert (!stuff->createdNode()); int numberIterations = stuff->nDeleteNode(); int nDeleteNode = 0; int maxDeleteNode = stuff->maxDeleteNode(); CbcNode ** delNode = stuff->delNode(); int returnCode = 1; // this should be updated by heuristics strong branching etc etc assert (numberIterations > 0); thisModel->setNumberThreads(0); int nodesThisTime = thisModel->getNodeCount(); int iterationsThisTime = thisModel->getIterationCount(); int strongThisTime = thisModel->numberStrongIterations(); thisModel->setStopNumberIterations(thisModel->getIterationCount() + numberIterations); int numberColumns = thisModel->getNumCols(); int * used = CoinCopyOfArray(thisModel->usedInSolution(), numberColumns); int numberSolutions = thisModel->getSolutionCount(); while (true) { if (thisModel->tree()->empty()) { returnCode = 1 + 1; #ifdef CLP_INVESTIGATE_2 printf("%x tree empty - time %18.6f\n", thisModel, CoinGetTimeOfDay() - 1.2348e9); #endif break; } #define NODE_ITERATIONS 2 int nodesNow = thisModel->getNodeCount(); int iterationsNow = thisModel->getIterationCount(); int strongNow = thisModel->numberStrongIterations(); bool exit1 = (NODE_ITERATIONS * ((nodesNow - nodesThisTime) + ((strongNow - strongThisTime) >> 1)) + (iterationsNow - iterationsThisTime) > numberIterations); //bool exit2 =(thisModel->getIterationCount()>thisModel->getStopNumberIterations()) ; //assert (exit1==exit2); if (exit1 && nodesNow - nodesThisTime >= 10) { // out of loop //printf("out of loop\n"); #ifdef CLP_INVESTIGATE3 printf("%x tree %d nodes left, done %d and %d its - time %18.6f\n", thisModel, thisModel->tree()->size(), nodesNow - nodesThisTime, iterationsNow - iterationsThisTime, CoinGetTimeOfDay() - 1.2348e9); #endif break; } double cutoff = thisModel->getCutoff() ; CbcNode *node = thisModel->tree()->bestNode(cutoff) ; // Possible one on tree worse than cutoff if (!node) continue; CbcNode * createdNode = NULL; // Do real work of node thisModel->doOneNode(NULL, node, createdNode); assert (createdNode); if (!createdNode->active()) { delete createdNode; } else { // Say one more pointing to this **** postpone if marked node->nodeInfo()->increment() ; thisModel->tree()->push(createdNode) ; } if (node->active()) { assert (node->nodeInfo()); if (node->nodeInfo()->numberBranchesLeft()) { thisModel->tree()->push(node) ; } else { node->setActive(false); } } else { if (node->nodeInfo()) { if (!node->nodeInfo()->numberBranchesLeft()) node->nodeInfo()->allBranchesGone(); // can clean up // So will delete underlying stuff node->setActive(true); } if (nDeleteNode == maxDeleteNode) { maxDeleteNode = (3 * maxDeleteNode) / 2 + 10; stuff->setMaxDeleteNode(maxDeleteNode); stuff->setDelNode(new CbcNode * [maxDeleteNode]); for (int i = 0; i < nDeleteNode; i++) stuff->delNode()[i] = delNode[i]; delete [] delNode; delNode = stuff->delNode(); } delNode[nDeleteNode++] = node; } } // end of this sub-tree int * usedA = thisModel->usedInSolution(); for (int i = 0; i < numberColumns; i++) { usedA[i] -= used[i]; } delete [] used; thisModel->setSolutionCount(thisModel->getSolutionCount() - numberSolutions); stuff->setNodesThisTime(thisModel->getNodeCount() - nodesThisTime); stuff->setIterationsThisTime(thisModel->getIterationCount() - iterationsThisTime); stuff->setNDeleteNode(nDeleteNode); stuff->setReturnCode( returnCode); thisModel->setNumberThreads(mode); } //printf("end node %x\n",stuff->node); stuff->unlockFromThread(); stuff->incrementTimeInThread(CoinCpuTime() - time2); } else { // exit break; } } //printf("THREAD exiting\n"); stuff->exitThread(); return NULL; } static void * doHeurThread(void * voidInfo) { typedef struct { double solutionValue; CbcModel * model; double * solution; int foundSol; } argBundle; argBundle * stuff = reinterpret_cast (voidInfo); stuff->foundSol = stuff->model->heuristic(0)->solution(stuff->solutionValue, stuff->solution); return NULL; } static void * doCutsThread(void * voidInfo) { CbcThread * stuff = reinterpret_cast (voidInfo); CbcModel * thisModel = stuff->thisModel(); while (true) { stuff->waitThread(); //printf("start node %x\n",stuff->node); int mode = thisModel->getNumberThreads(); if (mode) { // normal assert (stuff->returnCode() == 0); int fullScan = thisModel->getNodeCount() == 0 ? 1 : 0; //? was >0 CbcCutGenerator * generator = thisModel->cutGenerator(stuff->dantzigState()); generator->refreshModel(thisModel); OsiCuts * cuts = reinterpret_cast (stuff->delNode()); OsiSolverInterface * thisSolver = thisModel->solver(); generator->generateCuts(*cuts, fullScan, thisSolver, NULL); stuff->setReturnCode( 1); stuff->unlockFromThread(); } else { // exit break; } } stuff->exitThread(); return NULL; } // Split up nodes - returns number of CbcNodeInfo's affected int CbcModel::splitModel(int numberModels, CbcModel ** model, int numberNodes) { int iModel; int i; for (iModel = 0; iModel < numberModels; iModel++) { CbcModel * otherModel = model[iModel]; otherModel->moveToModel(this, 10); assert (!otherModel->tree()->size()); otherModel->tree()->resetNodeNumbers(); otherModel->bestPossibleObjective_ = bestPossibleObjective_; otherModel->sumChangeObjective1_ = sumChangeObjective1_; otherModel->sumChangeObjective2_ = sumChangeObjective2_; int numberColumns = solver_->getNumCols(); if (otherModel->bestSolution_) { assert (bestSolution_); memcpy(otherModel->bestSolution_, bestSolution_, numberColumns*sizeof(double)); } else if (bestSolution_) { otherModel->bestSolution_ = CoinCopyOfArray(bestSolution_, numberColumns); } otherModel->globalCuts_ = globalCuts_; otherModel->numberSolutions_ = numberSolutions_; otherModel->numberHeuristicSolutions_ = numberHeuristicSolutions_; otherModel->numberNodes_ = 1; //numberNodes_; otherModel->numberIterations_ = numberIterations_; #ifdef JJF_ZERO if (maximumNumberCuts_ > otherModel->maximumNumberCuts_) { otherModel->maximumNumberCuts_ = maximumNumberCuts_; delete [] otherModel->addedCuts_; otherModel->addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_]; } if (maximumDepth_ > otherModel->maximumDepth_) { otherModel->maximumDepth_ = maximumDepth_; delete [] otherModel->walkback_; otherModel->walkback_ = new CbcNodeInfo * [maximumDepth_]; } #endif otherModel->currentNumberCuts_ = currentNumberCuts_; if (otherModel->usedInSolution_) { assert (usedInSolution_); memcpy(otherModel->usedInSolution_, usedInSolution_, numberColumns*sizeof(int)); } else if (usedInSolution_) { otherModel->usedInSolution_ = CoinCopyOfArray(usedInSolution_, numberColumns); } /// ??? tree_; // Need flag (stopNumberIterations_>0?) which says don't update cut etc counts for (i = 0; i < numberObjects_; i++) { otherModel->object_[i]->updateBefore(object_[i]); } otherModel->maximumDepthActual_ = maximumDepthActual_; // Real cuts are in node info otherModel->numberOldActiveCuts_ = numberOldActiveCuts_; otherModel->numberNewCuts_ = numberNewCuts_; otherModel->numberStrongIterations_ = numberStrongIterations_; } double cutoff = getCutoff(); int nAffected = 0; while (!tree_->empty()) { for (iModel = 0; iModel < numberModels; iModel++) { if (tree_->empty()) break; CbcModel * otherModel = model[iModel]; CbcNode * node = tree_->bestNode(cutoff) ; CbcNodeInfo * nodeInfo = node->nodeInfo(); assert (nodeInfo); if (!nodeInfo->marked()) { //while (nodeInfo&&!nodeInfo->marked()) { if (nAffected == maximumDepth_) { redoWalkBack(); } nodeInfo->mark(); //nodeInfo->incrementCuts(1000000); walkback_[nAffected++] = nodeInfo; //nodeInfo = nodeInfo->parent() ; //} } // Make node join otherModel OsiBranchingObject * bobj = node->modifiableBranchingObject(); CbcBranchingObject * cbcobj = dynamic_cast (bobj); //assert (cbcobj); if (cbcobj) { CbcObject * object = cbcobj->object(); assert (object); int position = object->position(); assert (position >= 0); assert (object_[position] == object); CbcObject * objectNew = dynamic_cast (otherModel->object_[position]); cbcobj->setOriginalObject(objectNew); } otherModel->tree_->push(node); } numberNodes--; if (!numberNodes) break; } return nAffected; } // Start threads void CbcModel::startSplitModel(int /*numberIterations*/) { abort(); } // Merge models void CbcModel::mergeModels(int /*numberModel*/, CbcModel ** /*model*/, int /*numberNodes*/) { abort(); } /* Move/copy information from one model to another -1 - initial setup 0 - from base model 1 - to base model (and reset) 2 - add in final statistics etc (and reset so can do clean destruction) 10 - from base model (deterministic) 11 - to base model (deterministic) */ void CbcModel::moveToModel(CbcModel * baseModel, int mode) { if (mode == 0) { setCutoff(baseModel->getCutoff()); bestObjective_ = baseModel->bestObjective_; //assert (!baseModel->globalCuts_.sizeRowCuts()); if (numberSolutions_ < baseModel->numberSolutions_) { assert (baseModel->bestSolution_); int numberColumns = solver_->getNumCols(); if (!bestSolution_) bestSolution_ = new double [numberColumns]; memcpy(bestSolution_,baseModel->bestSolution_, numberColumns*sizeof(double)); numberSolutions_ = baseModel->numberSolutions_; } stateOfSearch_ = baseModel->stateOfSearch_; numberNodes_ = baseModel->numberNodes_; numberIterations_ = baseModel->numberIterations_; numberFixedAtRoot_ = numberIterations_; // for statistics numberSolves_ = 0; phase_ = baseModel->phase_; assert (!nextRowCut_); nodeCompare_ = baseModel->nodeCompare_; tree_ = baseModel->tree_; assert (!subTreeModel_); //branchingMethod_ = NULL; // need something but what numberOldActiveCuts_ = baseModel->numberOldActiveCuts_; cutModifier_ = NULL; assert (!analyzeResults_); CbcThread * stuff = reinterpret_cast (masterThread_); assert (stuff); //if (stuff) stuff->setCreatedNode(NULL); // ?? searchStrategy_; searchStrategy_ = baseModel->searchStrategy_; stuff->saveStuff()[0] = searchStrategy_; stateOfSearch_ = baseModel->stateOfSearch_; stuff->saveStuff()[1] = stateOfSearch_; for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) { CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object_[iObject]) ; if (dynamicObject) { CbcSimpleIntegerDynamicPseudoCost * baseObject = dynamic_cast (baseModel->object_[iObject]) ; assert (baseObject); dynamicObject->copySome(baseObject); } } } else if (mode == 1) { lockThread(); CbcThread * stuff = reinterpret_cast (masterThread_); assert (stuff); //stateOfSearch_ if (stuff->saveStuff()[0] != searchStrategy_) { #ifdef COIN_DEVELOP printf("changing searchStrategy from %d to %d\n", baseModel->searchStrategy_, searchStrategy_); #endif baseModel->searchStrategy_ = searchStrategy_; } if (stuff->saveStuff()[1] != stateOfSearch_) { #ifdef COIN_DEVELOP printf("changing stateOfSearch from %d to %d\n", baseModel->stateOfSearch_, stateOfSearch_); #endif baseModel->stateOfSearch_ = stateOfSearch_; } if (numberUpdateItems_) { for (int i = 0; i < numberUpdateItems_; i++) { CbcObjectUpdateData * update = updateItems_ + i; int objectNumber = update->objectNumber_; CbcObject * object = dynamic_cast (baseModel->object_[objectNumber]); if (object) object->updateInformation(*update); } numberUpdateItems_ = 0; } if (eventHappened_) baseModel->eventHappened_ = true; baseModel->numberNodes_++; baseModel->numberIterations_ += numberIterations_ - numberFixedAtRoot_; baseModel->numberSolves_ += numberSolves_; if (stuff->node()) baseModel->tree_->push(stuff->node()); if (stuff->createdNode()) baseModel->tree_->push(stuff->createdNode()); unlockThread(); } else if (mode == 2) { baseModel->sumChangeObjective1_ += sumChangeObjective1_; baseModel->sumChangeObjective2_ += sumChangeObjective2_; //baseModel->numberIterations_ += numberIterations_; for (int iGenerator = 0; iGenerator < numberCutGenerators_; iGenerator++) { CbcCutGenerator * generator = baseModel->generator_[iGenerator]; CbcCutGenerator * generator2 = generator_[iGenerator]; generator->incrementNumberTimesEntered(generator2->numberTimesEntered()); generator->incrementNumberCutsInTotal(generator2->numberCutsInTotal()); generator->incrementNumberCutsActive(generator2->numberCutsActive()); generator->incrementTimeInCutGenerator(generator2->timeInCutGenerator()); } if (parallelMode() >= 0) nodeCompare_ = NULL; baseModel->maximumDepthActual_ = CoinMax(baseModel->maximumDepthActual_, maximumDepthActual_); baseModel->numberDJFixed_ += numberDJFixed_; baseModel->numberStrongIterations_ += numberStrongIterations_; int i; for (i = 0; i < 3; i++) baseModel->strongInfo_[i] += strongInfo_[i]; if (parallelMode() >= 0) { walkback_ = NULL; lastNodeInfo_ = NULL; lastNumberCuts_ = NULL; lastCut_ = NULL; //addedCuts_ = NULL; tree_ = NULL; } eventHandler_ = NULL; delete solverCharacteristics_; solverCharacteristics_ = NULL; bool newMethod = (baseModel->branchingMethod_ && baseModel->branchingMethod_->chooseMethod()); if (newMethod) { // new method - we were using base models numberObjects_ = 0; object_ = NULL; } } else if (mode == -1) { delete eventHandler_; eventHandler_ = baseModel->eventHandler_; assert (!statistics_); assert(baseModel->solverCharacteristics_); solverCharacteristics_ = new OsiBabSolver (*baseModel->solverCharacteristics_); solverCharacteristics_->setSolver(solver_); setMaximumNodes(COIN_INT_MAX); if (parallelMode() >= 0) { delete [] walkback_; //delete [] addedCuts_; walkback_ = NULL; //addedCuts_ = NULL; delete [] lastNodeInfo_ ; lastNodeInfo_ = NULL; delete [] lastNumberCuts_ ; lastNumberCuts_ = NULL; delete [] lastCut_ ; lastCut_ = NULL; delete tree_; tree_ = NULL; delete nodeCompare_; nodeCompare_ = NULL; } else { delete tree_; tree_ = new CbcTree(); tree_->setComparison(*nodeCompare_) ; } continuousSolver_ = baseModel->continuousSolver_->clone(); bool newMethod = (baseModel->branchingMethod_ && baseModel->branchingMethod_->chooseMethod()); if (newMethod) { // new method uses solver - but point to base model // We may update an object in wrong order - shouldn't matter? numberObjects_ = baseModel->numberObjects_; if (parallelMode() >= 0) { object_ = baseModel->object_; } else { printf("*****WARNING - fix testosi option\n"); object_ = baseModel->object_; } } int i; for (i = 0; i < numberHeuristics_; i++) { delete heuristic_[i]; heuristic_[i] = baseModel->heuristic_[i]->clone(); heuristic_[i]->setModelOnly(this); } for (i = 0; i < numberCutGenerators_; i++) { delete generator_[i]; generator_[i] = new CbcCutGenerator(*baseModel->generator_[i]); // refreshModel was overkill as thought too many rows generator_[i]->setModel(this); } } else if (mode == 10) { setCutoff(baseModel->getCutoff()); bestObjective_ = baseModel->bestObjective_; //assert (!baseModel->globalCuts_.sizeRowCuts()); numberSolutions_ = baseModel->numberSolutions_; assert (usedInSolution_); assert (baseModel->usedInSolution_); memcpy(usedInSolution_, baseModel->usedInSolution_, solver_->getNumCols()*sizeof(int)); stateOfSearch_ = baseModel->stateOfSearch_; //numberNodes_ = baseModel->numberNodes_; //numberIterations_ = baseModel->numberIterations_; //numberFixedAtRoot_ = numberIterations_; // for statistics phase_ = baseModel->phase_; assert (!nextRowCut_); delete nodeCompare_; nodeCompare_ = baseModel->nodeCompare_->clone(); tree_->setComparison(*nodeCompare_) ; assert (!subTreeModel_); //branchingMethod_ = NULL; // need something but what numberOldActiveCuts_ = baseModel->numberOldActiveCuts_; cutModifier_ = NULL; assert (!analyzeResults_); CbcThread * stuff = reinterpret_cast (masterThread_); assert (stuff); //if (stuff) stuff->setCreatedNode(NULL); // ?? searchStrategy_; searchStrategy_ = baseModel->searchStrategy_; stuff->saveStuff()[0] = searchStrategy_; stateOfSearch_ = baseModel->stateOfSearch_; stuff->saveStuff()[1] = stateOfSearch_; OsiObject ** baseObject = baseModel->object_; for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) { object_[iObject]->updateBefore(baseObject[iObject]); } //delete [] stuff->nodeCount; //stuff->nodeCount = new int [baseModel->maximumDepth_+1]; } else if (mode == 11) { if (parallelMode() < 0) { // from deterministic CbcThread * stuff = reinterpret_cast (masterThread_); assert (stuff); // Move solution etc // might as well mark all including continuous int numberColumns = solver_->getNumCols(); for (int i = 0; i < numberColumns; i++) { baseModel->usedInSolution_[i] += usedInSolution_[i]; //usedInSolution_[i]=0; } baseModel->numberSolutions_ += numberSolutions_; if (bestObjective_ < baseModel->bestObjective_ && bestObjective_ < baseModel->getCutoff()) { baseModel->bestObjective_ = bestObjective_ ; int numberColumns = solver_->getNumCols(); if (!baseModel->bestSolution_) baseModel->bestSolution_ = new double[numberColumns]; CoinCopyN(bestSolution_, numberColumns, baseModel->bestSolution_); baseModel->setCutoff(getCutoff()); } //stateOfSearch_ if (stuff->saveStuff()[0] != searchStrategy_) { #ifdef COIN_DEVELOP printf("changing searchStrategy from %d to %d\n", baseModel->searchStrategy_, searchStrategy_); #endif baseModel->searchStrategy_ = searchStrategy_; } if (stuff->saveStuff()[1] != stateOfSearch_) { #ifdef COIN_DEVELOP printf("changing stateOfSearch from %d to %d\n", baseModel->stateOfSearch_, stateOfSearch_); #endif baseModel->stateOfSearch_ = stateOfSearch_; } int i; if (eventHappened_) baseModel->eventHappened_ = true; baseModel->numberNodes_ += stuff->nodesThisTime(); baseModel->numberIterations_ += stuff->iterationsThisTime(); double cutoff = baseModel->getCutoff(); while (!tree_->empty()) { CbcNode * node = tree_->bestNode(COIN_DBL_MAX) ; if (node->objectiveValue() < cutoff) { assert(node->nodeInfo()); // Make node join correctly OsiBranchingObject * bobj = node->modifiableBranchingObject(); CbcBranchingObject * cbcobj = dynamic_cast (bobj); if (cbcobj) { CbcObject * object = cbcobj->object(); assert (object); int position = object->position(); assert (position >= 0); assert (object_[position] == object); CbcObject * objectNew = dynamic_cast (baseModel->object_[position]); cbcobj->setOriginalObject(objectNew); } baseModel->tree_->push(node); } else { delete node; } } for (i = 0; i < stuff->nDeleteNode(); i++) { //printf("CbcNode %x stuff delete\n",stuff->delNode[i]); delete stuff->delNode()[i]; } } } else { abort(); } } // Generate one round of cuts - parallel mode int CbcModel::parallelCuts(CbcBaseModel * master, OsiCuts & theseCuts, CbcNode * /*node*/, OsiCuts & slackCuts, int lastNumberCuts) { /* Is it time to scan the cuts in order to remove redundant cuts? If so, set up to do it. */ int fullScan = 0 ; if ((numberNodes_ % SCANCUTS) == 0 || (specialOptions_&256) != 0) { fullScan = 1 ; if (!numberNodes_ || (specialOptions_&256) != 0) fullScan = 2; specialOptions_ &= ~256; // mark as full scan done } // do cuts independently OsiCuts * eachCuts = new OsiCuts [numberCutGenerators_];; int i; assert (master); for (i = 0; i < numberThreads_; i++) { // set solver here after cloning master->model(i)->solver_ = solver_->clone(); master->model(i)->numberNodes_ = (fullScan) ? 1 : 0; } // generate cuts int status = 0; const OsiRowCutDebugger * debugger = NULL; bool onOptimalPath = false; for (i = 0; i < numberCutGenerators_; i++) { bool generate = generator_[i]->normal(); // skip if not optimal and should be (maybe a cut generator has fixed variables) if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable()) generate = false; if (generator_[i]->switchedOff()) generate = false;; if (generate) { master->waitForThreadsInCuts(0, eachCuts + i, i); } } // wait master->waitForThreadsInCuts(1, eachCuts, 0); // Now put together for (i = 0; i < numberCutGenerators_; i++) { // add column cuts int numberColumnCutsBefore = theseCuts.sizeColCuts() ; int numberColumnCuts = eachCuts[i].sizeColCuts(); int numberColumnCutsAfter = numberColumnCutsBefore + numberColumnCuts; int j; for (j = 0; j < numberColumnCuts; j++) { theseCuts.insert(eachCuts[i].colCut(j)); } int numberRowCutsBefore = theseCuts.sizeRowCuts() ; int numberRowCuts = eachCuts[i].sizeRowCuts(); // insert good cuts if (numberRowCuts) { int n = numberRowCuts; numberRowCuts = 0; for (j = 0; j < n; j++) { const OsiRowCut * thisCut = eachCuts[i].rowCutPtr(j) ; if (thisCut->lb() <= 1.0e10 && thisCut->ub() >= -1.0e10) { theseCuts.insert(eachCuts[i].rowCut(j)); numberRowCuts++; } } if (generator_[i]->mustCallAgain() && status >= 0) status = 1; // say must go round } int numberRowCutsAfter = numberRowCutsBefore + numberRowCuts; if (numberRowCuts) { // Check last cut to see if infeasible const OsiRowCut * thisCut = theseCuts.rowCutPtr(numberRowCutsAfter - 1) ; if (thisCut->lb() > thisCut->ub()) { status = -1; // sub-problem is infeasible break; } } #ifdef CBC_DEBUG { int k ; for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { OsiRowCut thisCut = theseCuts.rowCut(k) ; /* check size of elements. We can allow smaller but this helps debug generators as it is unsafe to have small elements */ int n = thisCut.row().getNumElements(); const int * column = thisCut.row().getIndices(); const double * element = thisCut.row().getElements(); //assert (n); for (int i = 0; i < n; i++) { double value = element[i]; assert(fabs(value) > 1.0e-12 && fabs(value) < 1.0e20); } } } #endif if ((specialOptions_&1) != 0) { if (onOptimalPath) { int k ; for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { OsiRowCut thisCut = theseCuts.rowCut(k) ; if (debugger->invalidCut(thisCut)) { solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); solver_->writeMpsNative("badCut.mps", NULL, NULL, 2); #ifdef NDEBUG printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n", i, generator_[i]->cutGeneratorName(), k - numberRowCutsBefore); const double *lower = getColLower() ; const double *upper = getColUpper() ; int numberColumns = solver_->getNumCols(); for (int i = 0; i < numberColumns; i++) printf("%d bounds %g,%g\n", i, lower[i], upper[i]); abort(); #endif } assert(!debugger->invalidCut(thisCut)) ; } } } /* The cut generator has done its thing, and maybe it generated some cuts. Do a bit of bookkeeping: load whichGenerator[i] with the index of the generator responsible for a cut, and place cuts flagged as global in the global cut pool for the model. lastNumberCuts is the sum of cuts added in previous iterations; it's the offset to the proper starting position in whichGenerator. */ int numberBefore = numberRowCutsBefore + numberColumnCutsBefore + lastNumberCuts ; int numberAfter = numberRowCutsAfter + numberColumnCutsAfter + lastNumberCuts ; // possibly extend whichGenerator resizeWhichGenerator(numberBefore, numberAfter); for (j = numberRowCutsBefore; j < numberRowCutsAfter; j++) { whichGenerator_[numberBefore++] = i ; const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ; if (thisCut->lb() > thisCut->ub()) status = -1; // sub-problem is infeasible if (thisCut->globallyValid()) { // add to global list OsiRowCut newCut(*thisCut); newCut.setGloballyValid(true); newCut.mutableRow().setTestForDuplicateIndex(false); globalCuts_.addCutIfNotDuplicate(newCut) ; } } for (j = numberColumnCutsBefore; j < numberColumnCutsAfter; j++) { //whichGenerator_[numberBefore++] = i ; const OsiColCut * thisCut = theseCuts.colCutPtr(j) ; if (thisCut->globallyValid()) { // add to global list makeGlobalCut(thisCut); } } } // Add in any violated saved cuts if (!theseCuts.sizeRowCuts() && !theseCuts.sizeColCuts()) { int numberOld = theseCuts.sizeRowCuts() + lastNumberCuts; int numberCuts = slackCuts.sizeRowCuts() ; int i; // possibly extend whichGenerator resizeWhichGenerator(numberOld, numberOld + numberCuts); double primalTolerance; solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ; for ( i = 0; i < numberCuts; i++) { const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ; if (thisCut->violated(cbcColSolution_) > 100.0*primalTolerance) { if (messageHandler()->logLevel() > 2) printf("Old cut added - violation %g\n", thisCut->violated(cbcColSolution_)) ; whichGenerator_[numberOld++] = -1; theseCuts.insert(*thisCut) ; } } } delete [] eachCuts; return status; } /* Locks a thread if parallel so that stuff like cut pool can be updated and/or used. */ void CbcModel::lockThread() { if (masterThread_ && (threadMode_&1) == 0) masterThread_->lockThread(); } /* Unlocks a thread if parallel */ void CbcModel::unlockThread() { if (masterThread_ && (threadMode_&1) == 0) masterThread_->unlockThread(); } // Returns true if locked bool CbcModel::isLocked() const { if (masterThread_) { return (masterThread_->locked()); } else { return true; } } // Stop a child void CbcModel::setInfoInChild(int type, CbcThread * info) { if (type == -3) { // set up masterThread_ = info; } else if (type == -2) { numberThreads_ = 0; // signal to stop } else { // make sure message handler will be deleted defaultHandler_ = true; ownObjects_ = false; delete solverCharacteristics_; solverCharacteristics_ = NULL; if (type >= 0) { delete [] object_; // may be able to when all over to CbcThread for (int i = 0; i < numberCutGenerators_; i++) { delete generator_[i]; generator_[i] = NULL; //delete virginGenerator_[i]; //virginGenerator_[i]=NULL; } //generator_[0] = NULL; //delete [] generator_; //generator_ = NULL; numberCutGenerators_ = 0; } else { for (int i = 0; i < numberCutGenerators_; i++) { generator_[i] = NULL; } } object_ = NULL; } } /// Indicates whether Cbc library has been compiled with multithreading support bool CbcModel::haveMultiThreadSupport() { return true; } #else // Default constructor CbcBaseModel::CbcBaseModel() {} bool CbcModel::haveMultiThreadSupport() { return false; } #endif Cbc-2.8.12/src/CbcHeuristicRandRound.hpp0000644000076600007660000000300612131315050016423 0ustar coincoin/* $Id: CbcHeuristicRandRound.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicRandRound_H #define CbcHeuristicRandRound_H #include "CbcHeuristic.hpp" /** LocalSearch class */ class CbcHeuristicRandRound : public CbcHeuristic { public: // Default Constructor CbcHeuristicRandRound (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicRandRound (CbcModel & model); // Copy constructor CbcHeuristicRandRound ( const CbcHeuristicRandRound &); // Destructor ~CbcHeuristicRandRound (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicRandRound & operator=(const CbcHeuristicRandRound& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) needs comments */ virtual int solution(double & objectiveValue, double * newSolution); protected: }; #endif Cbc-2.8.12/src/CbcHeuristicDivePseudoCost.hpp0000644000076600007660000000402212131315050017426 0ustar coincoin/* $Id: CbcHeuristicDivePseudoCost.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicDivePseudoCost_H #define CbcHeuristicDivePseudoCost_H #include "CbcHeuristicDive.hpp" /** DivePseudoCost class */ class CbcHeuristicDivePseudoCost : public CbcHeuristicDive { public: // Default Constructor CbcHeuristicDivePseudoCost (); // Constructor with model - assumed before cuts CbcHeuristicDivePseudoCost (CbcModel & model); // Copy constructor CbcHeuristicDivePseudoCost ( const CbcHeuristicDivePseudoCost &); // Destructor ~CbcHeuristicDivePseudoCost (); /// Clone virtual CbcHeuristicDivePseudoCost * clone() const; /// Assignment operator CbcHeuristicDivePseudoCost & operator=(const CbcHeuristicDivePseudoCost& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Selects the next variable to branch on /** Returns true if all the fractional variables can be trivially rounded. Returns false, if there is at least one fractional variable that is not trivially roundable. In this case, the bestColumn returned will not be trivially roundable. */ virtual bool selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound); /** Initializes any data which is going to be used repeatedly in selectVariableToBranch */ virtual void initializeData() ; /// Fix other variables at bounds virtual int fixOtherVariables(OsiSolverInterface * solver, const double * solution, PseudoReducedCost * candidate, const double * random); }; #endif Cbc-2.8.12/src/CbcEventHandler.cpp0000644000076600007660000000571311510742604015241 0ustar coincoin/* $Id: CbcEventHandler.cpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Shamelessly adapted from ClpEventHandler. #include "CoinPragma.hpp" #include "CbcEventHandler.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CbcEventHandler::CbcEventHandler (CbcModel *model) : model_(model), dfltAction_(CbcEventHandler::noAction), eaMap_(0) { /* nothing more required */ } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- /* Here we need to clone the event/action map, if it exists */ CbcEventHandler::CbcEventHandler (const CbcEventHandler & rhs) : model_(rhs.model_), dfltAction_(rhs.dfltAction_), eaMap_(0) { if (rhs.eaMap_ != 0) { eaMap_ = new eaMapPair(*rhs.eaMap_) ; } } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcEventHandler& CbcEventHandler::operator=(const CbcEventHandler & rhs) { if (this != &rhs) { model_ = rhs.model_ ; dfltAction_ = rhs.dfltAction_ ; if (rhs.eaMap_ != 0) { eaMap_ = new eaMapPair(*rhs.eaMap_) ; } else { eaMap_ = 0 ; } } return (*this) ; } //---------------------------------------------------------------- // Clone //------------------------------------------------------------------- CbcEventHandler* CbcEventHandler::clone() const { return (new CbcEventHandler(*this)) ; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- /* Take care to free the event/action map. */ CbcEventHandler::~CbcEventHandler () { if (eaMap_ != 0) delete eaMap_ ; } //------------------------------------------------------------------- // event() -- return the action for an event. //------------------------------------------------------------------- CbcEventHandler::CbcAction CbcEventHandler::event(CbcEvent event) /* If an event/action map exists and contains an entry for the event, return it. Otherwise return the default action. */ { if (eaMap_ != 0) { eaMapPair::iterator entry = eaMap_->find(event) ; if (entry != eaMap_->end()) { return (entry->second) ; } else { return (dfltAction_) ; } } else { return (dfltAction_) ; } } Cbc-2.8.12/src/OsiCbc/0000755000076600007660000000000012377555230012713 5ustar coincoinCbc-2.8.12/src/OsiCbc/OsiCbcSolverInterface.hpp0000644000076600007660000007211712131315050017570 0ustar coincoin// $Id: OsiCbcSolverInterface.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef OsiCbcSolverInterface_H #define OsiCbcSolverInterface_H #include #include #include #include "CbcModel.hpp" #include "CoinPackedMatrix.hpp" #include "OsiSolverInterface.hpp" #include "CbcStrategy.hpp" #include "CoinWarmStartBasis.hpp" class OsiRowCut; class OsiClpSolverInterface; static const double OsiCbcInfinity = COIN_DBL_MAX; //############################################################################# /** Cbc Solver Interface Instantiation of OsiCbcSolverInterface for the Model Algorithm. */ class OsiCbcSolverInterface : virtual public OsiSolverInterface { friend void OsiCbcSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir); public: //--------------------------------------------------------------------------- /**@name Solve methods */ //@{ /// Solve initial LP relaxation virtual void initialSolve(); /// Resolve an LP relaxation after problem modification virtual void resolve(); /// Invoke solver's built-in enumeration algorithm virtual void branchAndBound(); //@} //--------------------------------------------------------------------------- /**@name Parameter set/get methods The set methods return true if the parameter was set to the given value, false otherwise. There can be various reasons for failure: the given parameter is not applicable for the solver (e.g., refactorization frequency for the cbc algorithm), the parameter is not yet implemented for the solver or simply the value of the parameter is out of the range the solver accepts. If a parameter setting call returns false check the details of your solver. The get methods return true if the given parameter is applicable for the solver and is implemented. In this case the value of the parameter is returned in the second argument. Otherwise they return false. */ //@{ // Set an integer parameter bool setIntParam(OsiIntParam key, int value); // Set an double parameter bool setDblParam(OsiDblParam key, double value); // Set a string parameter bool setStrParam(OsiStrParam key, const std::string & value); // Get an integer parameter bool getIntParam(OsiIntParam key, int& value) const; // Get an double parameter bool getDblParam(OsiDblParam key, double& value) const; // Get a string parameter bool getStrParam(OsiStrParam key, std::string& value) const; // Set a hint parameter - overrides OsiSolverInterface virtual bool setHintParam(OsiHintParam key, bool yesNo=true, OsiHintStrength strength=OsiHintTry, void * otherInformation=NULL); /// Get a hint parameter virtual bool getHintParam(OsiHintParam key, bool& yesNo, OsiHintStrength& strength, void *& otherInformation) const; using OsiSolverInterface::getHintParam ; /// Get a hint parameter virtual bool getHintParam(OsiHintParam key, bool& yesNo, OsiHintStrength& strength) const; //@} //--------------------------------------------------------------------------- ///@name Methods returning info on how the solution process terminated //@{ /// Are there a numerical difficulties? virtual bool isAbandoned() const; /// Is optimality proven? virtual bool isProvenOptimal() const; /// Is primal infeasiblity proven? virtual bool isProvenPrimalInfeasible() const; /// Is dual infeasiblity proven? virtual bool isProvenDualInfeasible() const; /// Is the given primal objective limit reached? virtual bool isPrimalObjectiveLimitReached() const; /// Is the given dual objective limit reached? virtual bool isDualObjectiveLimitReached() const; /// Iteration limit reached? virtual bool isIterationLimitReached() const; //@} //--------------------------------------------------------------------------- /**@name WarmStart related methods */ //@{ /*! \brief Get an empty warm start object This routine returns an empty CoinWarmStartBasis object. Its purpose is to provide a way to give a client a warm start basis object of the appropriate type, which can resized and modified as desired. */ virtual CoinWarmStart *getEmptyWarmStart () const; /// Get warmstarting information virtual CoinWarmStart* getWarmStart() const; /** Set warmstarting information. Return true/false depending on whether the warmstart information was accepted or not. */ virtual bool setWarmStart(const CoinWarmStart* warmstart); //@} //--------------------------------------------------------------------------- /**@name Hotstart related methods (primarily used in strong branching).
The user can create a hotstart (a snapshot) of the optimization process then reoptimize over and over again always starting from there.
NOTE: between hotstarted optimizations only bound changes are allowed. */ //@{ /// Create a hotstart point of the optimization process virtual void markHotStart(); /// Optimize starting from the hotstart virtual void solveFromHotStart(); /// Delete the snapshot virtual void unmarkHotStart(); //@} //--------------------------------------------------------------------------- /**@name Problem information methods These methods call the solver's query routines to return information about the problem referred to by the current object. Querying a problem that has no data associated with it result in zeros for the number of rows and columns, and NULL pointers from the methods that return vectors. Const pointers returned from any data-query method are valid as long as the data is unchanged and the solver is not called. */ //@{ /**@name Methods related to querying the input data */ //@{ /// Get number of columns virtual int getNumCols() const; /// Get number of rows virtual int getNumRows() const; /// Get number of nonzero elements virtual int getNumElements() const ; /// Get pointer to array[getNumCols()] of column lower bounds virtual const double * getColLower() const; /// Get pointer to array[getNumCols()] of column upper bounds virtual const double * getColUpper() const; /** Get pointer to array[getNumRows()] of row constraint senses.
  • 'L' <= constraint
  • 'E' = constraint
  • 'G' >= constraint
  • 'R' ranged constraint
  • 'N' free constraint
*/ virtual const char * getRowSense() const; /** Get pointer to array[getNumRows()] of rows right-hand sides
  • if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i]
  • if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i]
  • if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i]
  • if rowsense()[i] == 'N' then rhs()[i] == 0.0
*/ virtual const double * getRightHandSide() const ; /** Get pointer to array[getNumRows()] of row ranges.
  • if rowsense()[i] == 'R' then rowrange()[i] == rowupper()[i] - rowlower()[i]
  • if rowsense()[i] != 'R' then rowrange()[i] is undefined
*/ virtual const double * getRowRange() const ; /// Get pointer to array[getNumRows()] of row lower bounds virtual const double * getRowLower() const ; /// Get pointer to array[getNumRows()] of row upper bounds virtual const double * getRowUpper() const ; /// Get pointer to array[getNumCols()] of objective function coefficients virtual const double * getObjCoefficients() const; /// Get objective function sense (1 for min (default), -1 for max) virtual double getObjSense() const ; /// Return true if column is continuous virtual bool isContinuous(int colNumber) const; /// Get pointer to row-wise copy of matrix virtual const CoinPackedMatrix * getMatrixByRow() const; /// Get pointer to column-wise copy of matrix virtual const CoinPackedMatrix * getMatrixByCol() const; /// Get solver's value for infinity virtual double getInfinity() const; //@} /**@name Methods related to querying the solution */ //@{ /// Get pointer to array[getNumCols()] of primal solution vector virtual const double * getColSolution() const; /// Get pointer to array[getNumRows()] of dual prices virtual const double * getRowPrice() const; /// Get a pointer to array[getNumCols()] of reduced costs virtual const double * getReducedCost() const; /** Get pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector */ virtual const double * getRowActivity() const; /// Get objective function value virtual double getObjValue() const; /** Get how many iterations it took to solve the problem (whatever "iteration" mean to the solver. */ virtual int getIterationCount() const ; /** Get as many dual rays as the solver can provide. (In case of proven primal infeasibility there should be at least one.) The first getNumRows() ray components will always be associated with the row duals (as returned by getRowPrice()). If \c fullRay is true, the final getNumCols() entries will correspond to the ray components associated with the nonbasic variables. If the full ray is requested and the method cannot provide it, it will throw an exception. NOTE for implementers of solver interfaces:
The double pointers in the vector should point to arrays of length getNumRows() and they should be allocated via new[].
NOTE for users of solver interfaces:
It is the user's responsibility to free the double pointers in the vector using delete[]. */ virtual std::vector getDualRays(int maxNumRays, bool fullRay = false) const; /** Get as many primal rays as the solver can provide. (In case of proven dual infeasibility there should be at least one.) NOTE for implementers of solver interfaces:
The double pointers in the vector should point to arrays of length getNumCols() and they should be allocated via new[].
NOTE for users of solver interfaces:
It is the user's responsibility to free the double pointers in the vector using delete[]. */ virtual std::vector getPrimalRays(int maxNumRays) const; //@} /*! \name Methods for row and column names. Because OsiCbc is a pass-through class, it's necessary to override any virtual method in order to be sure we catch an override by the underlying solver. See the OsiSolverInterface class documentation for detailed descriptions. */ //@{ /*! \brief Generate a standard name of the form Rnnnnnnn or Cnnnnnnn */ virtual std::string dfltRowColName(char rc, int ndx, unsigned digits = 7) const ; /*! \brief Return the name of the objective function */ virtual std::string getObjName (unsigned maxLen = std::string::npos) const ; /*! \brief Set the name of the objective function */ virtual void setObjName (std::string name) ; /*! \brief Return the name of the row. */ virtual std::string getRowName(int rowIndex, unsigned maxLen = std::string::npos) const ; /*! \brief Return a pointer to a vector of row names */ virtual const OsiNameVec &getRowNames() ; /*! \brief Set a row name */ virtual void setRowName(int ndx, std::string name) ; /*! \brief Set multiple row names */ virtual void setRowNames(OsiNameVec &srcNames, int srcStart, int len, int tgtStart) ; /*! \brief Delete len row names starting at index tgtStart */ virtual void deleteRowNames(int tgtStart, int len) ; /*! \brief Return the name of the column */ virtual std::string getColName(int colIndex, unsigned maxLen = std::string::npos) const ; /*! \brief Return a pointer to a vector of column names */ virtual const OsiNameVec &getColNames() ; /*! \brief Set a column name */ virtual void setColName(int ndx, std::string name) ; /*! \brief Set multiple column names */ virtual void setColNames(OsiNameVec &srcNames, int srcStart, int len, int tgtStart) ; /*! \brief Delete len column names starting at index tgtStart */ virtual void deleteColNames(int tgtStart, int len) ; //@} //@} //--------------------------------------------------------------------------- /**@name Problem modifying methods */ //@{ //------------------------------------------------------------------------- /**@name Changing bounds on variables and constraints */ //@{ /** Set an objective function coefficient */ virtual void setObjCoeff( int elementIndex, double elementValue ); using OsiSolverInterface::setColLower ; /** Set a single column lower bound
Use -DBL_MAX for -infinity. */ virtual void setColLower( int elementIndex, double elementValue ); using OsiSolverInterface::setColUpper ; /** Set a single column upper bound
Use DBL_MAX for infinity. */ virtual void setColUpper( int elementIndex, double elementValue ); /** Set a single column lower and upper bound */ virtual void setColBounds( int elementIndex, double lower, double upper ); /** Set the bounds on a number of columns simultaneously
The default implementation just invokes setColLower() and setColUpper() over and over again. @param indexFirst,indexLast pointers to the beginning and after the end of the array of the indices of the variables whose either bound changes @param boundList the new lower/upper bound pairs for the variables */ virtual void setColSetBounds(const int* indexFirst, const int* indexLast, const double* boundList); /** Set a single row lower bound
Use -DBL_MAX for -infinity. */ virtual void setRowLower( int elementIndex, double elementValue ); /** Set a single row upper bound
Use DBL_MAX for infinity. */ virtual void setRowUpper( int elementIndex, double elementValue ) ; /** Set a single row lower and upper bound */ virtual void setRowBounds( int elementIndex, double lower, double upper ) ; /** Set the type of a single row
*/ virtual void setRowType(int index, char sense, double rightHandSide, double range); /** Set the bounds on a number of rows simultaneously
The default implementation just invokes setRowLower() and setRowUpper() over and over again. @param indexFirst,indexLast pointers to the beginning and after the end of the array of the indices of the constraints whose either bound changes @param boundList the new lower/upper bound pairs for the constraints */ virtual void setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList); /** Set the type of a number of rows simultaneously
The default implementation just invokes setRowType() over and over again. @param indexFirst,indexLast pointers to the beginning and after the end of the array of the indices of the constraints whose any characteristics changes @param senseList the new senses @param rhsList the new right hand sides @param rangeList the new ranges */ virtual void setRowSetTypes(const int* indexFirst, const int* indexLast, const char* senseList, const double* rhsList, const double* rangeList); //@} //------------------------------------------------------------------------- /**@name Integrality related changing methods */ //@{ /** Set the index-th variable to be a continuous variable */ virtual void setContinuous(int index); /** Set the index-th variable to be an integer variable */ virtual void setInteger(int index); /** Set the variables listed in indices (which is of length len) to be continuous variables */ virtual void setContinuous(const int* indices, int len); /** Set the variables listed in indices (which is of length len) to be integer variables */ virtual void setInteger(const int* indices, int len); //@} //------------------------------------------------------------------------- /// Set objective function sense (1 for min (default), -1 for max,) virtual void setObjSense(double s ); /** Set the primal solution column values colsol[numcols()] is an array of values of the problem column variables. These values are copied to memory owned by the solver object or the solver. They will be returned as the result of colsol() until changed by another call to setColsol() or by a call to any solver routine. Whether the solver makes use of the solution in any way is solver-dependent. */ virtual void setColSolution(const double * colsol); /** Set dual solution vector rowprice[numrows()] is an array of values of the problem row dual variables. These values are copied to memory owned by the solver object or the solver. They will be returned as the result of rowprice() until changed by another call to setRowprice() or by a call to any solver routine. Whether the solver makes use of the solution in any way is solver-dependent. */ virtual void setRowPrice(const double * rowprice); //------------------------------------------------------------------------- /**@name Methods to expand a problem.
Note that if a column is added then by default it will correspond to a continuous variable. */ //@{ using OsiSolverInterface::addCol ; /** */ virtual void addCol(const CoinPackedVectorBase& vec, const double collb, const double colub, const double obj); /** Add a column (primal variable) to the problem. */ virtual void addCol(int numberElements, const int * rows, const double * elements, const double collb, const double colub, const double obj) ; using OsiSolverInterface::addCols ; /** */ virtual void addCols(const int numcols, const CoinPackedVectorBase * const * cols, const double* collb, const double* colub, const double* obj); /** */ virtual void deleteCols(const int num, const int * colIndices); using OsiSolverInterface::addRow ; /** */ virtual void addRow(const CoinPackedVectorBase& vec, const double rowlb, const double rowub); /** */ virtual void addRow(const CoinPackedVectorBase& vec, const char rowsen, const double rowrhs, const double rowrng); using OsiSolverInterface::addRows ; /** */ virtual void addRows(const int numrows, const CoinPackedVectorBase * const * rows, const double* rowlb, const double* rowub); /** */ virtual void addRows(const int numrows, const CoinPackedVectorBase * const * rows, const char* rowsen, const double* rowrhs, const double* rowrng); /** */ virtual void deleteRows(const int num, const int * rowIndices); //----------------------------------------------------------------------- /** Apply a collection of row cuts which are all effective. applyCuts seems to do one at a time which seems inefficient. */ virtual void applyRowCuts(int numberCuts, const OsiRowCut * cuts); /** Apply a collection of row cuts which are all effective. applyCuts seems to do one at a time which seems inefficient. This uses array of pointers */ virtual void applyRowCuts(int numberCuts, const OsiRowCut ** cuts); //@} //@} //--------------------------------------------------------------------------- public: /**@name Methods to input a problem */ //@{ /** Load in an problem by copying the arguments (the constraints on the rows are given by lower and upper bounds). If a pointer is 0 then the following values are the default:
  • colub: all columns have upper bound infinity
  • collb: all columns have lower bound 0
  • rowub: all rows have upper bound infinity
  • rowlb: all rows have lower bound -infinity
  • obj: all variables have 0 objective coefficient
*/ virtual void loadProblem(const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub); /** Load in an problem by assuming ownership of the arguments (the constraints on the rows are given by lower and upper bounds). For default values see the previous method.
WARNING: The arguments passed to this method will be freed using the C++ delete and delete[] functions. */ virtual void assignProblem(CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, double*& rowlb, double*& rowub); /** Load in an problem by copying the arguments (the constraints on the rows are given by sense/rhs/range triplets). If a pointer is 0 then the following values are the default:
  • colub: all columns have upper bound infinity
  • collb: all columns have lower bound 0
  • obj: all variables have 0 objective coefficient
  • rowsen: all rows are >=
  • rowrhs: all right hand sides are 0
  • rowrng: 0 for the ranged rows
*/ virtual void loadProblem(const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const char* rowsen, const double* rowrhs, const double* rowrng); /** Load in an problem by assuming ownership of the arguments (the constraints on the rows are given by sense/rhs/range triplets). For default values see the previous method.
WARNING: The arguments passed to this method will be freed using the C++ delete and delete[] functions. */ virtual void assignProblem(CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, char*& rowsen, double*& rowrhs, double*& rowrng); /** Just like the other loadProblem() methods except that the matrix is given in a standard column major ordered format (without gaps). */ virtual void loadProblem(const int numcols, const int numrows, const CoinBigIndex * start, const int* index, const double* value, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub); /** Just like the other loadProblem() methods except that the matrix is given in a standard column major ordered format (without gaps). */ virtual void loadProblem(const int numcols, const int numrows, const CoinBigIndex * start, const int* index, const double* value, const double* collb, const double* colub, const double* obj, const char* rowsen, const double* rowrhs, const double* rowrng); using OsiSolverInterface::readMps ; /** Read an mps file from the given filename (defaults to Osi reader) - returns number of errors (see OsiMpsReader class) */ virtual int readMps(const char *filename, const char *extension = "mps") ; /** Write the problem into an mps file of the given filename. If objSense is non zero then -1.0 forces the code to write a maximization objective and +1.0 to write a minimization one. If 0.0 then solver can do what it wants */ virtual void writeMps(const char *filename, const char *extension = "mps", double objSense=0.0) const; /** Write the problem into an mps file of the given filename, names may be null. formatType is 0 - normal 1 - extra accuracy 2 - IEEE hex (later) Returns non-zero on I/O error */ virtual int writeMpsNative(const char *filename, const char ** rowNames, const char ** columnNames, int formatType=0,int numberAcross=2, double objSense=0.0) const ; //@} /**@name Message handling (extra for Cbc messages). Normally I presume you would want the same language. If not then you could use underlying model pointer */ //@{ /// Set language void newLanguage(CoinMessages::Language language); void setLanguage(CoinMessages::Language language) {newLanguage(language);} //@} //--------------------------------------------------------------------------- /**@name Cbc specific public interfaces */ //@{ /// Get pointer to Cbc model inline CbcModel * getModelPtr() const { return modelPtr_;} /// Get pointer to underlying solver inline OsiSolverInterface * getRealSolverPtr() const { return modelPtr_->solver();} /// Set cutoff bound on the objective function. inline void setCutoff(double value) { modelPtr_->setCutoff(value);} /// Get the cutoff bound on the objective function - always as minimize inline double getCutoff() const { return modelPtr_->getCutoff();} /// Set the CbcModel::CbcMaxNumNode maximum node limit inline void setMaximumNodes( int value) { modelPtr_->setMaximumNodes(value);} /// Get the CbcModel::CbcMaxNumNode maximum node limit inline int getMaximumNodes() const { return modelPtr_->getMaximumNodes();} /// Set the CbcModel::CbcMaxNumSol maximum number of solutions inline void setMaximumSolutions( int value) { modelPtr_->setMaximumSolutions(value);} /// Get the CbcModel::CbcMaxNumSol maximum number of solutions inline int getMaximumSolutions() const { return modelPtr_->getMaximumSolutions();} /// Set the CbcModel::CbcMaximumSeconds maximum number of seconds inline void setMaximumSeconds( double value) { modelPtr_->setMaximumSeconds(value);} /// Get the CbcModel::CbcMaximumSeconds maximum number of seconds inline double getMaximumSeconds() const { return modelPtr_->getMaximumSeconds();} /// Node limit reached? inline bool isNodeLimitReached() const { return modelPtr_->isNodeLimitReached();} /// Solution limit reached? inline bool isSolutionLimitReached() const { return modelPtr_->isSolutionLimitReached();} /// Get how many Nodes it took to solve the problem. inline int getNodeCount() const { return modelPtr_->getNodeCount();} /// Final status of problem - 0 finished, 1 stopped, 2 difficulties inline int status() const { return modelPtr_->status();} /** Pass in a message handler It is the client's responsibility to destroy a message handler installed by this routine; it will not be destroyed when the solver interface is destroyed. */ virtual void passInMessageHandler(CoinMessageHandler * handler); //@} //--------------------------------------------------------------------------- /**@name Constructors and destructors */ //@{ /// Default Constructor OsiCbcSolverInterface (OsiSolverInterface * solver=NULL, CbcStrategy * strategy=NULL); /// Clone virtual OsiSolverInterface * clone(bool copyData = true) const; /// Copy constructor OsiCbcSolverInterface (const OsiCbcSolverInterface &); #if 0 /// Borrow constructor - only delete one copy OsiCbcSolverInterface (CbcModel * rhs, bool reallyOwn=false); /// Releases so won't error void releaseCbc(); #endif /// Assignment operator OsiCbcSolverInterface & operator=(const OsiCbcSolverInterface& rhs); /// Destructor virtual ~OsiCbcSolverInterface (); //@} //--------------------------------------------------------------------------- protected: ///@name Protected methods //@{ /** Apply a row cut (append to constraint matrix). */ virtual void applyRowCut(const OsiRowCut& rc); /** Apply a column cut (adjust one or more bounds). */ virtual void applyColCut(const OsiColCut& cc); //@} /**@name Protected member data */ //@{ /// Cbc model represented by this class instance mutable CbcModel * modelPtr_; //@} }; // So unit test can find out if NDEBUG set bool OsiCbcHasNDEBUG(); //############################################################################# /** A function that tests the methods in the OsiCbcSolverInterface class. */ void OsiCbcSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir); #endif Cbc-2.8.12/src/OsiCbc/Makefile.am0000644000076600007660000000433512253440730014743 0ustar coincoin# Copyright (C) 2006 International Business Machines and others. # All Rights Reserved. # This file is distributed under the Eclipse Public License. ## $Id: Makefile.am 1992 2013-12-15 23:57:12Z tkr $ # Author: Andreas Waechter IBM 2006-04-13 AUTOMAKE_OPTIONS = foreign ######################################################################## # libOsiCbc # ######################################################################## # Name of the library compiled in this directory. lib_LTLIBRARIES = libOsiCbc.la # List all source files for this library, including headers libOsiCbc_la_SOURCES = OsiCbcSolverInterface.cpp OsiCbcSolverInterface.hpp # List all additionally required libraries if DEPENDENCY_LINKING libOsiCbc_la_LIBADD = $(CBCLIB_LIBS) ../libCbc.la endif # This is for libtool (on Windows) libOsiCbc_la_LDFLAGS = $(LT_LDFLAGS) # Here list all include flags, relative to this "srcdir" directory. This # "cygpath" stuff is necessary to compile with native compilers on Windows. AM_CPPFLAGS = -I`$(CYGPATH_W) $(srcdir)/..` $(COINDEPEND_CFLAGS) # Plus the appropriate include directories for the default solver. if OSICBC_DFLT_SOLVER_CLP AM_CPPFLAGS += ${CLP_CFLAGS} endif if OSICBC_DFLT_SOLVER_CPX AM_CPPFLAGS += ${CPX_CFLAGS} endif if OSICBC_DFLT_SOLVER_DYLP AM_CPPFLAGS += ${DYLP_CFLAGS} endif if OSICBC_DFLT_SOLVER_GLPK AM_CPPFLAGS += ${GLPK_CFLAGS} endif if OSICBC_DFLT_SOLVER_GRB AM_CPPFLAGS += ${GRB_CFLAGS} endif if OSICBC_DFLT_SOLVER_MSK AM_CPPFLAGS += ${MSK_CFLAGS} endif if OSICBC_DFLT_SOLVER_SYM AM_CPPFLAGS += ${SYM_CFLAGS} endif if OSICBC_DFLT_SOLVER_XPR AM_CPPFLAGS += ${XPR_CFLAGS} endif # This line is necessary to allow VPATH compilation DEFAULT_INCLUDES = -I. -I`$(CYGPATH_W) $(srcdir)` -I.. ######################################################################## # Headers that need to be installed # ######################################################################## # Here list all the header files that are required by a user of the library, # and that therefore should be installed in 'include/coin' includecoindir = $(includedir)/coin includecoin_HEADERS = OsiCbcSolverInterface.hpp Cbc-2.8.12/src/OsiCbc/Makefile.in0000644000076600007660000006512712253440730014762 0ustar coincoin# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Copyright (C) 2006 International Business Machines and others. # All Rights Reserved. # This file is distributed under the Eclipse Public License. # Author: Andreas Waechter IBM 2006-04-13 srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ # Plus the appropriate include directories for the default solver. @OSICBC_DFLT_SOLVER_CLP_TRUE@am__append_1 = ${CLP_CFLAGS} @OSICBC_DFLT_SOLVER_CPX_TRUE@am__append_2 = ${CPX_CFLAGS} @OSICBC_DFLT_SOLVER_DYLP_TRUE@am__append_3 = ${DYLP_CFLAGS} @OSICBC_DFLT_SOLVER_GLPK_TRUE@am__append_4 = ${GLPK_CFLAGS} @OSICBC_DFLT_SOLVER_GRB_TRUE@am__append_5 = ${GRB_CFLAGS} @OSICBC_DFLT_SOLVER_MSK_TRUE@am__append_6 = ${MSK_CFLAGS} @OSICBC_DFLT_SOLVER_SYM_TRUE@am__append_7 = ${SYM_CFLAGS} @OSICBC_DFLT_SOLVER_XPR_TRUE@am__append_8 = ${XPR_CFLAGS} subdir = src/OsiCbc DIST_COMMON = $(includecoin_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h \ $(top_builddir)/src/config_cbc.h CONFIG_CLEAN_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includecoindir)" libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = @DEPENDENCY_LINKING_TRUE@libOsiCbc_la_DEPENDENCIES = \ @DEPENDENCY_LINKING_TRUE@ $(am__DEPENDENCIES_1) ../libCbc.la am_libOsiCbc_la_OBJECTS = OsiCbcSolverInterface.lo libOsiCbc_la_OBJECTS = $(am_libOsiCbc_la_OBJECTS) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libOsiCbc_la_SOURCES) DIST_SOURCES = $(libOsiCbc_la_SOURCES) includecoinHEADERS_INSTALL = $(INSTALL_HEADER) HEADERS = $(includecoin_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ABSBUILDDIR = @ABSBUILDDIR@ ACLOCAL = @ACLOCAL@ ADD_CFLAGS = @ADD_CFLAGS@ ADD_CXXFLAGS = @ADD_CXXFLAGS@ ALWAYS_FALSE_FALSE = @ALWAYS_FALSE_FALSE@ ALWAYS_FALSE_TRUE = @ALWAYS_FALSE_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ ASL_CFLAGS = @ASL_CFLAGS@ ASL_CFLAGS_INSTALLED = @ASL_CFLAGS_INSTALLED@ ASL_DATA = @ASL_DATA@ ASL_DATA_INSTALLED = @ASL_DATA_INSTALLED@ ASL_DEPENDENCIES = @ASL_DEPENDENCIES@ ASL_LIBS = @ASL_LIBS@ ASL_LIBS_INSTALLED = @ASL_LIBS_INSTALLED@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUX_DIR = @AUX_DIR@ AWK = @AWK@ BUILDTOOLSDIR = @BUILDTOOLSDIR@ CBCGENERIC_CFLAGS = @CBCGENERIC_CFLAGS@ CBCGENERIC_CFLAGS_INSTALLED = @CBCGENERIC_CFLAGS_INSTALLED@ CBCGENERIC_DEPENDENCIES = @CBCGENERIC_DEPENDENCIES@ CBCGENERIC_LIBS = @CBCGENERIC_LIBS@ CBCGENERIC_LIBS_INSTALLED = @CBCGENERIC_LIBS_INSTALLED@ CBCGENERIC_PCLIBS = @CBCGENERIC_PCLIBS@ CBCGENERIC_PCREQUIRES = @CBCGENERIC_PCREQUIRES@ CBCLIB_CFLAGS = @CBCLIB_CFLAGS@ CBCLIB_CFLAGS_INSTALLED = @CBCLIB_CFLAGS_INSTALLED@ CBCLIB_DEPENDENCIES = @CBCLIB_DEPENDENCIES@ CBCLIB_LIBS = @CBCLIB_LIBS@ CBCLIB_LIBS_INSTALLED = @CBCLIB_LIBS_INSTALLED@ CBCLIB_PCLIBS = @CBCLIB_PCLIBS@ CBCLIB_PCREQUIRES = @CBCLIB_PCREQUIRES@ CBC_BUILD_CBC_GENERIC_FALSE = @CBC_BUILD_CBC_GENERIC_FALSE@ CBC_BUILD_CBC_GENERIC_TRUE = @CBC_BUILD_CBC_GENERIC_TRUE@ CBC_SVN_REV = @CBC_SVN_REV@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDEFS = @CDEFS@ CFLAGS = @CFLAGS@ CLP_CFLAGS = @CLP_CFLAGS@ CLP_CFLAGS_INSTALLED = @CLP_CFLAGS_INSTALLED@ CLP_DATA = @CLP_DATA@ CLP_DATA_INSTALLED = @CLP_DATA_INSTALLED@ CLP_DEPENDENCIES = @CLP_DEPENDENCIES@ CLP_LIBS = @CLP_LIBS@ CLP_LIBS_INSTALLED = @CLP_LIBS_INSTALLED@ COINDEPEND_CFLAGS = @COINDEPEND_CFLAGS@ COINDEPEND_CFLAGS_INSTALLED = @COINDEPEND_CFLAGS_INSTALLED@ COINDEPEND_DATA = @COINDEPEND_DATA@ COINDEPEND_DATA_INSTALLED = @COINDEPEND_DATA_INSTALLED@ COINDEPEND_DEPENDENCIES = @COINDEPEND_DEPENDENCIES@ COINDEPEND_LIBS = @COINDEPEND_LIBS@ COINDEPEND_LIBS_INSTALLED = @COINDEPEND_LIBS_INSTALLED@ COIN_CC_IS_CL_FALSE = @COIN_CC_IS_CL_FALSE@ COIN_CC_IS_CL_TRUE = @COIN_CC_IS_CL_TRUE@ COIN_CXX_IS_CL_FALSE = @COIN_CXX_IS_CL_FALSE@ COIN_CXX_IS_CL_TRUE = @COIN_CXX_IS_CL_TRUE@ COIN_HAS_ASL_FALSE = @COIN_HAS_ASL_FALSE@ COIN_HAS_ASL_TRUE = @COIN_HAS_ASL_TRUE@ COIN_HAS_CLP_FALSE = @COIN_HAS_CLP_FALSE@ COIN_HAS_CLP_TRUE = @COIN_HAS_CLP_TRUE@ COIN_HAS_COINDEPEND_FALSE = @COIN_HAS_COINDEPEND_FALSE@ COIN_HAS_COINDEPEND_TRUE = @COIN_HAS_COINDEPEND_TRUE@ COIN_HAS_CPX_FALSE = @COIN_HAS_CPX_FALSE@ COIN_HAS_CPX_TRUE = @COIN_HAS_CPX_TRUE@ COIN_HAS_DYLP_FALSE = @COIN_HAS_DYLP_FALSE@ COIN_HAS_DYLP_TRUE = @COIN_HAS_DYLP_TRUE@ COIN_HAS_GLPK_FALSE = @COIN_HAS_GLPK_FALSE@ COIN_HAS_GLPK_TRUE = @COIN_HAS_GLPK_TRUE@ COIN_HAS_GRB_FALSE = @COIN_HAS_GRB_FALSE@ COIN_HAS_GRB_TRUE = @COIN_HAS_GRB_TRUE@ COIN_HAS_MIPLIB3_FALSE = @COIN_HAS_MIPLIB3_FALSE@ COIN_HAS_MIPLIB3_TRUE = @COIN_HAS_MIPLIB3_TRUE@ COIN_HAS_MSK_FALSE = @COIN_HAS_MSK_FALSE@ COIN_HAS_MSK_TRUE = @COIN_HAS_MSK_TRUE@ COIN_HAS_NETLIB_FALSE = @COIN_HAS_NETLIB_FALSE@ COIN_HAS_NETLIB_TRUE = @COIN_HAS_NETLIB_TRUE@ COIN_HAS_OSITESTS_FALSE = @COIN_HAS_OSITESTS_FALSE@ COIN_HAS_OSITESTS_TRUE = @COIN_HAS_OSITESTS_TRUE@ COIN_HAS_PKGCONFIG_FALSE = @COIN_HAS_PKGCONFIG_FALSE@ COIN_HAS_PKGCONFIG_TRUE = @COIN_HAS_PKGCONFIG_TRUE@ COIN_HAS_SAMPLE_FALSE = @COIN_HAS_SAMPLE_FALSE@ COIN_HAS_SAMPLE_TRUE = @COIN_HAS_SAMPLE_TRUE@ COIN_HAS_SPX_FALSE = @COIN_HAS_SPX_FALSE@ COIN_HAS_SPX_TRUE = @COIN_HAS_SPX_TRUE@ COIN_HAS_VOL_FALSE = @COIN_HAS_VOL_FALSE@ COIN_HAS_VOL_TRUE = @COIN_HAS_VOL_TRUE@ COIN_HAS_XPR_FALSE = @COIN_HAS_XPR_FALSE@ COIN_HAS_XPR_TRUE = @COIN_HAS_XPR_TRUE@ COIN_PKG_CONFIG_PATH = @COIN_PKG_CONFIG_PATH@ COIN_PKG_CONFIG_PATH_UNINSTALLED = @COIN_PKG_CONFIG_PATH_UNINSTALLED@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPX_CFLAGS = @CPX_CFLAGS@ CPX_CFLAGS_INSTALLED = @CPX_CFLAGS_INSTALLED@ CPX_DATA = @CPX_DATA@ CPX_DATA_INSTALLED = @CPX_DATA_INSTALLED@ CPX_DEPENDENCIES = @CPX_DEPENDENCIES@ CPX_LIBS = @CPX_LIBS@ CPX_LIBS_INSTALLED = @CPX_LIBS_INSTALLED@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEFS = @CXXDEFS@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBG_CFLAGS = @DBG_CFLAGS@ DBG_CXXFLAGS = @DBG_CXXFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DEPENDENCY_LINKING_FALSE = @DEPENDENCY_LINKING_FALSE@ DEPENDENCY_LINKING_TRUE = @DEPENDENCY_LINKING_TRUE@ DYLP_CFLAGS = @DYLP_CFLAGS@ DYLP_CFLAGS_INSTALLED = @DYLP_CFLAGS_INSTALLED@ DYLP_DATA = @DYLP_DATA@ DYLP_DATA_INSTALLED = @DYLP_DATA_INSTALLED@ DYLP_DEPENDENCIES = @DYLP_DEPENDENCIES@ DYLP_LIBS = @DYLP_LIBS@ DYLP_LIBS_INSTALLED = @DYLP_LIBS_INSTALLED@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GLPK_CFLAGS = @GLPK_CFLAGS@ GLPK_CFLAGS_INSTALLED = @GLPK_CFLAGS_INSTALLED@ GLPK_DATA = @GLPK_DATA@ GLPK_DATA_INSTALLED = @GLPK_DATA_INSTALLED@ GLPK_DEPENDENCIES = @GLPK_DEPENDENCIES@ GLPK_LIBS = @GLPK_LIBS@ GLPK_LIBS_INSTALLED = @GLPK_LIBS_INSTALLED@ GRB_CFLAGS = @GRB_CFLAGS@ GRB_CFLAGS_INSTALLED = @GRB_CFLAGS_INSTALLED@ GRB_DATA = @GRB_DATA@ GRB_DATA_INSTALLED = @GRB_DATA_INSTALLED@ GRB_DEPENDENCIES = @GRB_DEPENDENCIES@ GRB_LIBS = @GRB_LIBS@ GRB_LIBS_INSTALLED = @GRB_LIBS_INSTALLED@ HAVE_EXTERNALS_FALSE = @HAVE_EXTERNALS_FALSE@ HAVE_EXTERNALS_TRUE = @HAVE_EXTERNALS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBEXT = @LIBEXT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOLM4 = @LIBTOOLM4@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_LDFLAGS = @LT_LDFLAGS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MIPLIB3_CFLAGS = @MIPLIB3_CFLAGS@ MIPLIB3_CFLAGS_INSTALLED = @MIPLIB3_CFLAGS_INSTALLED@ MIPLIB3_DATA = @MIPLIB3_DATA@ MIPLIB3_DATA_INSTALLED = @MIPLIB3_DATA_INSTALLED@ MIPLIB3_DEPENDENCIES = @MIPLIB3_DEPENDENCIES@ MIPLIB3_LIBS = @MIPLIB3_LIBS@ MIPLIB3_LIBS_INSTALLED = @MIPLIB3_LIBS_INSTALLED@ MPICC = @MPICC@ MPICXX = @MPICXX@ MSK_CFLAGS = @MSK_CFLAGS@ MSK_CFLAGS_INSTALLED = @MSK_CFLAGS_INSTALLED@ MSK_DATA = @MSK_DATA@ MSK_DATA_INSTALLED = @MSK_DATA_INSTALLED@ MSK_DEPENDENCIES = @MSK_DEPENDENCIES@ MSK_LIBS = @MSK_LIBS@ MSK_LIBS_INSTALLED = @MSK_LIBS_INSTALLED@ NETLIB_CFLAGS = @NETLIB_CFLAGS@ NETLIB_CFLAGS_INSTALLED = @NETLIB_CFLAGS_INSTALLED@ NETLIB_DATA = @NETLIB_DATA@ NETLIB_DATA_INSTALLED = @NETLIB_DATA_INSTALLED@ NETLIB_DEPENDENCIES = @NETLIB_DEPENDENCIES@ NETLIB_LIBS = @NETLIB_LIBS@ NETLIB_LIBS_INSTALLED = @NETLIB_LIBS_INSTALLED@ OBJEXT = @OBJEXT@ OPT_CFLAGS = @OPT_CFLAGS@ OPT_CXXFLAGS = @OPT_CXXFLAGS@ OSICBC_DFLT_SOLVER_CLP_FALSE = @OSICBC_DFLT_SOLVER_CLP_FALSE@ OSICBC_DFLT_SOLVER_CLP_TRUE = @OSICBC_DFLT_SOLVER_CLP_TRUE@ OSICBC_DFLT_SOLVER_CPX_FALSE = @OSICBC_DFLT_SOLVER_CPX_FALSE@ OSICBC_DFLT_SOLVER_CPX_TRUE = @OSICBC_DFLT_SOLVER_CPX_TRUE@ OSICBC_DFLT_SOLVER_DYLP_FALSE = @OSICBC_DFLT_SOLVER_DYLP_FALSE@ OSICBC_DFLT_SOLVER_DYLP_TRUE = @OSICBC_DFLT_SOLVER_DYLP_TRUE@ OSICBC_DFLT_SOLVER_GLPK_FALSE = @OSICBC_DFLT_SOLVER_GLPK_FALSE@ OSICBC_DFLT_SOLVER_GLPK_TRUE = @OSICBC_DFLT_SOLVER_GLPK_TRUE@ OSICBC_DFLT_SOLVER_GRB_FALSE = @OSICBC_DFLT_SOLVER_GRB_FALSE@ OSICBC_DFLT_SOLVER_GRB_TRUE = @OSICBC_DFLT_SOLVER_GRB_TRUE@ OSICBC_DFLT_SOLVER_MSK_FALSE = @OSICBC_DFLT_SOLVER_MSK_FALSE@ OSICBC_DFLT_SOLVER_MSK_TRUE = @OSICBC_DFLT_SOLVER_MSK_TRUE@ OSICBC_DFLT_SOLVER_SPX_FALSE = @OSICBC_DFLT_SOLVER_SPX_FALSE@ OSICBC_DFLT_SOLVER_SPX_TRUE = @OSICBC_DFLT_SOLVER_SPX_TRUE@ OSICBC_DFLT_SOLVER_SYM_FALSE = @OSICBC_DFLT_SOLVER_SYM_FALSE@ OSICBC_DFLT_SOLVER_SYM_TRUE = @OSICBC_DFLT_SOLVER_SYM_TRUE@ OSICBC_DFLT_SOLVER_VOL_FALSE = @OSICBC_DFLT_SOLVER_VOL_FALSE@ OSICBC_DFLT_SOLVER_VOL_TRUE = @OSICBC_DFLT_SOLVER_VOL_TRUE@ OSICBC_DFLT_SOLVER_XPR_FALSE = @OSICBC_DFLT_SOLVER_XPR_FALSE@ OSICBC_DFLT_SOLVER_XPR_TRUE = @OSICBC_DFLT_SOLVER_XPR_TRUE@ OSITESTS_CFLAGS = @OSITESTS_CFLAGS@ OSITESTS_CFLAGS_INSTALLED = @OSITESTS_CFLAGS_INSTALLED@ OSITESTS_DATA = @OSITESTS_DATA@ OSITESTS_DATA_INSTALLED = @OSITESTS_DATA_INSTALLED@ OSITESTS_DEPENDENCIES = @OSITESTS_DEPENDENCIES@ OSITESTS_LIBS = @OSITESTS_LIBS@ OSITESTS_LIBS_INSTALLED = @OSITESTS_LIBS_INSTALLED@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ RPATH_FLAGS = @RPATH_FLAGS@ SAMPLE_CFLAGS = @SAMPLE_CFLAGS@ SAMPLE_CFLAGS_INSTALLED = @SAMPLE_CFLAGS_INSTALLED@ SAMPLE_DATA = @SAMPLE_DATA@ SAMPLE_DATA_INSTALLED = @SAMPLE_DATA_INSTALLED@ SAMPLE_DEPENDENCIES = @SAMPLE_DEPENDENCIES@ SAMPLE_LIBS = @SAMPLE_LIBS@ SAMPLE_LIBS_INSTALLED = @SAMPLE_LIBS_INSTALLED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPX_CFLAGS = @SPX_CFLAGS@ SPX_CFLAGS_INSTALLED = @SPX_CFLAGS_INSTALLED@ SPX_DATA = @SPX_DATA@ SPX_DATA_INSTALLED = @SPX_DATA_INSTALLED@ SPX_DEPENDENCIES = @SPX_DEPENDENCIES@ SPX_LIBS = @SPX_LIBS@ SPX_LIBS_INSTALLED = @SPX_LIBS_INSTALLED@ STRIP = @STRIP@ VERSION = @VERSION@ VOL_CFLAGS = @VOL_CFLAGS@ VOL_CFLAGS_INSTALLED = @VOL_CFLAGS_INSTALLED@ VOL_DATA = @VOL_DATA@ VOL_DATA_INSTALLED = @VOL_DATA_INSTALLED@ VOL_DEPENDENCIES = @VOL_DEPENDENCIES@ VOL_LIBS = @VOL_LIBS@ VOL_LIBS_INSTALLED = @VOL_LIBS_INSTALLED@ VPATH_DISTCLEANFILES = @VPATH_DISTCLEANFILES@ XPR_CFLAGS = @XPR_CFLAGS@ XPR_CFLAGS_INSTALLED = @XPR_CFLAGS_INSTALLED@ XPR_DATA = @XPR_DATA@ XPR_DATA_INSTALLED = @XPR_DATA_INSTALLED@ XPR_DEPENDENCIES = @XPR_DEPENDENCIES@ XPR_LIBS = @XPR_LIBS@ XPR_LIBS_INSTALLED = @XPR_LIBS_INSTALLED@ abs_bin_dir = @abs_bin_dir@ abs_include_dir = @abs_include_dir@ abs_lib_dir = @abs_lib_dir@ abs_source_dir = @abs_source_dir@ ac_c_preproc_warn_flag = @ac_c_preproc_warn_flag@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ ac_ct_PKG_CONFIG = @ac_ct_PKG_CONFIG@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_cxx_preproc_warn_flag = @ac_cxx_preproc_warn_flag@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ coin_doxy_excludes = @coin_doxy_excludes@ coin_doxy_logname = @coin_doxy_logname@ coin_doxy_tagfiles = @coin_doxy_tagfiles@ coin_doxy_tagname = @coin_doxy_tagname@ coin_doxy_usedot = @coin_doxy_usedot@ coin_have_doxygen = @coin_have_doxygen@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_autoconf = @have_autoconf@ have_automake = @have_automake@ have_svn = @have_svn@ have_svnversion = @have_svnversion@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sol_cc_compiler = @sol_cc_compiler@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AUTOMAKE_OPTIONS = foreign ######################################################################## # libOsiCbc # ######################################################################## # Name of the library compiled in this directory. lib_LTLIBRARIES = libOsiCbc.la # List all source files for this library, including headers libOsiCbc_la_SOURCES = OsiCbcSolverInterface.cpp OsiCbcSolverInterface.hpp # List all additionally required libraries @DEPENDENCY_LINKING_TRUE@libOsiCbc_la_LIBADD = $(CBCLIB_LIBS) ../libCbc.la # This is for libtool (on Windows) libOsiCbc_la_LDFLAGS = $(LT_LDFLAGS) # Here list all include flags, relative to this "srcdir" directory. This # "cygpath" stuff is necessary to compile with native compilers on Windows. AM_CPPFLAGS = -I`$(CYGPATH_W) $(srcdir)/..` $(COINDEPEND_CFLAGS) \ $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) \ $(am__append_7) $(am__append_8) # This line is necessary to allow VPATH compilation DEFAULT_INCLUDES = -I. -I`$(CYGPATH_W) $(srcdir)` -I.. ######################################################################## # Headers that need to be installed # ######################################################################## # Here list all the header files that are required by a user of the library, # and that therefore should be installed in 'include/coin' includecoindir = $(includedir)/coin includecoin_HEADERS = OsiCbcSolverInterface.hpp all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/OsiCbc/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/OsiCbc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ else :; fi; \ done uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libOsiCbc.la: $(libOsiCbc_la_OBJECTS) $(libOsiCbc_la_DEPENDENCIES) $(CXXLINK) -rpath $(libdir) $(libOsiCbc_la_LDFLAGS) $(libOsiCbc_la_OBJECTS) $(libOsiCbc_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OsiCbcSolverInterface.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: install-includecoinHEADERS: $(includecoin_HEADERS) @$(NORMAL_INSTALL) test -z "$(includecoindir)" || $(mkdir_p) "$(DESTDIR)$(includecoindir)" @list='$(includecoin_HEADERS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(includecoinHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includecoindir)/$$f'"; \ $(includecoinHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includecoindir)/$$f"; \ done uninstall-includecoinHEADERS: @$(NORMAL_UNINSTALL) @list='$(includecoin_HEADERS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(includecoindir)/$$f'"; \ rm -f "$(DESTDIR)$(includecoindir)/$$f"; \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includecoindir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-libtool distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-includecoinHEADERS install-exec-am: install-libLTLIBRARIES install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-includecoinHEADERS uninstall-info-am \ uninstall-libLTLIBRARIES .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-exec \ install-exec-am install-includecoinHEADERS install-info \ install-info-am install-libLTLIBRARIES install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags uninstall uninstall-am \ uninstall-includecoinHEADERS uninstall-info-am \ uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: Cbc-2.8.12/src/OsiCbc/OsiCbcSolverInterface.cpp0000644000076600007660000006612012131315050017560 0ustar coincoin// $Id: OsiCbcSolverInterface.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include "OsiConfig.h" #include "CoinTime.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" /* Default solver configuration: In any environment, clp is the default if you do nothing. The necessary definitions will be handled by the configure script (based on the value specified for --with-osicbc-default-solver) in any environment where configure is available. The results can be found in inc/config_osi.h, which is created during configuration from config_osi.h.in and placed in the build directory. In an environment which does not use configure (MS Visual Studio, for example) the preferred method is to edit the definitions in inc/OsiConfig.h. The symbols are left undefined by default because some older environments (e.g., MS Visual Studio v7 or earlier) will not accept an #include directive which uses a macro to specify the file. In such an environment, if you want to use a solver other than OsiClp, you'll need to make the changes here. */ #ifndef OSICBC_DFLT_SOLVER #define OSICBC_DFLT_SOLVER OsiClpSolverInterface #define OSICBC_CLP_DFLT_SOLVER #include "OsiClpSolverInterface.hpp" #else #include OSICBC_DFLT_SOLVER_HPP #endif #include "OsiCbcSolverInterface.hpp" #include "OsiCuts.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" #ifdef OSICBC_CLP_DFLT_SOLVER #include "ClpPresolve.hpp" #endif //############################################################################# // Solve methods //############################################################################# void OsiCbcSolverInterface::initialSolve() { modelPtr_->solver()->initialSolve(); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::resolve() { modelPtr_->solver()->resolve(); } //############################################################################# // Parameter related methods //############################################################################# bool OsiCbcSolverInterface::setIntParam(OsiIntParam key, int value) { return modelPtr_->solver()->setIntParam(key,value);; } //----------------------------------------------------------------------------- bool OsiCbcSolverInterface::setDblParam(OsiDblParam key, double value) { return modelPtr_->solver()->setDblParam(key,value); } //----------------------------------------------------------------------------- bool OsiCbcSolverInterface::setStrParam(OsiStrParam key, const std::string & value) { return modelPtr_->solver()->setStrParam(key,value); } //----------------------------------------------------------------------------- bool OsiCbcSolverInterface::getIntParam(OsiIntParam key, int& value) const { return modelPtr_->solver()->getIntParam(key,value); } //----------------------------------------------------------------------------- bool OsiCbcSolverInterface::getDblParam(OsiDblParam key, double& value) const { return modelPtr_->solver()->getDblParam(key,value); } //----------------------------------------------------------------------------- bool OsiCbcSolverInterface::getStrParam(OsiStrParam key, std::string & value) const { if ( key==OsiSolverName ) { std::string value2; modelPtr_->solver()->getStrParam(key,value2); value = "cbc"+value2; return true; } return modelPtr_->solver()->getStrParam(key,value); } //############################################################################# // Methods returning info on how the solution process terminated //############################################################################# bool OsiCbcSolverInterface::isAbandoned() const { return modelPtr_->solver()->isAbandoned(); } bool OsiCbcSolverInterface::isProvenOptimal() const { return modelPtr_->solver()->isProvenOptimal(); } bool OsiCbcSolverInterface::isProvenPrimalInfeasible() const { return modelPtr_->solver()->isProvenPrimalInfeasible(); } bool OsiCbcSolverInterface::isProvenDualInfeasible() const { return modelPtr_->solver()->isProvenDualInfeasible(); } bool OsiCbcSolverInterface::isPrimalObjectiveLimitReached() const { return modelPtr_->solver()->isPrimalObjectiveLimitReached(); } bool OsiCbcSolverInterface::isDualObjectiveLimitReached() const { return modelPtr_->solver()->isDualObjectiveLimitReached(); } bool OsiCbcSolverInterface::isIterationLimitReached() const { return modelPtr_->solver()->isIterationLimitReached(); } //############################################################################# // WarmStart related methods //############################################################################# CoinWarmStart *OsiCbcSolverInterface::getEmptyWarmStart () const { return modelPtr_->solver()->getEmptyWarmStart(); } CoinWarmStart* OsiCbcSolverInterface::getWarmStart() const { return modelPtr_->solver()->getWarmStart(); } //----------------------------------------------------------------------------- bool OsiCbcSolverInterface::setWarmStart(const CoinWarmStart* warmstart) { return modelPtr_->solver()->setWarmStart(warmstart); } //############################################################################# // Hotstart related methods (primarily used in strong branching) //############################################################################# void OsiCbcSolverInterface::markHotStart() { modelPtr_->solver()->markHotStart(); } void OsiCbcSolverInterface::solveFromHotStart() { modelPtr_->solver()->solveFromHotStart(); } void OsiCbcSolverInterface::unmarkHotStart() { modelPtr_->solver()->unmarkHotStart(); } //############################################################################# // Problem information methods (original data) //############################################################################# //------------------------------------------------------------------ const char * OsiCbcSolverInterface::getRowSense() const { return modelPtr_->solver()->getRowSense(); } //------------------------------------------------------------------ const double * OsiCbcSolverInterface::getRightHandSide() const { return modelPtr_->solver()->getRightHandSide(); } //------------------------------------------------------------------ const double * OsiCbcSolverInterface::getRowRange() const { return modelPtr_->solver()->getRowRange(); } //------------------------------------------------------------------ // Return information on integrality //------------------------------------------------------------------ bool OsiCbcSolverInterface::isContinuous(int colNumber) const { return modelPtr_->solver()->isContinuous(colNumber); } //------------------------------------------------------------------ //------------------------------------------------------------------ // Row and column copies of the matrix ... //------------------------------------------------------------------ const CoinPackedMatrix * OsiCbcSolverInterface::getMatrixByRow() const { return modelPtr_->solver()->getMatrixByRow(); } const CoinPackedMatrix * OsiCbcSolverInterface::getMatrixByCol() const { return modelPtr_->solver()->getMatrixByCol(); } //------------------------------------------------------------------ std::vector OsiCbcSolverInterface::getDualRays(int maxNumRays, bool fullRay) const { return modelPtr_->solver()->getDualRays(maxNumRays,fullRay); } //------------------------------------------------------------------ std::vector OsiCbcSolverInterface::getPrimalRays(int maxNumRays) const { return modelPtr_->solver()->getPrimalRays(maxNumRays); } //############################################################################# void OsiCbcSolverInterface::setContinuous(int index) { modelPtr_->solver()->setContinuous(index); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::setInteger(int index) { modelPtr_->solver()->setInteger(index); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::setContinuous(const int* indices, int len) { modelPtr_->solver()->setContinuous(indices,len); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::setInteger(const int* indices, int len) { modelPtr_->solver()->setInteger(indices,len); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::setColSolution(const double * cs) { modelPtr_->solver()->setColSolution(cs); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::setRowPrice(const double * rs) { modelPtr_->solver()->setRowPrice(rs); } //############################################################################# // Problem modifying methods (matrix) //############################################################################# void OsiCbcSolverInterface::addCol(const CoinPackedVectorBase& vec, const double collb, const double colub, const double obj) { modelPtr_->solver()->addCol(vec,collb,colub,obj); } /* Add a column (primal variable) to the problem. */ void OsiCbcSolverInterface::addCol(int numberElements, const int * rows, const double * elements, const double collb, const double colub, const double obj) { modelPtr_->solver()->addCol(numberElements, rows, elements, collb,colub,obj); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::addCols(const int numcols, const CoinPackedVectorBase * const * cols, const double* collb, const double* colub, const double* obj) { modelPtr_->solver()->addCols(numcols,cols,collb,colub,obj); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::deleteCols(const int num, const int * columnIndices) { modelPtr_->solver()->deleteCols(num,columnIndices); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::addRow(const CoinPackedVectorBase& vec, const double rowlb, const double rowub) { modelPtr_->solver()->addRow(vec,rowlb,rowub); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::addRow(const CoinPackedVectorBase& vec, const char rowsen, const double rowrhs, const double rowrng) { modelPtr_->solver()->addRow(vec,rowsen,rowrhs,rowrng); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::addRows(const int numrows, const CoinPackedVectorBase * const * rows, const double* rowlb, const double* rowub) { modelPtr_->solver()->addRows(numrows,rows,rowlb,rowub); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::addRows(const int numrows, const CoinPackedVectorBase * const * rows, const char* rowsen, const double* rowrhs, const double* rowrng) { modelPtr_->solver()->addRows(numrows,rows,rowsen,rowrhs,rowrng); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::deleteRows(const int num, const int * rowIndices) { modelPtr_->solver()->deleteRows(num,rowIndices); } //############################################################################# // Methods to input a problem //############################################################################# void OsiCbcSolverInterface::loadProblem(const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub) { modelPtr_->solver()->loadProblem(matrix,collb,colub,obj,rowlb,rowub); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::assignProblem(CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, double*& rowlb, double*& rowub) { modelPtr_->solver()->assignProblem(matrix,collb,colub,obj,rowlb,rowub); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::loadProblem(const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const char* rowsen, const double* rowrhs, const double* rowrng) { modelPtr_->solver()->loadProblem(matrix,collb,colub,obj,rowsen,rowrhs,rowrng); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::assignProblem(CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, char*& rowsen, double*& rowrhs, double*& rowrng) { modelPtr_->solver()->assignProblem(matrix,collb,colub,obj,rowsen,rowrhs,rowrng); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::loadProblem(const int numcols, const int numrows, const CoinBigIndex * start, const int* index, const double* value, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub) { modelPtr_->solver()->loadProblem(numcols,numrows,start,index,value, collb,colub,obj,rowlb,rowub); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::loadProblem(const int numcols, const int numrows, const CoinBigIndex * start, const int* index, const double* value, const double* collb, const double* colub, const double* obj, const char* rowsen, const double* rowrhs, const double* rowrng) { modelPtr_->solver()->loadProblem(numcols,numrows,start,index,value, collb,colub,obj,rowsen,rowrhs,rowrng); } //----------------------------------------------------------------------------- // Write mps files //----------------------------------------------------------------------------- void OsiCbcSolverInterface::writeMps(const char * filename, const char * extension, double objSense) const { modelPtr_->solver()->writeMps(filename,extension,objSense); } int OsiCbcSolverInterface::writeMpsNative(const char *filename, const char ** rowNames, const char ** columnNames, int formatType,int numberAcross,double objSense) const { return modelPtr_->solver()->writeMpsNative(filename, rowNames, columnNames, formatType, numberAcross,objSense); } //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiCbcSolverInterface::OsiCbcSolverInterface (OsiSolverInterface * solver, CbcStrategy * strategy) : OsiSolverInterface() { if (solver) { modelPtr_=new CbcModel(*solver); } else { OSICBC_DFLT_SOLVER solverDflt; modelPtr_=new CbcModel(solverDflt); } if (strategy) { modelPtr_->setStrategy(*strategy); } else { CbcStrategyDefault defaultStrategy; modelPtr_->setStrategy(defaultStrategy); } } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * OsiCbcSolverInterface::clone(bool CopyData) const { if (CopyData) { return new OsiCbcSolverInterface(*this); } else { return new OsiCbcSolverInterface(); } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiCbcSolverInterface::OsiCbcSolverInterface ( const OsiCbcSolverInterface & rhs) : OsiSolverInterface(rhs) { assert (rhs.modelPtr_); modelPtr_ = new CbcModel(*rhs.modelPtr_); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiCbcSolverInterface::~OsiCbcSolverInterface () { delete modelPtr_; } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiCbcSolverInterface & OsiCbcSolverInterface::operator=(const OsiCbcSolverInterface& rhs) { if (this != &rhs) { OsiSolverInterface::operator=(rhs); delete modelPtr_; modelPtr_=new CbcModel(*rhs.modelPtr_); } return *this; } //############################################################################# // Applying cuts //############################################################################# void OsiCbcSolverInterface::applyRowCut( const OsiRowCut & rowCut ) { modelPtr_->solver()->applyRowCuts(1,&rowCut); } /* Apply a collection of row cuts which are all effective. applyCuts seems to do one at a time which seems inefficient. */ void OsiCbcSolverInterface::applyRowCuts(int numberCuts, const OsiRowCut * cuts) { modelPtr_->solver()->applyRowCuts(numberCuts,cuts); } /* Apply a collection of row cuts which are all effective. applyCuts seems to do one at a time which seems inefficient. */ void OsiCbcSolverInterface::applyRowCuts(int numberCuts, const OsiRowCut ** cuts) { modelPtr_->solver()->applyRowCuts(numberCuts, cuts); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::applyColCut( const OsiColCut & cc ) { const double * lower = modelPtr_->solver()->getColLower(); const double * upper = modelPtr_->solver()->getColUpper(); const CoinPackedVector & lbs = cc.lbs(); const CoinPackedVector & ubs = cc.ubs(); int i; for ( i=0; i lower[iCol] ) modelPtr_->solver()->setColLower(iCol, value); } for ( i=0; isolver()->setColUpper(iCol, value); } } /* Read an mps file from the given filename (defaults to Osi reader) - returns number of errors (see OsiMpsReader class) */ int OsiCbcSolverInterface::readMps(const char *filename, const char *extension ) { return modelPtr_->solver()->readMps(filename,extension); } // Get pointer to array[getNumCols()] of primal solution vector const double * OsiCbcSolverInterface::getColSolution() const { return modelPtr_->solver()->getColSolution(); } // Get pointer to array[getNumRows()] of dual prices const double * OsiCbcSolverInterface::getRowPrice() const { return modelPtr_->solver()->getRowPrice(); } // Get a pointer to array[getNumCols()] of reduced costs const double * OsiCbcSolverInterface::getReducedCost() const { return modelPtr_->solver()->getReducedCost(); } /* Get pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector */ const double * OsiCbcSolverInterface::getRowActivity() const { return modelPtr_->solver()->getRowActivity(); } double OsiCbcSolverInterface::getObjValue() const { return modelPtr_->solver()->getObjValue(); } /* Set an objective function coefficient */ void OsiCbcSolverInterface::setObjCoeff( int elementIndex, double elementValue ) { modelPtr_->solver()->setObjCoeff(elementIndex,elementValue); } /* Set a single column lower bound
Use -DBL_MAX for -infinity. */ void OsiCbcSolverInterface::setColLower( int elementIndex, double elementValue ) { modelPtr_->solver()->setColLower(elementIndex,elementValue); } /* Set a single column upper bound
Use DBL_MAX for infinity. */ void OsiCbcSolverInterface::setColUpper( int elementIndex, double elementValue ) { modelPtr_->solver()->setColUpper(elementIndex,elementValue); } /* Set a single column lower and upper bound */ void OsiCbcSolverInterface::setColBounds( int elementIndex, double lower, double upper ) { modelPtr_->solver()->setColBounds(elementIndex,lower,upper); } void OsiCbcSolverInterface::setColSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { modelPtr_->solver()->setColSetBounds(indexFirst,indexLast,boundList); } //------------------------------------------------------------------ /* Set a single row lower bound
Use -DBL_MAX for -infinity. */ void OsiCbcSolverInterface::setRowLower( int elementIndex, double elementValue ) { modelPtr_->solver()->setRowLower(elementIndex,elementValue); } /* Set a single row upper bound
Use DBL_MAX for infinity. */ void OsiCbcSolverInterface::setRowUpper( int elementIndex, double elementValue ) { modelPtr_->solver()->setRowUpper(elementIndex,elementValue); } /* Set a single row lower and upper bound */ void OsiCbcSolverInterface::setRowBounds( int elementIndex, double lower, double upper ) { modelPtr_->solver()->setRowBounds(elementIndex,lower,upper); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::setRowType(int i, char sense, double rightHandSide, double range) { modelPtr_->solver()->setRowType(i,sense,rightHandSide,range); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { modelPtr_->solver()->setRowSetBounds(indexFirst,indexLast,boundList); } //----------------------------------------------------------------------------- void OsiCbcSolverInterface::setRowSetTypes(const int* indexFirst, const int* indexLast, const char* senseList, const double* rhsList, const double* rangeList) { modelPtr_->solver()->setRowSetTypes(indexFirst,indexLast,senseList,rhsList,rangeList); } // Set a hint parameter bool OsiCbcSolverInterface::setHintParam(OsiHintParam key, bool yesNo, OsiHintStrength strength, void * otherInformation) { return modelPtr_->solver()->setHintParam(key,yesNo, strength, otherInformation); } // Get a hint parameter bool OsiCbcSolverInterface::getHintParam(OsiHintParam key, bool & yesNo, OsiHintStrength & strength, void *& otherInformation) const { return modelPtr_->solver()->getHintParam(key,yesNo, strength, otherInformation); } // Get a hint parameter bool OsiCbcSolverInterface::getHintParam(OsiHintParam key, bool & yesNo, OsiHintStrength & strength) const { return modelPtr_->solver()->getHintParam(key,yesNo, strength); } int OsiCbcSolverInterface::getNumCols() const { return modelPtr_->solver()->getNumCols(); } int OsiCbcSolverInterface::getNumRows() const { return modelPtr_->solver()->getNumRows(); } int OsiCbcSolverInterface::getNumElements() const { return modelPtr_->solver()->getNumElements(); } const double * OsiCbcSolverInterface::getColLower() const { return modelPtr_->solver()->getColLower(); } const double * OsiCbcSolverInterface::getColUpper() const { return modelPtr_->solver()->getColUpper(); } const double * OsiCbcSolverInterface::getRowLower() const { return modelPtr_->solver()->getRowLower(); } const double * OsiCbcSolverInterface::getRowUpper() const { return modelPtr_->solver()->getRowUpper(); } const double * OsiCbcSolverInterface::getObjCoefficients() const { return modelPtr_->solver()->getObjCoefficients(); } double OsiCbcSolverInterface::getObjSense() const { return modelPtr_->solver()->getObjSense(); } double OsiCbcSolverInterface::getInfinity() const { return modelPtr_->solver()->getInfinity(); } int OsiCbcSolverInterface::getIterationCount() const { return modelPtr_->solver()->getIterationCount(); } void OsiCbcSolverInterface::setObjSense(double s ) { modelPtr_->setObjSense(s); } // Invoke solver's built-in enumeration algorithm void OsiCbcSolverInterface::branchAndBound() { *messageHandler() << "Warning: Use of OsiCbc is deprecated." << CoinMessageEol; *messageHandler() << "To enjoy the full performance of Cbc, use the CbcSolver interface." << CoinMessageEol; modelPtr_->branchAndBound(); } /* Name discipline support -- lh, 070328 -- For safety, there's really nothing to it but to pass each call of an impure virtual method on to the underlying solver. Otherwise we just can't know if it's been overridden or not. */ std::string OsiCbcSolverInterface::dfltRowColName (char rc, int ndx, unsigned digits) const { return (modelPtr_->solver()->dfltRowColName(rc,ndx,digits)) ; } std::string OsiCbcSolverInterface::getObjName (unsigned maxLen) const { return (modelPtr_->solver()->getObjName(maxLen)) ; } std::string OsiCbcSolverInterface::getRowName (int ndx, unsigned maxLen) const { return (modelPtr_->solver()->getRowName(ndx,maxLen)) ; } const OsiSolverInterface::OsiNameVec &OsiCbcSolverInterface::getRowNames () { return (modelPtr_->solver()->getRowNames()) ; } std::string OsiCbcSolverInterface::getColName (int ndx, unsigned maxLen) const { return (modelPtr_->solver()->getColName(ndx,maxLen)) ; } const OsiSolverInterface::OsiNameVec &OsiCbcSolverInterface::getColNames () { return (modelPtr_->solver()->getColNames()) ; } void OsiCbcSolverInterface::setRowNames (OsiNameVec &srcNames, int srcStart, int len, int tgtStart) { modelPtr_->solver()->setRowNames(srcNames,srcStart,len,tgtStart) ; } void OsiCbcSolverInterface::deleteRowNames (int tgtStart, int len) { modelPtr_->solver()->deleteRowNames(tgtStart,len) ; } void OsiCbcSolverInterface::setColNames (OsiNameVec &srcNames, int srcStart, int len, int tgtStart) { modelPtr_->solver()->setColNames(srcNames,srcStart,len,tgtStart) ; } void OsiCbcSolverInterface::deleteColNames (int tgtStart, int len) { modelPtr_->solver()->deleteColNames(tgtStart,len) ; } /* These last three are the only functions that would normally be overridden. */ /* Set objective function name. */ void OsiCbcSolverInterface::setObjName (std::string name) { modelPtr_->solver()->setObjName(name) ; } /* Set a row name, to make sure both the solver and OSI see the same name. */ void OsiCbcSolverInterface::setRowName (int ndx, std::string name) { modelPtr_->solver()->setRowName(ndx,name) ; } /* Set a column name, to make sure both the solver and OSI see the same name. */ void OsiCbcSolverInterface::setColName (int ndx, std::string name) { modelPtr_->solver()->setColName(ndx,name) ; } // Pass in Message handler (not deleted at end) void OsiCbcSolverInterface::passInMessageHandler(CoinMessageHandler * handler) { OsiSolverInterface::passInMessageHandler(handler); if (modelPtr_) modelPtr_->passInMessageHandler(handler); } // So unit test can find out if NDEBUG set bool OsiCbcHasNDEBUG() { #ifdef NDEBUG return true; #else return false; #endif } Cbc-2.8.12/src/CbcSimpleInteger.cpp0000644000076600007660000005567712131315050015436 0ustar coincoin// $Id: CbcSimpleInteger.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/9/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcSimpleInteger.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" //############################################################################## /** Default Constructor Equivalent to an unspecified binary variable. */ CbcSimpleInteger::CbcSimpleInteger () : CbcObject(), originalLower_(0.0), originalUpper_(1.0), breakEven_(0.5), columnNumber_(-1), preferredWay_(0) { } /** Useful constructor Loads actual upper & lower bounds for the specified variable. */ CbcSimpleInteger::CbcSimpleInteger ( CbcModel * model, int iColumn, double breakEven) : CbcObject(model) { columnNumber_ = iColumn ; originalLower_ = model->solver()->getColLower()[columnNumber_] ; originalUpper_ = model->solver()->getColUpper()[columnNumber_] ; breakEven_ = breakEven; assert (breakEven_ > 0.0 && breakEven_ < 1.0); preferredWay_ = 0; } // Copy constructor CbcSimpleInteger::CbcSimpleInteger ( const CbcSimpleInteger & rhs) : CbcObject(rhs) { columnNumber_ = rhs.columnNumber_; originalLower_ = rhs.originalLower_; originalUpper_ = rhs.originalUpper_; breakEven_ = rhs.breakEven_; preferredWay_ = rhs.preferredWay_; } // Clone CbcObject * CbcSimpleInteger::clone() const { return new CbcSimpleInteger(*this); } // Assignment operator CbcSimpleInteger & CbcSimpleInteger::operator=( const CbcSimpleInteger & rhs) { if (this != &rhs) { CbcObject::operator=(rhs); columnNumber_ = rhs.columnNumber_; originalLower_ = rhs.originalLower_; originalUpper_ = rhs.originalUpper_; breakEven_ = rhs.breakEven_; preferredWay_ = rhs.preferredWay_; } return *this; } // Destructor CbcSimpleInteger::~CbcSimpleInteger () { } // Construct an OsiSimpleInteger object OsiSimpleInteger * CbcSimpleInteger::osiObject() const { OsiSimpleInteger * obj = new OsiSimpleInteger(columnNumber_, originalLower_, originalUpper_); obj->setPriority(priority()); return obj; } double CbcSimpleInteger::infeasibility(const OsiBranchingInformation * info, int &preferredWay) const { double value = info->solution_[columnNumber_]; value = CoinMax(value, info->lower_[columnNumber_]); value = CoinMin(value, info->upper_[columnNumber_]); double nearest = floor(value + (1.0 - breakEven_)); assert (breakEven_ > 0.0 && breakEven_ < 1.0); if (nearest > value) preferredWay = 1; else preferredWay = -1; if (preferredWay_) preferredWay = preferredWay_; double weight = fabs(value - nearest); // normalize so weight is 0.5 at break even if (nearest < value) weight = (0.5 / breakEven_) * weight; else weight = (0.5 / (1.0 - breakEven_)) * weight; if (fabs(value - nearest) <= info->integerTolerance_) return 0.0; else return weight; } double CbcSimpleInteger::feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const { double value = info->solution_[columnNumber_]; #ifdef COIN_DEVELOP if (fabs(value - floor(value + 0.5)) > 1.0e-5) printf("value for %d away from integer %g\n", columnNumber_, value); #endif double newValue = CoinMax(value, info->lower_[columnNumber_]); newValue = CoinMin(newValue, info->upper_[columnNumber_]); newValue = floor(newValue + 0.5); solver->setColLower(columnNumber_, newValue); solver->setColUpper(columnNumber_, newValue); return fabs(value - newValue); } /* Create an OsiSolverBranch object This returns NULL if branch not represented by bound changes */ OsiSolverBranch * CbcSimpleInteger::solverBranch(OsiSolverInterface * /*solver*/, const OsiBranchingInformation * info) const { double value = info->solution_[columnNumber_]; value = CoinMax(value, info->lower_[columnNumber_]); value = CoinMin(value, info->upper_[columnNumber_]); assert (info->upper_[columnNumber_] > info->lower_[columnNumber_]); #ifndef NDEBUG double nearest = floor(value + 0.5); assert (fabs(value - nearest) > info->integerTolerance_); #endif OsiSolverBranch * branch = new OsiSolverBranch(); branch->addBranch(columnNumber_, value); return branch; } // Creates a branching object CbcBranchingObject * CbcSimpleInteger::createCbcBranch(OsiSolverInterface * /*solver*/, const OsiBranchingInformation * info, int way) { CbcIntegerBranchingObject * branch = new CbcIntegerBranchingObject(model_, 0, -1, 0.5); fillCreateBranch(branch, info, way); return branch; } // Fills in a created branching object void CbcSimpleInteger::fillCreateBranch(CbcIntegerBranchingObject * branch, const OsiBranchingInformation * info, int way) { branch->setOriginalObject(this); double value = info->solution_[columnNumber_]; value = CoinMax(value, info->lower_[columnNumber_]); value = CoinMin(value, info->upper_[columnNumber_]); assert (info->upper_[columnNumber_] > info->lower_[columnNumber_]); if (!info->hotstartSolution_ && priority_ != -999) { #if 0 // out because of very strong branching ndef NDEBUG double nearest = floor(value + 0.5); assert (fabs(value - nearest) > info->integerTolerance_); #endif } else if (info->hotstartSolution_) { double targetValue = info->hotstartSolution_[columnNumber_]; if (way > 0) value = targetValue - 0.1; else value = targetValue + 0.1; } else { if (value <= info->lower_[columnNumber_]) value += 0.1; else if (value >= info->upper_[columnNumber_]) value -= 0.1; } assert (value >= info->lower_[columnNumber_] && value <= info->upper_[columnNumber_]); branch->fillPart(columnNumber_, way, value); } /* Column number if single column object -1 otherwise, so returns >= 0 Used by heuristics */ int CbcSimpleInteger::columnNumber() const { return columnNumber_; } /* Reset variable bounds to their original values. Bounds may be tightened, so it may be good to be able to set this info in object. */ void CbcSimpleInteger::resetBounds(const OsiSolverInterface * solver) { originalLower_ = solver->getColLower()[columnNumber_] ; originalUpper_ = solver->getColUpper()[columnNumber_] ; } /* Change column numbers after preprocessing */ void CbcSimpleInteger::resetSequenceEtc(int /*numberColumns*/, const int * originalColumns) { //assert (numberColumns>0); int iColumn; #ifdef JJF_ZERO for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnNumber_ == originalColumns[iColumn]) break; } assert (iColumn < numberColumns); #else iColumn = originalColumns[columnNumber_]; assert (iColumn >= 0); #endif columnNumber_ = iColumn; } // This looks at solution and sets bounds to contain solution /** More precisely: it first forces the variable within the existing bounds, and then tightens the bounds to fix the variable at the nearest integer value. */ void CbcSimpleInteger::feasibleRegion() { abort(); } //############################################################################## // Default Constructor CbcIntegerBranchingObject::CbcIntegerBranchingObject() : CbcBranchingObject() { down_[0] = 0.0; down_[1] = 0.0; up_[0] = 0.0; up_[1] = 0.0; #ifdef FUNNY_BRANCHING2 variables_ = NULL; newBounds_ = NULL; numberExtraChangedBounds_ = 0; #endif } // Useful constructor CbcIntegerBranchingObject::CbcIntegerBranchingObject (CbcModel * model, int variable, int way , double value) : CbcBranchingObject(model, variable, way, value) { int iColumn = variable; assert (model_->solver()->getNumCols() > 0); down_[0] = model_->solver()->getColLower()[iColumn]; down_[1] = floor(value_); up_[0] = ceil(value_); up_[1] = model->getColUpper()[iColumn]; #ifdef FUNNY_BRANCHING2 variables_ = NULL; newBounds_ = NULL; numberExtraChangedBounds_ = 0; #endif } // Does part of constructor void CbcIntegerBranchingObject::fillPart (int variable, int way , double value) { //originalObject_=NULL; branchIndex_ = 0; value_ = value; numberBranches_ = 2; //model_= model; //originalCbcObject_=NULL; variable_ = variable; way_ = way; int iColumn = variable; down_[0] = model_->solver()->getColLower()[iColumn]; down_[1] = floor(value_); up_[0] = ceil(value_); up_[1] = model_->getColUpper()[iColumn]; } // Useful constructor for fixing CbcIntegerBranchingObject::CbcIntegerBranchingObject (CbcModel * model, int variable, int way, double lowerValue, double upperValue) : CbcBranchingObject(model, variable, way, lowerValue) { setNumberBranchesLeft(1); down_[0] = lowerValue; down_[1] = upperValue; up_[0] = lowerValue; up_[1] = upperValue; #ifdef FUNNY_BRANCHING2 variables_ = NULL; newBounds_ = NULL; numberExtraChangedBounds_ = 0; #endif } // Copy constructor CbcIntegerBranchingObject::CbcIntegerBranchingObject ( const CbcIntegerBranchingObject & rhs) : CbcBranchingObject(rhs) { down_[0] = rhs.down_[0]; down_[1] = rhs.down_[1]; up_[0] = rhs.up_[0]; up_[1] = rhs.up_[1]; #ifdef FUNNY_BRANCHING2 numberExtraChangedBounds_ = rhs.numberExtraChangedBounds_; int size = numberExtraChangedBounds_ * (sizeof(double) + sizeof(int)); char * temp = new char [size]; newBounds_ = (double *) temp; variables_ = (int *) (newBounds_ + numberExtraChangedBounds_); int i ; for (i = 0; i < numberExtraChangedBounds_; i++) { variables_[i] = rhs.variables_[i]; newBounds_[i] = rhs.newBounds_[i]; } #endif } // Assignment operator CbcIntegerBranchingObject & CbcIntegerBranchingObject::operator=( const CbcIntegerBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); down_[0] = rhs.down_[0]; down_[1] = rhs.down_[1]; up_[0] = rhs.up_[0]; up_[1] = rhs.up_[1]; #ifdef FUNNY_BRANCHING2 delete [] newBounds_; numberExtraChangedBounds_ = rhs.numberExtraChangedBounds_; int size = numberExtraChangedBounds_ * (sizeof(double) + sizeof(int)); char * temp = new char [size]; newBounds_ = (double *) temp; variables_ = (int *) (newBounds_ + numberExtraChangedBounds_); int i ; for (i = 0; i < numberExtraChangedBounds_; i++) { variables_[i] = rhs.variables_[i]; newBounds_[i] = rhs.newBounds_[i]; } #endif } return *this; } CbcBranchingObject * CbcIntegerBranchingObject::clone() const { return (new CbcIntegerBranchingObject(*this)); } // Destructor CbcIntegerBranchingObject::~CbcIntegerBranchingObject () { // for debugging threads way_ = -23456789; #ifdef FUNNY_BRANCHING2 delete [] newBounds_; #endif } /* Perform a branch by adjusting the bounds of the specified variable. Note that each arm of the branch advances the object to the next arm by advancing the value of way_. Providing new values for the variable's lower and upper bounds for each branching direction gives a little bit of additional flexibility and will be easily extensible to multi-way branching. Returns change in guessed objective on next branch */ double CbcIntegerBranchingObject::branch() { // for debugging threads if (way_ < -1 || way_ > 100000) { printf("way %d, left %d, iCol %d, variable %d\n", way_, numberBranchesLeft(), originalCbcObject_->columnNumber(), variable_); assert (way_ != -23456789); } decrementNumberBranchesLeft(); if (down_[1] == -COIN_DBL_MAX) return 0.0; int iColumn = originalCbcObject_->columnNumber(); assert (variable_ == iColumn); double olb, oub ; olb = model_->solver()->getColLower()[iColumn] ; oub = model_->solver()->getColUpper()[iColumn] ; //#define CBCSIMPLE_TIGHTEN_BOUNDS #ifndef CBCSIMPLE_TIGHTEN_BOUNDS #ifdef COIN_DEVELOP if (olb != down_[0] || oub != up_[1]) { if (way_ > 0) printf("branching up on var %d: [%g,%g] => [%g,%g] - other [%g,%g]\n", iColumn, olb, oub, up_[0], up_[1], down_[0], down_[1]) ; else printf("branching down on var %d: [%g,%g] => [%g,%g] - other [%g,%g]\n", iColumn, olb, oub, down_[0], down_[1], up_[0], up_[1]) ; } #endif #endif if (way_ < 0) { #ifdef CBC_DEBUG { double olb, oub ; olb = model_->solver()->getColLower()[iColumn] ; oub = model_->solver()->getColUpper()[iColumn] ; printf("branching down on var %d: [%g,%g] => [%g,%g]\n", iColumn, olb, oub, down_[0], down_[1]) ; } #endif #ifndef CBCSIMPLE_TIGHTEN_BOUNDS model_->solver()->setColLower(iColumn, down_[0]); #else model_->solver()->setColLower(iColumn, CoinMax(down_[0], olb)); #endif model_->solver()->setColUpper(iColumn, down_[1]); //#define CBC_PRINT2 #ifdef CBC_PRINT2 printf("%d branching down has bounds %g %g", iColumn, down_[0], down_[1]); #endif #ifdef FUNNY_BRANCHING2 // branch - do extra bounds for (int i = 0; i < numberExtraChangedBounds_; i++) { int variable = variables_[i]; if ((variable&0x40000000) != 0) { // for going down int k = variable & 0x3fffffff; assert (k != iColumn); if ((variable&0x80000000) == 0) { // lower bound changing #ifdef CBC_PRINT2 printf(" extra for %d changes lower from %g to %g", k, model_->solver()->getColLower()[k], newBounds_[i]); #endif model_->solver()->setColLower(k, newBounds_[i]); } else { // upper bound changing #ifdef CBC_PRINT2 printf(" extra for %d changes upper from %g to %g", k, model_->solver()->getColUpper()[k], newBounds_[i]); #endif model_->solver()->setColUpper(k, newBounds_[i]); } } } #endif #ifdef CBC_PRINT2 printf("\n"); #endif way_ = 1; } else { #ifdef CBC_DEBUG { double olb, oub ; olb = model_->solver()->getColLower()[iColumn] ; oub = model_->solver()->getColUpper()[iColumn] ; printf("branching up on var %d: [%g,%g] => [%g,%g]\n", iColumn, olb, oub, up_[0], up_[1]) ; } #endif model_->solver()->setColLower(iColumn, up_[0]); #ifndef CBCSIMPLE_TIGHTEN_BOUNDS model_->solver()->setColUpper(iColumn, up_[1]); #else model_->solver()->setColUpper(iColumn, CoinMin(up_[1], oub)); #endif #ifdef CBC_PRINT2 printf("%d branching up has bounds %g %g", iColumn, up_[0], up_[1]); #endif #ifdef FUNNY_BRANCHING2 // branch - do extra bounds for (int i = 0; i < numberExtraChangedBounds_; i++) { int variable = variables_[i]; if ((variable&0x40000000) == 0) { // for going up int k = variable & 0x3fffffff; assert (k != iColumn); if ((variable&0x80000000) == 0) { // lower bound changing #ifdef CBC_PRINT2 printf(" extra for %d changes lower from %g to %g", k, model_->solver()->getColLower()[k], newBounds_[i]); #endif model_->solver()->setColLower(k, newBounds_[i]); } else { // upper bound changing #ifdef CBC_PRINT2 printf(" extra for %d changes upper from %g to %g", k, model_->solver()->getColUpper()[k], newBounds_[i]); #endif model_->solver()->setColUpper(k, newBounds_[i]); } } } #endif #ifdef CBC_PRINT2 printf("\n"); #endif way_ = -1; // Swap direction } double nlb = model_->solver()->getColLower()[iColumn]; double nub = model_->solver()->getColUpper()[iColumn]; if (nlb < olb) { #ifdef CBC_PRINT2 printf("bad lb change for column %d from %g to %g\n", iColumn, olb, nlb); #endif //abort(); model_->solver()->setColLower(iColumn, CoinMin(olb, nub)); nlb = olb; } if (nub > oub) { #ifdef CBC_PRINT2 printf("bad ub change for column %d from %g to %g\n", iColumn, oub, nub); #endif //abort(); model_->solver()->setColUpper(iColumn, CoinMax(oub, nlb)); } #ifdef CBC_PRINT2 if (nlb < olb + 1.0e-8 && nub > oub - 1.0e-8 && false) printf("bad null change for column %d - bounds %g,%g\n", iColumn, olb, oub); #endif return 0.0; } /* Update bounds in solver as in 'branch' and update given bounds. branchState is -1 for 'down' +1 for 'up' */ void CbcIntegerBranchingObject::fix(OsiSolverInterface * /*solver*/, double * lower, double * upper, int branchState) const { int iColumn = originalCbcObject_->columnNumber(); assert (variable_ == iColumn); if (branchState < 0) { model_->solver()->setColLower(iColumn, down_[0]); lower[iColumn] = down_[0]; model_->solver()->setColUpper(iColumn, down_[1]); upper[iColumn] = down_[1]; } else { model_->solver()->setColLower(iColumn, up_[0]); lower[iColumn] = up_[0]; model_->solver()->setColUpper(iColumn, up_[1]); upper[iColumn] = up_[1]; } } // Change (tighten) bounds in object to reflect bounds in solver. // Return true if now fixed bool CbcIntegerBranchingObject::tighten(OsiSolverInterface * solver) { double lower = solver->getColLower()[variable_]; double upper = solver->getColUpper()[variable_]; assert (upper>lower); down_[0] = CoinMax(down_[0],lower); up_[0] = CoinMax(up_[0],lower); down_[1] = CoinMin(down_[1],upper); up_[1] = CoinMin(up_[1],upper); return (down_[0]==up_[1]); } #ifdef FUNNY_BRANCHING2 // Deactivate bounds for branching void CbcIntegerBranchingObject::deactivate() { down_[1] = -COIN_DBL_MAX; } int CbcIntegerBranchingObject::applyExtraBounds(int iColumn, double lower, double upper, int way) { // branch - do bounds int i; int found = 0; if (variable_ == iColumn) { printf("odd applyExtra %d\n", iColumn); if (way < 0) { down_[0] = CoinMax(lower, down_[0]); down_[1] = CoinMin(upper, down_[1]); assert (down_[0] <= down_[1]); } else { up_[0] = CoinMax(lower, up_[0]); up_[1] = CoinMin(upper, up_[1]); assert (up_[0] <= up_[1]); } return 0; } int check = (way < 0) ? 0x40000000 : 0; double newLower = lower; double newUpper = upper; for (i = 0; i < numberExtraChangedBounds_; i++) { int variable = variables_[i]; if ((variable&0x40000000) == check) { int k = variable & 0x3fffffff; if (k == iColumn) { if ((variable&0x80000000) == 0) { // lower bound changing found |= 1; newBounds_[i] = CoinMax(lower, newBounds_[i]); newLower = newBounds_[i]; } else { // upper bound changing found |= 2; newBounds_[i] = CoinMin(upper, newBounds_[i]); newUpper = newBounds_[i]; } } } } int nAdd = 0; if ((found&2) == 0) { // need to add new upper nAdd++; } if ((found&1) == 0) { // need to add new lower nAdd++; } if (nAdd) { int size = (numberExtraChangedBounds_ + nAdd) * (sizeof(double) + sizeof(int)); char * temp = new char [size]; double * newBounds = (double *) temp; int * variables = (int *) (newBounds + numberExtraChangedBounds_ + nAdd); int i ; for (i = 0; i < numberExtraChangedBounds_; i++) { variables[i] = variables_[i]; newBounds[i] = newBounds_[i]; } delete [] newBounds_; newBounds_ = newBounds; variables_ = variables; if ((found&2) == 0) { // need to add new upper int variable = iColumn | 0x80000000; variables_[numberExtraChangedBounds_] = variable; newBounds_[numberExtraChangedBounds_++] = newUpper; } if ((found&1) == 0) { // need to add new lower int variable = iColumn; variables_[numberExtraChangedBounds_] = variable; newBounds_[numberExtraChangedBounds_++] = newLower; } } return (newUpper >= newLower) ? 0 : 1; } #endif // Print what would happen void CbcIntegerBranchingObject::print() { int iColumn = originalCbcObject_->columnNumber(); assert (variable_ == iColumn); if (way_ < 0) { { double olb, oub ; olb = model_->solver()->getColLower()[iColumn] ; oub = model_->solver()->getColUpper()[iColumn] ; printf("CbcInteger would branch down on var %d (int var %d): [%g,%g] => [%g,%g]\n", iColumn, variable_, olb, oub, down_[0], down_[1]) ; } } else { { double olb, oub ; olb = model_->solver()->getColLower()[iColumn] ; oub = model_->solver()->getColUpper()[iColumn] ; printf("CbcInteger would branch up on var %d (int var %d): [%g,%g] => [%g,%g]\n", iColumn, variable_, olb, oub, up_[0], up_[1]) ; } } } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcIntegerBranchingObject::compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap) { const CbcIntegerBranchingObject* br = dynamic_cast(brObj); assert(br); double* thisBd = way_ < 0 ? down_ : up_; const double* otherBd = br->way_ < 0 ? br->down_ : br->up_; return CbcCompareRanges(thisBd, otherBd, replaceIfOverlap); } Cbc-2.8.12/src/CbcBranchAllDifferent.hpp0000644000076600007660000000321312131315050016324 0ustar coincoin// $Id: CbcBranchAllDifferent.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/13/2009-- carved out of CbcBranchCut #ifndef CbcBranchAllDifferent_H #define CbcBranchAllDifferent_H #include "CbcBranchBase.hpp" #include "OsiRowCut.hpp" #include "CoinPackedMatrix.hpp" #include "CbcBranchCut.hpp" /** Define a branch class that branches so that it is only satsified if all members have different values So cut is x <= y-1 or x >= y+1 */ class CbcBranchAllDifferent : public CbcBranchCut { public: // Default Constructor CbcBranchAllDifferent (); /** Useful constructor - passed set of integer variables which must all be different */ CbcBranchAllDifferent (CbcModel * model, int number, const int * which); // Copy constructor CbcBranchAllDifferent ( const CbcBranchAllDifferent &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcBranchAllDifferent & operator=( const CbcBranchAllDifferent& rhs); // Destructor ~CbcBranchAllDifferent (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; protected: /// data /// Number of entries int numberInSet_; /// Which variables int * which_; }; #endif Cbc-2.8.12/src/CbcSOS.cpp0000644000076600007660000010736112371443325013334 0ustar coincoin// $Id: CbcSOS.cpp 2055 2014-08-09 16:05:41Z forrest $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/9/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcSOS.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" //############################################################################## // Default Constructor CbcSOS::CbcSOS () : CbcObject(), members_(NULL), weights_(NULL), shadowEstimateDown_(1.0), shadowEstimateUp_(1.0), downDynamicPseudoRatio_(0.0), upDynamicPseudoRatio_(0.0), numberTimesDown_(0), numberTimesUp_(0), numberMembers_(0), sosType_(-1), integerValued_(false) { } // Useful constructor (which are indices) CbcSOS::CbcSOS (CbcModel * model, int numberMembers, const int * which, const double * weights, int identifier, int type) : CbcObject(model), shadowEstimateDown_(1.0), shadowEstimateUp_(1.0), downDynamicPseudoRatio_(0.0), upDynamicPseudoRatio_(0.0), numberTimesDown_(0), numberTimesUp_(0), numberMembers_(numberMembers), sosType_(type) { id_ = identifier; integerValued_ = type == 1; if (integerValued_) { // check all members integer OsiSolverInterface * solver = model->solver(); if (solver) { for (int i = 0; i < numberMembers_; i++) { if (!solver->isInteger(which[i])) integerValued_ = false; } } else { // can't tell integerValued_ = false; } } if (numberMembers_) { members_ = new int[numberMembers_]; weights_ = new double[numberMembers_]; memcpy(members_, which, numberMembers_*sizeof(int)); if (weights) { memcpy(weights_, weights, numberMembers_*sizeof(double)); } else { for (int i = 0; i < numberMembers_; i++) weights_[i] = i; } // sort so weights increasing CoinSort_2(weights_, weights_ + numberMembers_, members_); /* Force all weights to be distinct; note that the separation enforced here (1.0e-10) is not sufficien to pass the test in infeasibility(). */ double last = -COIN_DBL_MAX; int i; for (i = 0; i < numberMembers_; i++) { double possible = CoinMax(last + 1.0e-10, weights_[i]); weights_[i] = possible; last = possible; } } else { members_ = NULL; weights_ = NULL; } assert (sosType_ > 0 && sosType_ < 3); } // Copy constructor CbcSOS::CbcSOS ( const CbcSOS & rhs) : CbcObject(rhs) { shadowEstimateDown_ = rhs.shadowEstimateDown_; shadowEstimateUp_ = rhs.shadowEstimateUp_; downDynamicPseudoRatio_ = rhs.downDynamicPseudoRatio_; upDynamicPseudoRatio_ = rhs.upDynamicPseudoRatio_; numberTimesDown_ = rhs.numberTimesDown_; numberTimesUp_ = rhs.numberTimesUp_; numberMembers_ = rhs.numberMembers_; sosType_ = rhs.sosType_; integerValued_ = rhs.integerValued_; if (numberMembers_) { members_ = new int[numberMembers_]; weights_ = new double[numberMembers_]; memcpy(members_, rhs.members_, numberMembers_*sizeof(int)); memcpy(weights_, rhs.weights_, numberMembers_*sizeof(double)); } else { members_ = NULL; weights_ = NULL; } } // Clone CbcObject * CbcSOS::clone() const { return new CbcSOS(*this); } // Assignment operator CbcSOS & CbcSOS::operator=( const CbcSOS & rhs) { if (this != &rhs) { CbcObject::operator=(rhs); delete [] members_; delete [] weights_; shadowEstimateDown_ = rhs.shadowEstimateDown_; shadowEstimateUp_ = rhs.shadowEstimateUp_; downDynamicPseudoRatio_ = rhs.downDynamicPseudoRatio_; upDynamicPseudoRatio_ = rhs.upDynamicPseudoRatio_; numberTimesDown_ = rhs.numberTimesDown_; numberTimesUp_ = rhs.numberTimesUp_; numberMembers_ = rhs.numberMembers_; sosType_ = rhs.sosType_; integerValued_ = rhs.integerValued_; if (numberMembers_) { members_ = new int[numberMembers_]; weights_ = new double[numberMembers_]; memcpy(members_, rhs.members_, numberMembers_*sizeof(int)); memcpy(weights_, rhs.weights_, numberMembers_*sizeof(double)); } else { members_ = NULL; weights_ = NULL; } } return *this; } // Destructor CbcSOS::~CbcSOS () { delete [] members_; delete [] weights_; } /* Routine to calculate standard infeasibility of an SOS set and return a preferred branching direction. This routine looks to have undergone incomplete revision. There is vestigial code. preferredWay is unconditionally set to 1. There used to be a comment `large is 0.5' but John removed it at some point. Have to check to see if it no longer applies or if John thought it provided too much information. */ double CbcSOS::infeasibility(const OsiBranchingInformation * info, int &preferredWay) const { int j; int firstNonZero = -1; int lastNonZero = -1; OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); //const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); //double largestValue=0.0; double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double weight = 0.0; double sum = 0.0; // check bounds etc double lastWeight = -1.0e100; for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; /* The value used here (1.0e-7) is larger than the value enforced in the constructor. */ if (lastWeight >= weights_[j] - 1.0e-7) throw CoinError("Weights too close together in SOS", "infeasibility", "CbcSOS"); double value = CoinMax(0.0, solution[iColumn]); sum += value; /* If we're not making assumptions about integrality, why check integerTolerance here? Convenient tolerance? Why not just check against the upper bound? The calculation of weight looks to be a relic --- in the end, the value isn't used to calculate either the return value or preferredWay. */ if (value > integerTolerance && upper[iColumn]) { // Possibly due to scaling a fixed variable might slip through if (value > upper[iColumn]) { value = upper[iColumn]; // Could change to #ifdef CBC_DEBUG #ifndef NDEBUG if (model_->messageHandler()->logLevel() > 2 && value > upper[iColumn] + integerTolerance) printf("** Variable %d (%d) has value %g and upper bound of %g\n", iColumn, j, value, upper[iColumn]); #endif } weight += weights_[j] * value; if (firstNonZero < 0) firstNonZero = j; lastNonZero = j; } } /* ?? */ preferredWay = 1; /* SOS1 allows one nonzero; SOS2 allows two consecutive nonzeros. Infeasibility is calculated as (.5)(range of nonzero values)/(number of members). So if the first and last elements of the set are nonzero, we have maximum infeasibility. */ if (lastNonZero - firstNonZero >= sosType_) { // find where to branch assert (sum > 0.0); weight /= sum; if (info->defaultDual_ >= 0.0 && info->usefulRegion_ && info->columnStart_) { assert (sosType_ == 1); int iWhere; for (iWhere = firstNonZero; iWhere < lastNonZero - 1; iWhere++) { if (weight < weights_[iWhere+1]) { break; } } int jColumnDown = members_[iWhere]; int jColumnUp = members_[iWhere+1]; int n = 0; CoinBigIndex j; double objMove = info->objective_[jColumnDown]; for (j = info->columnStart_[jColumnDown]; j < info->columnStart_[jColumnDown] + info->columnLength_[jColumnDown]; j++) { double value = info->elementByColumn_[j]; int iRow = info->row_[j]; info->indexRegion_[n++] = iRow; info->usefulRegion_[iRow] = value; } for (iWhere = firstNonZero; iWhere < lastNonZero; iWhere++) { int jColumn = members_[iWhere]; double solValue = info->solution_[jColumn]; if (!solValue) continue; objMove -= info->objective_[jColumn] * solValue; for (j = info->columnStart_[jColumn]; j < info->columnStart_[jColumn] + info->columnLength_[jColumn]; j++) { double value = -info->elementByColumn_[j] * solValue; int iRow = info->row_[j]; double oldValue = info->usefulRegion_[iRow]; if (!oldValue) { info->indexRegion_[n++] = iRow; } else { value += oldValue; if (!value) value = 1.0e-100; } info->usefulRegion_[iRow] = value; } } const double * pi = info->pi_; const double * activity = info->rowActivity_; const double * lower = info->rowLower_; const double * upper = info->rowUpper_; double tolerance = info->primalTolerance_; double direction = info->direction_; shadowEstimateDown_ = objMove * direction; bool infeasible = false; for (int k = 0; k < n; k++) { int iRow = info->indexRegion_[k]; double movement = info->usefulRegion_[iRow]; // not this time info->usefulRegion_[iRow]=0.0; #if 0 if (lower[iRow] < -1.0e20) { if (pi[iRow] > 1.0e-3) { printf("Bad pi on row %d of %g\n",iRow,pi[iRow]); } } if (upper[iRow] >1.0e20) { if (pi[iRow] < -1.0e-3) { printf("Bad pi on row %d of %g\n",iRow,pi[iRow]); } } #endif double valueP = pi[iRow] * direction; // if move makes infeasible then make at least default double newValue = activity[iRow] + movement; if (newValue > upper[iRow] + tolerance || newValue < lower[iRow] - tolerance) { shadowEstimateDown_ += fabs(movement) * CoinMax(fabs(valueP), info->defaultDual_); infeasible = true; } } if (shadowEstimateDown_ < info->integerTolerance_) { if (!infeasible) { shadowEstimateDown_ = 1.0e-10; #ifdef COIN_DEVELOP printf("zero pseudoShadowPrice\n"); #endif } else shadowEstimateDown_ = info->integerTolerance_; } // And other way // take off objMove -= info->objective_[jColumnDown]; for (j = info->columnStart_[jColumnDown]; j < info->columnStart_[jColumnDown] + info->columnLength_[jColumnDown]; j++) { double value = -info->elementByColumn_[j]; int iRow = info->row_[j]; double oldValue = info->usefulRegion_[iRow]; if (!oldValue) { info->indexRegion_[n++] = iRow; } else { value += oldValue; if (!value) value = 1.0e-100; } info->usefulRegion_[iRow] = value; } // add on objMove += info->objective_[jColumnUp]; for (j = info->columnStart_[jColumnUp]; j < info->columnStart_[jColumnUp] + info->columnLength_[jColumnUp]; j++) { double value = info->elementByColumn_[j]; int iRow = info->row_[j]; double oldValue = info->usefulRegion_[iRow]; if (!oldValue) { info->indexRegion_[n++] = iRow; } else { value += oldValue; if (!value) value = 1.0e-100; } info->usefulRegion_[iRow] = value; } shadowEstimateUp_ = objMove * direction; infeasible = false; for (int k = 0; k < n; k++) { int iRow = info->indexRegion_[k]; double movement = info->usefulRegion_[iRow]; info->usefulRegion_[iRow] = 0.0; #if 0 if (lower[iRow] < -1.0e20) { if (pi[iRow] > 1.0e-3) { printf("Bad pi on row %d of %g\n",iRow,pi[iRow]); } } if (upper[iRow] >1.0e20) { if (pi[iRow] < -1.0e-3) { printf("Bad pi on row %d of %g\n",iRow,pi[iRow]); } } #endif double valueP = pi[iRow] * direction; // if move makes infeasible then make at least default double newValue = activity[iRow] + movement; if (newValue > upper[iRow] + tolerance || newValue < lower[iRow] - tolerance) { shadowEstimateUp_ += fabs(movement) * CoinMax(fabs(valueP), info->defaultDual_); infeasible = true; } } if (shadowEstimateUp_ < info->integerTolerance_) { if (!infeasible) { shadowEstimateUp_ = 1.0e-10; #ifdef COIN_DEVELOP printf("zero pseudoShadowPrice\n"); #endif } else shadowEstimateUp_ = info->integerTolerance_; } // adjust double downCost = shadowEstimateDown_; double upCost = shadowEstimateUp_; if (numberTimesDown_) downCost *= downDynamicPseudoRatio_ / static_cast (numberTimesDown_); if (numberTimesUp_) upCost *= upDynamicPseudoRatio_ / static_cast (numberTimesUp_); #define WEIGHT_AFTER 0.7 #define WEIGHT_BEFORE 0.1 int stateOfSearch = model_->stateOfSearch() % 10; double returnValue = 0.0; double minValue = CoinMin(downCost, upCost); double maxValue = CoinMax(downCost, upCost); if (stateOfSearch <= 2) { // no branching solution returnValue = WEIGHT_BEFORE * minValue + (1.0 - WEIGHT_BEFORE) * maxValue; } else { returnValue = WEIGHT_AFTER * minValue + (1.0 - WEIGHT_AFTER) * maxValue; } #ifdef PRINT_SHADOW printf("%d id - down %d %g up %d %g shadow %g, %g returned %g\n", id_, numberTimesDown_, downDynamicPseudoRatio_, numberTimesUp_, upDynamicPseudoRatio_, shadowEstimateDown_, shadowEstimateUp_, returnValue); #endif return returnValue; } else { double value = lastNonZero - firstNonZero + 1; value *= 0.5 / static_cast (numberMembers_); return value; } } else { return 0.0; // satisfied } } // This looks at solution and sets bounds to contain solution void CbcSOS::feasibleRegion() { int j; int firstNonZero = -1; int lastNonZero = -1; OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); //const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double weight = 0.0; double sum = 0.0; for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; double value = CoinMax(0.0, solution[iColumn]); sum += value; if (value > integerTolerance && upper[iColumn]) { weight += weights_[j] * value; if (firstNonZero < 0) firstNonZero = j; lastNonZero = j; } } // Might get here in odd situation if so fix all if (lastNonZero - firstNonZero < sosType_) { for (j = 0; j < firstNonZero; j++) { int iColumn = members_[j]; solver->setColUpper(iColumn, 0.0); } for (j = lastNonZero + 1; j < numberMembers_; j++) { int iColumn = members_[j]; solver->setColUpper(iColumn, 0.0); } } else { for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; solver->setColUpper(iColumn, 0.0); solver->setColLower(iColumn, 1.0); } } } // Redoes data when sequence numbers change void CbcSOS::redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns) { model_ = model; int n2 = 0; for (int j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; int i; for (i = 0; i < numberColumns; i++) { if (originalColumns[i] == iColumn) break; } if (i < numberColumns) { members_[n2] = i; weights_[n2++] = weights_[j]; } } if (n2 < numberMembers_) { COIN_DETAIL_PRINT(printf("** SOS number of members reduced from %d to %d!\n",numberMembers_,n2)); numberMembers_ = n2; } } CbcBranchingObject * CbcSOS::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int way) { int j; const double * solution = model_->testSolution(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); //OsiSolverInterface * solver = model_->solver(); const double * upper = solver->getColUpper(); int firstNonFixed = -1; int lastNonFixed = -1; int firstNonZero = -1; int lastNonZero = -1; double weight = 0.0; double sum = 0.0; for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; if (upper[iColumn]) { double value = CoinMax(0.0, solution[iColumn]); sum += value; if (firstNonFixed < 0) firstNonFixed = j; lastNonFixed = j; if (value > integerTolerance) { weight += weights_[j] * value; if (firstNonZero < 0) firstNonZero = j; lastNonZero = j; } } } assert (lastNonZero - firstNonZero >= sosType_) ; // find where to branch assert (sum > 0.0); weight /= sum; int iWhere; double separator = 0.0; for (iWhere = firstNonZero; iWhere < lastNonZero; iWhere++) if (weight < weights_[iWhere+1]) break; if (sosType_ == 1) { // SOS 1 separator = 0.5 * (weights_[iWhere] + weights_[iWhere+1]); } else { // SOS 2 if (iWhere == firstNonFixed) iWhere++;; if (iWhere == lastNonFixed - 1) iWhere = lastNonFixed - 2; separator = weights_[iWhere+1]; } // create object CbcBranchingObject * branch; branch = new CbcSOSBranchingObject(model_, this, way, separator); branch->setOriginalObject(this); return branch; } /* Pass in information on branch just done and create CbcObjectUpdateData instance. If object does not need data then backward pointer will be NULL. Assumes can get information from solver */ CbcObjectUpdateData CbcSOS::createUpdateInformation(const OsiSolverInterface * solver, const CbcNode * node, const CbcBranchingObject * branchingObject) { double originalValue = node->objectiveValue(); int originalUnsatisfied = node->numberUnsatisfied(); double objectiveValue = solver->getObjValue() * solver->getObjSense(); int unsatisfied = 0; int i; //might be base model - doesn't matter int numberIntegers = model_->numberIntegers();; const double * solution = solver->getColSolution(); //const double * lower = solver->getColLower(); //const double * upper = solver->getColUpper(); double change = CoinMax(0.0, objectiveValue - originalValue); int iStatus; if (solver->isProvenOptimal()) iStatus = 0; // optimal else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) iStatus = 2; // unknown else iStatus = 1; // infeasible bool feasible = iStatus != 1; if (feasible) { double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); const int * integerVariable = model_->integerVariable(); for (i = 0; i < numberIntegers; i++) { int j = integerVariable[i]; double value = solution[j]; double nearest = floor(value + 0.5); if (fabs(value - nearest) > integerTolerance) unsatisfied++; } } int way = branchingObject->way(); way = - way; // because after branch so moved on double value = branchingObject->value(); CbcObjectUpdateData newData (this, way, change, iStatus, originalUnsatisfied - unsatisfied, value); newData.originalObjective_ = originalValue; // Solvers know about direction double direction = solver->getObjSense(); solver->getDblParam(OsiDualObjectiveLimit, newData.cutoff_); newData.cutoff_ *= direction; return newData; } // Update object by CbcObjectUpdateData void CbcSOS::updateInformation(const CbcObjectUpdateData & data) { bool feasible = data.status_ != 1; int way = data.way_; //double value = data.branchingValue_; double originalValue = data.originalObjective_; double change = data.change_; if (way < 0) { // down if (!feasible) { double distanceToCutoff = 0.0; //double objectiveValue = model_->getCurrentMinimizationObjValue(); distanceToCutoff = model_->getCutoff() - originalValue; if (distanceToCutoff < 1.0e20) change = distanceToCutoff * 2.0; else change = (downDynamicPseudoRatio_ * shadowEstimateDown_ + 1.0e-3) * 10.0; } change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change); #ifdef PRINT_SHADOW if (numberTimesDown_) printf("Updating id %d - down change %g (true %g) - ndown %d estimated change %g - raw shadow estimate %g\n", id_, change, data.change_, numberTimesDown_, shadowEstimateDown_* (downDynamicPseudoRatio_ / ((double) numberTimesDown_)), shadowEstimateDown_); else printf("Updating id %d - down change %g (true %g) - shadow estimate %g\n", id_, change, data.change_, shadowEstimateDown_); #endif numberTimesDown_++; downDynamicPseudoRatio_ += change / shadowEstimateDown_; } else { // up if (!feasible) { double distanceToCutoff = 0.0; //double objectiveValue = model_->getCurrentMinimizationObjValue(); distanceToCutoff = model_->getCutoff() - originalValue; if (distanceToCutoff < 1.0e20) change = distanceToCutoff * 2.0; else change = (upDynamicPseudoRatio_ * shadowEstimateUp_ + 1.0e-3) * 10.0; } change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change); #ifdef PRINT_SHADOW if (numberTimesUp_) printf("Updating id %d - up change %g (true %g) - nup %d estimated change %g - raw shadow estimate %g\n", id_, change, data.change_, numberTimesUp_, shadowEstimateUp_* (upDynamicPseudoRatio_ / ((double) numberTimesUp_)), shadowEstimateUp_); else printf("Updating id %d - up change %g (true %g) - shadow estimate %g\n", id_, change, data.change_, shadowEstimateUp_); #endif numberTimesUp_++; upDynamicPseudoRatio_ += change / shadowEstimateUp_; } } /* Create an OsiSolverBranch object This returns NULL if branch not represented by bound changes */ OsiSolverBranch * CbcSOS::solverBranch() const { int j; const double * solution = model_->testSolution(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); OsiSolverInterface * solver = model_->solver(); const double * upper = solver->getColUpper(); int firstNonFixed = -1; int lastNonFixed = -1; int firstNonZero = -1; int lastNonZero = -1; double weight = 0.0; double sum = 0.0; double * fix = new double[numberMembers_]; int * which = new int[numberMembers_]; for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; // fix all on one side or other (even if fixed) fix[j] = 0.0; which[j] = iColumn; if (upper[iColumn]) { double value = CoinMax(0.0, solution[iColumn]); sum += value; if (firstNonFixed < 0) firstNonFixed = j; lastNonFixed = j; if (value > integerTolerance) { weight += weights_[j] * value; if (firstNonZero < 0) firstNonZero = j; lastNonZero = j; } } } assert (lastNonZero - firstNonZero >= sosType_) ; // find where to branch assert (sum > 0.0); weight /= sum; // down branch fixes ones above weight to 0 int iWhere; int iDownStart = 0; int iUpEnd = 0; for (iWhere = firstNonZero; iWhere < lastNonZero; iWhere++) if (weight < weights_[iWhere+1]) break; if (sosType_ == 1) { // SOS 1 iUpEnd = iWhere + 1; iDownStart = iUpEnd; } else { // SOS 2 if (iWhere == firstNonFixed) iWhere++;; if (iWhere == lastNonFixed - 1) iWhere = lastNonFixed - 2; iUpEnd = iWhere + 1; iDownStart = iUpEnd + 1; } // OsiSolverBranch * branch = new OsiSolverBranch(); branch->addBranch(-1, 0, NULL, NULL, numberMembers_ - iDownStart, which + iDownStart, fix); branch->addBranch(1, 0, NULL, NULL, iUpEnd, which, fix); delete [] fix; delete [] which; return branch; } // Construct an OsiSOS object OsiSOS * CbcSOS::osiObject(const OsiSolverInterface * solver) const { OsiSOS * obj = new OsiSOS(solver, numberMembers_, members_, weights_, sosType_); obj->setPriority(priority()); return obj; } // Default Constructor CbcSOSBranchingObject::CbcSOSBranchingObject() : CbcBranchingObject(), firstNonzero_(-1), lastNonzero_(-1) { set_ = NULL; separator_ = 0.0; } // Useful constructor CbcSOSBranchingObject::CbcSOSBranchingObject (CbcModel * model, const CbcSOS * set, int way , double separator) : CbcBranchingObject(model, set->id(), way, 0.5) { set_ = set; separator_ = separator; computeNonzeroRange(); } // Copy constructor CbcSOSBranchingObject::CbcSOSBranchingObject (const CbcSOSBranchingObject & rhs) : CbcBranchingObject(rhs), firstNonzero_(rhs.firstNonzero_), lastNonzero_(rhs.lastNonzero_) { set_ = rhs.set_; separator_ = rhs.separator_; } // Assignment operator CbcSOSBranchingObject & CbcSOSBranchingObject::operator=( const CbcSOSBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); set_ = rhs.set_; separator_ = rhs.separator_; firstNonzero_ = rhs.firstNonzero_; lastNonzero_ = rhs.lastNonzero_; } return *this; } CbcBranchingObject * CbcSOSBranchingObject::clone() const { return (new CbcSOSBranchingObject(*this)); } // Destructor CbcSOSBranchingObject::~CbcSOSBranchingObject () { } void CbcSOSBranchingObject::computeNonzeroRange() { const int numberMembers = set_->numberMembers(); const double * weights = set_->weights(); int i = 0; if (way_ < 0) { for ( i = 0; i < numberMembers; i++) { if (weights[i] > separator_) break; } assert (i < numberMembers); firstNonzero_ = 0; lastNonzero_ = i; } else { for ( i = 0; i < numberMembers; i++) { if (weights[i] >= separator_) break; } assert (i < numberMembers); firstNonzero_ = i; lastNonzero_ = numberMembers; } } double CbcSOSBranchingObject::branch() { decrementNumberBranchesLeft(); int numberMembers = set_->numberMembers(); const int * which = set_->members(); const double * weights = set_->weights(); OsiSolverInterface * solver = model_->solver(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); // *** for way - up means fix all those in down section if (way_ < 0) { int i; for ( i = 0; i < numberMembers; i++) { if (weights[i] > separator_) break; } assert (i < numberMembers); for (; i < numberMembers; i++) solver->setColUpper(which[i], 0.0); way_ = 1; // Swap direction } else { int i; for ( i = 0; i < numberMembers; i++) { if (weights[i] >= separator_) break; else solver->setColUpper(which[i], 0.0); } assert (i < numberMembers); way_ = -1; // Swap direction } computeNonzeroRange(); double predictedChange=0.0; for (int i = 0; i < numberMembers; i++) { int iColumn=which[i]; if (lower[iColumn]>upper[iColumn]) predictedChange=COIN_DBL_MAX; } return predictedChange; } /* Update bounds in solver as in 'branch' and update given bounds. branchState is -1 for 'down' +1 for 'up' */ void CbcSOSBranchingObject::fix(OsiSolverInterface * solver, double * /*lower*/, double * upper, int branchState) const { int numberMembers = set_->numberMembers(); const int * which = set_->members(); const double * weights = set_->weights(); //const double * lower = solver->getColLower(); //const double * upper = solver->getColUpper(); // *** for way - up means fix all those in down section if (branchState < 0) { int i; for ( i = 0; i < numberMembers; i++) { if (weights[i] > separator_) break; } assert (i < numberMembers); for (; i < numberMembers; i++) { solver->setColUpper(which[i], 0.0); upper[which[i]] = 0.0; } } else { int i; for ( i = 0; i < numberMembers; i++) { if (weights[i] >= separator_) { break; } else { solver->setColUpper(which[i], 0.0); upper[which[i]] = 0.0; } } assert (i < numberMembers); } } // Print what would happen void CbcSOSBranchingObject::print() { int numberMembers = set_->numberMembers(); const int * which = set_->members(); const double * weights = set_->weights(); OsiSolverInterface * solver = model_->solver(); //const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); int first = numberMembers; int last = -1; int numberFixed = 0; int numberOther = 0; int i; for ( i = 0; i < numberMembers; i++) { double bound = upper[which[i]]; if (bound) { first = CoinMin(first, i); last = CoinMax(last, i); } } // *** for way - up means fix all those in down section if (way_ < 0) { printf("SOS Down"); for ( i = 0; i < numberMembers; i++) { double bound = upper[which[i]]; if (weights[i] > separator_) break; else if (bound) numberOther++; } assert (i < numberMembers); for (; i < numberMembers; i++) { double bound = upper[which[i]]; if (bound) numberFixed++; } } else { printf("SOS Up"); for ( i = 0; i < numberMembers; i++) { double bound = upper[which[i]]; if (weights[i] >= separator_) break; else if (bound) numberFixed++; } assert (i < numberMembers); for (; i < numberMembers; i++) { double bound = upper[which[i]]; if (bound) numberOther++; } } printf(" - at %g, free range %d (%g) => %d (%g), %d would be fixed, %d other way\n", separator_, which[first], weights[first], which[last], weights[last], numberFixed, numberOther); } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcSOSBranchingObject::compareOriginalObject (const CbcBranchingObject* brObj) const { const CbcSOSBranchingObject* br = dynamic_cast(brObj); assert(br); const CbcSOS* s0 = set_; const CbcSOS* s1 = br->set_; if (s0->sosType() != s1->sosType()) { return s0->sosType() - s1->sosType(); } if (s0->numberMembers() != s1->numberMembers()) { return s0->numberMembers() - s1->numberMembers(); } const int memberCmp = memcmp(s0->members(), s1->members(), s0->numberMembers() * sizeof(int)); if (memberCmp != 0) { return memberCmp; } return memcmp(s0->weights(), s1->weights(), s0->numberMembers() * sizeof(double)); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcSOSBranchingObject::compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap) { const CbcSOSBranchingObject* br = dynamic_cast(brObj); assert(br); if (firstNonzero_ < br->firstNonzero_) { if (lastNonzero_ >= br->lastNonzero_) { return CbcRangeSuperset; } else if (lastNonzero_ <= br->firstNonzero_) { return CbcRangeDisjoint; } else { // overlap if (replaceIfOverlap) { firstNonzero_ = br->firstNonzero_; } return CbcRangeOverlap; } } else if (firstNonzero_ > br->firstNonzero_) { if (lastNonzero_ <= br->lastNonzero_) { return CbcRangeSubset; } else if (firstNonzero_ >= br->lastNonzero_) { return CbcRangeDisjoint; } else { // overlap if (replaceIfOverlap) { lastNonzero_ = br->lastNonzero_; } return CbcRangeOverlap; } } else { if (lastNonzero_ == br->lastNonzero_) { return CbcRangeSame; } return lastNonzero_ < br->lastNonzero_ ? CbcRangeSubset : CbcRangeSuperset; } return CbcRangeSame; // fake return } Cbc-2.8.12/src/CbcBranchCut.cpp0000644000076600007660000002215011510742604014525 0ustar coincoin/* $Id: CbcBranchCut.cpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchCut.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" /** Default Constructor */ CbcBranchCut::CbcBranchCut () : CbcObject() { } /* Constructor so model can be passed up */ CbcBranchCut::CbcBranchCut (CbcModel * model) : CbcObject(model) { } // Copy constructor CbcBranchCut::CbcBranchCut ( const CbcBranchCut & rhs) : CbcObject(rhs) { } // Clone CbcObject * CbcBranchCut::clone() const { return new CbcBranchCut(*this); } // Assignment operator CbcBranchCut & CbcBranchCut::operator=( const CbcBranchCut& /*rhs*/) { return *this; } // Destructor CbcBranchCut::~CbcBranchCut () { } double CbcBranchCut::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { throw CoinError("Use of base class", "infeasibility", "CbcBranchCut"); preferredWay = -1; return 0.0; } // This looks at solution and sets bounds to contain solution /** More precisely: it first forces the variable within the existing bounds, and then tightens the bounds to fix the variable at the nearest integer value. */ void CbcBranchCut::feasibleRegion() { } /* Return true if branch created by object should fix variables */ bool CbcBranchCut::boundBranch() const { return false; } CbcBranchingObject * CbcBranchCut::createCbcBranch(OsiSolverInterface * /*solver*/, const OsiBranchingInformation * /*info*/, int /*way*/) { throw CoinError("Use of base class", "createCbcBranch", "CbcBranchCut"); return new CbcCutBranchingObject(); } /* Given valid solution (i.e. satisfied) and reduced costs etc returns a branching object which would give a new feasible point in direction reduced cost says would be cheaper. If no feasible point returns null */ CbcBranchingObject * CbcBranchCut::preferredNewFeasible() const { throw CoinError("Use of base class", "preferredNewFeasible", "CbcBranchCut"); return new CbcCutBranchingObject(); } /* Given valid solution (i.e. satisfied) and reduced costs etc returns a branching object which would give a new feasible point in direction opposite to one reduced cost says would be cheaper. If no feasible point returns null */ CbcBranchingObject * CbcBranchCut::notPreferredNewFeasible() const { throw CoinError("Use of base class", "notPreferredNewFeasible", "CbcBranchCut"); return new CbcCutBranchingObject(); } /* Bounds may be tightened, so it may be good to be able to refresh the local copy of the original bounds. */ void CbcBranchCut::resetBounds() { } // Default Constructor CbcCutBranchingObject::CbcCutBranchingObject() : CbcBranchingObject() { down_ = OsiRowCut(); up_ = OsiRowCut(); canFix_ = false; } // Useful constructor CbcCutBranchingObject::CbcCutBranchingObject (CbcModel * model, OsiRowCut & down, OsiRowCut &up, bool canFix) : CbcBranchingObject(model, 0, -1, 0.0) { down_ = down; up_ = up; canFix_ = canFix; } // Copy constructor CbcCutBranchingObject::CbcCutBranchingObject ( const CbcCutBranchingObject & rhs) : CbcBranchingObject(rhs) { down_ = rhs.down_; up_ = rhs.up_; canFix_ = rhs.canFix_; } // Assignment operator CbcCutBranchingObject & CbcCutBranchingObject::operator=( const CbcCutBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); down_ = rhs.down_; up_ = rhs.up_; canFix_ = rhs.canFix_; } return *this; } CbcBranchingObject * CbcCutBranchingObject::clone() const { return (new CbcCutBranchingObject(*this)); } // Destructor CbcCutBranchingObject::~CbcCutBranchingObject () { } /* Perform a branch by adjusting bounds and/or adding a cut. Note that each arm of the branch advances the object to the next arm by advancing the value of way_. Returns change in guessed objective on next branch */ double CbcCutBranchingObject::branch() { decrementNumberBranchesLeft(); OsiRowCut * cut; if (way_ < 0) { cut = &down_; way_ = 1; } else { cut = &up_; way_ = -1; // Swap direction } printf("CUT %s ", (way_ == -1) ? "up" : "down"); cut->print(); // See if cut just fixes variables double lb = cut->lb(); double ub = cut->ub(); int n = cut->row().getNumElements(); const int * column = cut->row().getIndices(); const double * element = cut->row().getElements(); OsiSolverInterface * solver = model_->solver(); const double * upper = solver->getColUpper(); const double * lower = solver->getColLower(); double low = 0.0; double high = 0.0; for (int i = 0; i < n; i++) { int iColumn = column[i]; double value = element[i]; if (value > 0.0) { high += upper[iColumn] * value; low += lower[iColumn] * value; } else { high += lower[iColumn] * value; low += upper[iColumn] * value; } } // leave as cut //model_->setNextRowCut(*cut); //return 0.0; // assume cut was cunningly constructed so we need not worry too much about tolerances if (low + 1.0e-8 >= ub && canFix_) { // fix for (int i = 0; i < n; i++) { int iColumn = column[i]; double value = element[i]; if (value > 0.0) { solver->setColUpper(iColumn, lower[iColumn]); } else { solver->setColLower(iColumn, upper[iColumn]); } } } else if (high - 1.0e-8 <= lb && canFix_) { // fix for (int i = 0; i < n; i++) { int iColumn = column[i]; double value = element[i]; if (value > 0.0) { solver->setColLower(iColumn, upper[iColumn]); } else { solver->setColUpper(iColumn, lower[iColumn]); } } } else { // leave as cut model_->setNextRowCut(*cut); } return 0.0; } // Print what would happen void CbcCutBranchingObject::print() { OsiRowCut * cut; if (way_ < 0) { cut = &down_; printf("CbcCut would branch down"); } else { cut = &up_; printf("CbcCut would branch up"); } double lb = cut->lb(); double ub = cut->ub(); int n = cut->row().getNumElements(); const int * column = cut->row().getIndices(); const double * element = cut->row().getElements(); if (n > 5) { printf(" - %d elements, lo=%g, up=%g\n", n, lb, ub); } else { printf(" - %g <=", lb); for (int i = 0; i < n; i++) { int iColumn = column[i]; double value = element[i]; printf(" (%d,%g)", iColumn, value); } printf(" <= %g\n", ub); } } // Return true if branch should fix variables bool CbcCutBranchingObject::boundBranch() const { return false; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcCutBranchingObject::compareOriginalObject (const CbcBranchingObject* brObj) const { const CbcCutBranchingObject* br = dynamic_cast(brObj); assert(br); const OsiRowCut& r0 = way_ == -1 ? down_ : up_; const OsiRowCut& r1 = br->way_ == -1 ? br->down_ : br->up_; return r0.row().compare(r1.row()); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcCutBranchingObject::compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap) { const CbcCutBranchingObject* br = dynamic_cast(brObj); assert(br); OsiRowCut& r0 = way_ == -1 ? down_ : up_; const OsiRowCut& r1 = br->way_ == -1 ? br->down_ : br->up_; double thisBd[2]; thisBd[0] = r0.lb(); thisBd[1] = r0.ub(); double otherBd[2]; otherBd[0] = r1.lb(); otherBd[1] = r1.ub(); CbcRangeCompare comp = CbcCompareRanges(thisBd, otherBd, replaceIfOverlap); if (comp != CbcRangeOverlap || (comp == CbcRangeOverlap && !replaceIfOverlap)) { return comp; } r0.setLb(thisBd[0]); r0.setUb(thisBd[1]); return comp; } Cbc-2.8.12/src/CbcFollowOn.cpp0000644000076600007660000006312312131315050014407 0ustar coincoin// $Id: CbcFollowOn.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcFollowOn.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchCut.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" //############################################################################## // Default Constructor CbcFollowOn::CbcFollowOn () : CbcObject(), rhs_(NULL) { } // Useful constructor CbcFollowOn::CbcFollowOn (CbcModel * model) : CbcObject(model) { assert (model); OsiSolverInterface * solver = model_->solver(); matrix_ = *solver->getMatrixByCol(); matrix_.removeGaps(); matrix_.setExtraGap(0.0); matrixByRow_ = *solver->getMatrixByRow(); int numberRows = matrix_.getNumRows(); rhs_ = new int[numberRows]; int i; const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); for (i = 0; i < numberRows; i++) { rhs_[i] = 0; double value = rowLower[i]; if (value == rowUpper[i]) { if (floor(value) == value && value >= 1.0 && value < 10.0) { // check elements bool good = true; for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (!solver->isBinary(iColumn)) good = false; double elValue = elementByRow[j]; if (floor(elValue) != elValue || value < 1.0) good = false; } if (good) rhs_[i] = static_cast (value); } } } } // Copy constructor CbcFollowOn::CbcFollowOn ( const CbcFollowOn & rhs) : CbcObject(rhs), matrix_(rhs.matrix_), matrixByRow_(rhs.matrixByRow_) { int numberRows = matrix_.getNumRows(); rhs_ = CoinCopyOfArray(rhs.rhs_, numberRows); } // Clone CbcObject * CbcFollowOn::clone() const { return new CbcFollowOn(*this); } // Assignment operator CbcFollowOn & CbcFollowOn::operator=( const CbcFollowOn & rhs) { if (this != &rhs) { CbcObject::operator=(rhs); delete [] rhs_; matrix_ = rhs.matrix_; matrixByRow_ = rhs.matrixByRow_; int numberRows = matrix_.getNumRows(); rhs_ = CoinCopyOfArray(rhs.rhs_, numberRows); } return *this; } // Destructor CbcFollowOn::~CbcFollowOn () { delete [] rhs_; } // As some computation is needed in more than one place - returns row int CbcFollowOn::gutsOfFollowOn(int & otherRow, int & preferredWay) const { int whichRow = -1; otherRow = -1; int numberRows = matrix_.getNumRows(); int i; // For sorting int * sort = new int [numberRows]; int * isort = new int [numberRows]; // Column copy //const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); const double * solution = solver->getColSolution(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); int nSort = 0; for (i = 0; i < numberRows; i++) { if (rhs_[i]) { // check elements double smallest = 1.0e10; double largest = 0.0; int rhsValue = rhs_[i]; int number1 = 0; int numberUnsatisfied = 0; for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; double value = elementByRow[j]; double solValue = solution[iColumn]; if (columnLower[iColumn] != columnUpper[iColumn]) { smallest = CoinMin(smallest, value); largest = CoinMax(largest, value); if (value == 1.0) number1++; if (solValue < 1.0 - integerTolerance && solValue > integerTolerance) numberUnsatisfied++; } else { rhsValue -= static_cast(value * floor(solValue + 0.5)); } } if (numberUnsatisfied > 1) { if (smallest < largest) { // probably no good but check a few things assert (largest <= rhsValue); if (number1 == 1 && largest == rhsValue) printf("could fix\n"); } else if (largest == rhsValue) { sort[nSort] = i; isort[nSort++] = -numberUnsatisfied; } } } } if (nSort > 1) { CoinSort_2(isort, isort + nSort, sort); CoinZeroN(isort, numberRows); double * other = new double[numberRows]; CoinZeroN(other, numberRows); int * which = new int[numberRows]; //#define COUNT #ifndef COUNT bool beforeSolution = model_->getSolutionCount() == 0; #endif for (int k = 0; k < nSort - 1; k++) { i = sort[k]; int numberUnsatisfied = 0; int n = 0; int j; for (j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (columnLower[iColumn] != columnUpper[iColumn]) { double solValue = solution[iColumn] - columnLower[iColumn]; if (solValue < 1.0 - integerTolerance && solValue > integerTolerance) { numberUnsatisfied++; for (int jj = columnStart[iColumn]; jj < columnStart[iColumn] + columnLength[iColumn]; jj++) { int iRow = row[jj]; if (rhs_[iRow]) { other[iRow] += solValue; if (isort[iRow]) { isort[iRow]++; } else { isort[iRow] = 1; which[n++] = iRow; } } } } } } double total = 0.0; // Take out row double sumThis = other[i]; other[i] = 0.0; assert (numberUnsatisfied == isort[i]); // find one nearest half if solution, one if before solution int iBest = -1; double dtarget = 0.5 * total; #ifdef COUNT int target = (numberUnsatisfied + 1) >> 1; int best = numberUnsatisfied; #else double best; if (beforeSolution) best = dtarget; else best = 1.0e30; #endif for (j = 0; j < n; j++) { int iRow = which[j]; double dvalue = other[iRow]; other[iRow] = 0.0; #ifdef COUNT int value = isort[iRow]; #endif isort[iRow] = 0; if (fabs(dvalue) < 1.0e-8 || fabs(sumThis - dvalue) < 1.0e-8) continue; if (dvalue < integerTolerance || dvalue > 1.0 - integerTolerance) continue; #ifdef COUNT if (abs(value - target) < best && value != numberUnsatisfied) { best = abs(value - target); iBest = iRow; if (dvalue < dtarget) preferredWay = 1; else preferredWay = -1; } #else if (beforeSolution) { if (fabs(dvalue - dtarget) > best) { best = fabs(dvalue - dtarget); iBest = iRow; if (dvalue < dtarget) preferredWay = 1; else preferredWay = -1; } } else { if (fabs(dvalue - dtarget) < best) { best = fabs(dvalue - dtarget); iBest = iRow; if (dvalue < dtarget) preferredWay = 1; else preferredWay = -1; } } #endif } if (iBest >= 0) { whichRow = i; otherRow = iBest; break; } } delete [] which; delete [] other; } delete [] sort; delete [] isort; return whichRow; } double CbcFollowOn::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { int otherRow = 0; int whichRow = gutsOfFollowOn(otherRow, preferredWay); if (whichRow < 0) return 0.0; else return 2.0* model_->getDblParam(CbcModel::CbcIntegerTolerance); } // This looks at solution and sets bounds to contain solution void CbcFollowOn::feasibleRegion() { } CbcBranchingObject * CbcFollowOn::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int way) { int otherRow = 0; int preferredWay; int whichRow = gutsOfFollowOn(otherRow, preferredWay); assert(way == preferredWay); assert (whichRow >= 0); int numberColumns = matrix_.getNumCols(); // Column copy //const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Row copy //const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); //OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); //const double * solution = solver->getColSolution(); int nUp = 0; int nDown = 0; int * upList = new int[numberColumns]; int * downList = new int[numberColumns]; int j; for (j = rowStart[whichRow]; j < rowStart[whichRow] + rowLength[whichRow]; j++) { int iColumn = column[j]; if (columnLower[iColumn] != columnUpper[iColumn]) { bool up = true; for (int jj = columnStart[iColumn]; jj < columnStart[iColumn] + columnLength[iColumn]; jj++) { int iRow = row[jj]; if (iRow == otherRow) { up = false; break; } } if (up) upList[nUp++] = iColumn; else downList[nDown++] = iColumn; } } //printf("way %d\n",way); // create object //printf("would fix %d down and %d up\n",nDown,nUp); CbcBranchingObject * branch = new CbcFixingBranchingObject(model_, way, nDown, downList, nUp, upList); delete [] upList; delete [] downList; return branch; } //############################################################################## // Default Constructor CbcFixingBranchingObject::CbcFixingBranchingObject() : CbcBranchingObject() { numberDown_ = 0; numberUp_ = 0; downList_ = NULL; upList_ = NULL; } // Useful constructor CbcFixingBranchingObject::CbcFixingBranchingObject (CbcModel * model, int way , int numberOnDownSide, const int * down, int numberOnUpSide, const int * up) : CbcBranchingObject(model, 0, way, 0.5) { numberDown_ = numberOnDownSide; numberUp_ = numberOnUpSide; downList_ = CoinCopyOfArray(down, numberDown_); upList_ = CoinCopyOfArray(up, numberUp_); } // Copy constructor CbcFixingBranchingObject::CbcFixingBranchingObject ( const CbcFixingBranchingObject & rhs) : CbcBranchingObject(rhs) { numberDown_ = rhs.numberDown_; numberUp_ = rhs.numberUp_; downList_ = CoinCopyOfArray(rhs.downList_, numberDown_); upList_ = CoinCopyOfArray(rhs.upList_, numberUp_); } // Assignment operator CbcFixingBranchingObject & CbcFixingBranchingObject::operator=( const CbcFixingBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); delete [] downList_; delete [] upList_; numberDown_ = rhs.numberDown_; numberUp_ = rhs.numberUp_; downList_ = CoinCopyOfArray(rhs.downList_, numberDown_); upList_ = CoinCopyOfArray(rhs.upList_, numberUp_); } return *this; } CbcBranchingObject * CbcFixingBranchingObject::clone() const { return (new CbcFixingBranchingObject(*this)); } // Destructor CbcFixingBranchingObject::~CbcFixingBranchingObject () { delete [] downList_; delete [] upList_; } double CbcFixingBranchingObject::branch() { decrementNumberBranchesLeft(); OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); int i; // *** for way - up means fix all those in up section if (way_ < 0) { #ifdef FULL_PRINT printf("Down Fix "); #endif //printf("Down Fix %d\n",numberDown_); for (i = 0; i < numberDown_; i++) { int iColumn = downList_[i]; model_->solver()->setColUpper(iColumn, columnLower[iColumn]); #ifdef FULL_PRINT printf("Setting bound on %d to lower bound\n", iColumn); #endif } way_ = 1; // Swap direction } else { #ifdef FULL_PRINT printf("Up Fix "); #endif //printf("Up Fix %d\n",numberUp_); for (i = 0; i < numberUp_; i++) { int iColumn = upList_[i]; model_->solver()->setColUpper(iColumn, columnLower[iColumn]); #ifdef FULL_PRINT printf("Setting bound on %d to lower bound\n", iColumn); #endif } way_ = -1; // Swap direction } #ifdef FULL_PRINT printf("\n"); #endif return 0.0; } void CbcFixingBranchingObject::print() { int i; // *** for way - up means fix all those in up section if (way_ < 0) { printf("Down Fix "); for (i = 0; i < numberDown_; i++) { int iColumn = downList_[i]; printf("%d ", iColumn); } } else { printf("Up Fix "); for (i = 0; i < numberUp_; i++) { int iColumn = upList_[i]; printf("%d ", iColumn); } } printf("\n"); } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcFixingBranchingObject::compareOriginalObject (const CbcBranchingObject* /*brObj*/) const { throw("must implement"); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcFixingBranchingObject::compareBranchingObject (const CbcBranchingObject* /*brObj*/, const bool /*replaceIfOverlap*/) { #ifdef JJF_ZERO //ndef NDEBUG const CbcFixingBranchingObject* br = dynamic_cast(brObj); assert(br); #endif // If two FixingBranchingObject's have the same base object then it's pretty // much guaranteed throw("must implement"); } //############################################################################## //############################################################################## // Default Constructor CbcIdiotBranch::CbcIdiotBranch () : CbcObject() { id_ = 1000000000 + CutBranchingObj; } // Useful constructor CbcIdiotBranch::CbcIdiotBranch (CbcModel * model) : CbcObject(model) { assert (model); id_ = 1000000000 + CutBranchingObj; } // Copy constructor CbcIdiotBranch::CbcIdiotBranch ( const CbcIdiotBranch & rhs) : CbcObject(rhs), randomNumberGenerator_(rhs.randomNumberGenerator_), savedRandomNumberGenerator_(rhs.savedRandomNumberGenerator_) { } // Clone CbcObject * CbcIdiotBranch::clone() const { return new CbcIdiotBranch(*this); } // Assignment operator CbcIdiotBranch & CbcIdiotBranch::operator=( const CbcIdiotBranch & rhs) { if (this != &rhs) { CbcObject::operator=(rhs); randomNumberGenerator_ = rhs.randomNumberGenerator_; savedRandomNumberGenerator_ = rhs.savedRandomNumberGenerator_; } return *this; } // Destructor CbcIdiotBranch::~CbcIdiotBranch () { } double CbcIdiotBranch::infeasibility(const OsiBranchingInformation * info, int &preferredWay) const { randomNumberGenerator_ = savedRandomNumberGenerator_; double rhs = buildCut(info,0,preferredWay).ub(); double fraction = rhs-floor(rhs); if (fraction>0.5) fraction=1.0-fraction; return fraction; } // This looks at solution and sets bounds to contain solution void CbcIdiotBranch::feasibleRegion() { } CbcBranchingObject * CbcIdiotBranch::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) { // down and up randomNumberGenerator_ = savedRandomNumberGenerator_; int preferredWay; OsiRowCut downCut = buildCut(info,0,preferredWay); double rhs = downCut.ub(); assert(rhs == downCut.lb()); OsiRowCut upCut =downCut; downCut.setUb(floor(rhs)); downCut.setLb(-COIN_DBL_MAX); upCut.setLb(ceil(rhs)); upCut.setUb(COIN_DBL_MAX); CbcBranchingObject * branch = new CbcCutBranchingObject(model_, downCut,upCut,true); return branch; } // Initialize for branching void CbcIdiotBranch::initializeForBranching(CbcModel * ) { savedRandomNumberGenerator_ = randomNumberGenerator_; } // Build "cut" OsiRowCut CbcIdiotBranch::buildCut(const OsiBranchingInformation * info,int /*type*/,int & preferredWay) const { int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int * which = new int [numberIntegers]; double * away = new double [numberIntegers]; const double * solution = info->solution_; const double * lower = info->lower_; const double * upper = info->upper_; double integerTolerance = model_->getIntegerTolerance(); //int nMax=CoinMin(4,numberIntegers/2); int n=0; for (int i=0;iintegerTolerance) { double random = 0.0; //0.25*randomNumberGenerator_.randomDouble(); away[n]=-fabs(value-nearest)*(1.0+random); which[n++]=iColumn; } #else double distanceDown = value-floor(value); if (distanceDown>10.0*integerTolerance&&distanceDown<0.1) { double random = 0.0; //0.25*randomNumberGenerator_.randomDouble(); away[n]=distanceDown*(1.0+random); which[n++]=iColumn; } #endif } CoinSort_2(away,away+n,which); OsiRowCut possibleCut; possibleCut.setUb(0.0); if (n>1) { int nUse=0; double useRhs=0.0; double best=0.0; double rhs = 0.0; double scaleFactor=1.0; /* should be able to be clever to find best cut maybe don't do if away >0.45 maybe don't be random maybe do complete enumeration on biggest k (where sum of k >= 1.0) maybe allow +-1 */ for (int i=0;ibest) { nUse=i+1; best=distance; useRhs=rhs; } } // create cut if (nUse>1) { possibleCut.setRow(nUse,which,away); possibleCut.setLb(useRhs); possibleCut.setUb(useRhs); } } delete [] which; delete [] away; return possibleCut; } #if 0 //############################################################################## // Default Constructor CbcBoundingBranchingObject::CbcBoundingBranchingObject() : CbcBranchingObject() { branchCut_.setUb(0.0); } // Useful constructor CbcBoundingBranchingObject::CbcBoundingBranchingObject (CbcModel * model, int way , const OsiRowCut * cut) : CbcBranchingObject(model, 0, way, 0.5) { branchCut_ = *cut; } // Copy constructor CbcBoundingBranchingObject::CbcBoundingBranchingObject ( const CbcBoundingBranchingObject & rhs) : CbcBranchingObject(rhs) { branchCut_ = rhs.branchCut_; } // Assignment operator CbcBoundingBranchingObject & CbcBoundingBranchingObject::operator=( const CbcBoundingBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); branchCut_ = rhs.branchCut_; } return *this; } CbcBranchingObject * CbcBoundingBranchingObject::clone() const { return (new CbcBoundingBranchingObject(*this)); } // Destructor CbcBoundingBranchingObject::~CbcBoundingBranchingObject () { } double CbcBoundingBranchingObject::branch() { decrementNumberBranchesLeft(); OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); int i; // *** for way - up means bound all those in up section if (way_ < 0) { #ifdef FULL_PRINT printf("Down Bound "); #endif //printf("Down Bound %d\n",numberDown_); for (i = 0; i < numberDown_; i++) { int iColumn = downList_[i]; model_->solver()->setColUpper(iColumn, columnLower[iColumn]); #ifdef FULL_PRINT printf("Setting bound on %d to lower bound\n", iColumn); #endif } way_ = 1; // Swap direction } else { #ifdef FULL_PRINT printf("Up Bound "); #endif //printf("Up Bound %d\n",numberUp_); for (i = 0; i < numberUp_; i++) { int iColumn = upList_[i]; model_->solver()->setColUpper(iColumn, columnLower[iColumn]); #ifdef FULL_PRINT printf("Setting bound on %d to lower bound\n", iColumn); #endif } way_ = -1; // Swap direction } #ifdef FULL_PRINT printf("\n"); #endif return 0.0; } void CbcBoundingBranchingObject::print() { OsiRowCut cut = branchCut_; if (way_ < 0) { printf("Down Fix "); cut.setUb(floor(branchCut_.ub())); cut.setLb(-COIN_DBL_MAX); } else { printf("Up Fix "); cut.setLb(ceil(branchCut_.lb())); cut.setUb(COIN_DBL_MAX); } printf("\n"); cut.print(); } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcBoundingBranchingObject::compareOriginalObject (const CbcBranchingObject* /*brObj*/) const { throw("must implement"); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcBoundingBranchingObject::compareBranchingObject (const CbcBranchingObject* /*brObj*/, const bool /*replaceIfOverlap*/) { #ifdef JJF_ZERO //ndef NDEBUG const CbcBoundingBranchingObject* br = dynamic_cast(brObj); assert(br); #endif // If two BoundingBranchingObject's have the same base object then it's pretty // much guaranteed throw("must implement"); } //############################################################################## #endif Cbc-2.8.12/src/Makefile.in0000644000076600007660000013566312376140747013636 0ustar coincoin# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Copyright (C) 2006, 2007 International Business Machines and others. # All Rights Reserved. # This file is distributed under the Eclipse Public License. # Author: Andreas Waechter IBM 2006-04-13 srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) ######################################################################## # cbc program # ######################################################################## # Name of the executable compiled in this directory. We want it to be # installed in the 'bin' directory @COIN_HAS_CLP_TRUE@am__append_1 = cbc ######################################################################## # cbc-generic program # ######################################################################## # Name of the executable compiled in this directory. We want it to be # installed in the 'bin' directory @CBC_BUILD_CBC_GENERIC_TRUE@am__append_2 = cbc-generic # List all additionally required solver and Osi libraries # the linker flags for all available LP solvers should already be included in $CBCGENERIC_LIBS, # so just add compiler flags here (all we can think of) @CBC_BUILD_CBC_GENERIC_TRUE@am__append_3 = $(DYLP_CFLAGS) $(GLPK_CFLAGS) $(MSK_CFLAGS) $(SPX_CFLAGS) $(VOL_CFLAGS) $(XPR_CFLAGS) subdir = src DIST_COMMON = $(includecoin_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(srcdir)/config_cbc.h.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h config_cbc.h CONFIG_CLEAN_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(includecoindir)" libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = @DEPENDENCY_LINKING_TRUE@libCbc_la_DEPENDENCIES = \ @DEPENDENCY_LINKING_TRUE@ $(am__DEPENDENCIES_1) am_libCbc_la_OBJECTS = CbcBranchAllDifferent.lo CbcBranchCut.lo \ CbcBranchDecision.lo CbcBranchDefaultDecision.lo \ CbcBranchDynamic.lo CbcBranchingObject.lo CbcBranchLotsize.lo \ CbcBranchToFixLots.lo CbcCompareDefault.lo CbcCompareDepth.lo \ CbcCompareEstimate.lo CbcCompareObjective.lo CbcConsequence.lo \ CbcClique.lo CbcCountRowCut.lo CbcCutGenerator.lo \ CbcCutModifier.lo CbcCutSubsetModifier.lo \ CbcDummyBranchingObject.lo CbcEventHandler.lo CbcFathom.lo \ CbcFathomDynamicProgramming.lo CbcFixVariable.lo \ CbcFullNodeInfo.lo CbcFollowOn.lo CbcGeneral.lo \ CbcGeneralDepth.lo CbcHeuristic.lo CbcHeuristicDINS.lo \ CbcHeuristicDive.lo CbcHeuristicDiveCoefficient.lo \ CbcHeuristicDiveFractional.lo CbcHeuristicDiveGuided.lo \ CbcHeuristicDiveLineSearch.lo CbcHeuristicDivePseudoCost.lo \ CbcHeuristicDiveVectorLength.lo CbcHeuristicFPump.lo \ CbcHeuristicGreedy.lo CbcHeuristicLocal.lo \ CbcHeuristicPivotAndFix.lo CbcHeuristicRandRound.lo \ CbcHeuristicRENS.lo CbcHeuristicRINS.lo CbcHeuristicVND.lo \ CbcMessage.lo CbcModel.lo CbcNode.lo CbcNodeInfo.lo CbcNWay.lo \ CbcObject.lo CbcObjectUpdateData.lo CbcPartialNodeInfo.lo \ CbcSimpleInteger.lo CbcSimpleIntegerDynamicPseudoCost.lo \ CbcSimpleIntegerPseudoCost.lo CbcSOS.lo CbcStatistics.lo \ CbcStrategy.lo CbcSubProblem.lo CbcThread.lo CbcTree.lo \ CbcTreeLocal.lo libCbc_la_OBJECTS = $(am_libCbc_la_OBJECTS) @DEPENDENCY_LINKING_TRUE@libCbcSolver_la_DEPENDENCIES = \ @DEPENDENCY_LINKING_TRUE@ $(am__DEPENDENCIES_1) libCbc.la am_libCbcSolver_la_OBJECTS = Cbc_C_Interface.lo CbcCbcParam.lo \ Cbc_ampl.lo CbcLinked.lo CbcLinkedUtils.lo unitTestClp.lo \ CbcSolver.lo CbcSolverHeuristics.lo CbcSolverAnalyze.lo \ CbcMipStartIO.lo CbcSolverExpandKnapsack.lo libCbcSolver_la_OBJECTS = $(am_libCbcSolver_la_OBJECTS) @COIN_HAS_CLP_TRUE@am__EXEEXT_1 = cbc$(EXEEXT) @CBC_BUILD_CBC_GENERIC_TRUE@am__EXEEXT_2 = cbc-generic$(EXEEXT) binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am__cbc_SOURCES_DIST = CoinSolve.cpp @COIN_HAS_CLP_TRUE@am_cbc_OBJECTS = CoinSolve.$(OBJEXT) cbc_OBJECTS = $(am_cbc_OBJECTS) am__cbc_generic_SOURCES_DIST = CbcGenBaB.cpp CbcGenCbcParam.cpp \ CbcGenCbcParam.hpp CbcGenCbcParamUtils.cpp CbcGenCtlBlk.cpp \ CbcGenCtlBlk.hpp CbcGeneric.cpp CbcGenMessages.cpp \ CbcGenMessages.hpp CbcGenOsiParam.cpp CbcGenOsiParam.hpp \ CbcGenOsiParamUtils.cpp CbcGenParam.cpp CbcGenParam.hpp \ CbcGenParamUtils.cpp CbcGenSolution.cpp CbcGenSolvers.cpp @CBC_BUILD_CBC_GENERIC_TRUE@am_cbc_generic_OBJECTS = \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenBaB.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenCbcParam.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenCbcParamUtils.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenCtlBlk.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGeneric.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenMessages.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenOsiParam.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenOsiParamUtils.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenParam.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenParamUtils.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenSolution.$(OBJEXT) \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenSolvers.$(OBJEXT) cbc_generic_OBJECTS = $(am_cbc_generic_OBJECTS) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libCbc_la_SOURCES) $(libCbcSolver_la_SOURCES) \ $(cbc_SOURCES) $(cbc_generic_SOURCES) DIST_SOURCES = $(libCbc_la_SOURCES) $(libCbcSolver_la_SOURCES) \ $(am__cbc_SOURCES_DIST) $(am__cbc_generic_SOURCES_DIST) includecoinHEADERS_INSTALL = $(INSTALL_HEADER) HEADERS = $(includecoin_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ABSBUILDDIR = @ABSBUILDDIR@ ACLOCAL = @ACLOCAL@ ADD_CFLAGS = @ADD_CFLAGS@ ADD_CXXFLAGS = @ADD_CXXFLAGS@ ALWAYS_FALSE_FALSE = @ALWAYS_FALSE_FALSE@ ALWAYS_FALSE_TRUE = @ALWAYS_FALSE_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ ASL_CFLAGS = @ASL_CFLAGS@ ASL_CFLAGS_INSTALLED = @ASL_CFLAGS_INSTALLED@ ASL_DATA = @ASL_DATA@ ASL_DATA_INSTALLED = @ASL_DATA_INSTALLED@ ASL_DEPENDENCIES = @ASL_DEPENDENCIES@ ASL_LIBS = @ASL_LIBS@ ASL_LIBS_INSTALLED = @ASL_LIBS_INSTALLED@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUX_DIR = @AUX_DIR@ AWK = @AWK@ BUILDTOOLSDIR = @BUILDTOOLSDIR@ CBCGENERIC_CFLAGS = @CBCGENERIC_CFLAGS@ CBCGENERIC_CFLAGS_INSTALLED = @CBCGENERIC_CFLAGS_INSTALLED@ CBCGENERIC_DEPENDENCIES = @CBCGENERIC_DEPENDENCIES@ CBCGENERIC_LIBS = @CBCGENERIC_LIBS@ CBCGENERIC_LIBS_INSTALLED = @CBCGENERIC_LIBS_INSTALLED@ CBCGENERIC_PCLIBS = @CBCGENERIC_PCLIBS@ CBCGENERIC_PCREQUIRES = @CBCGENERIC_PCREQUIRES@ CBCLIB_CFLAGS = @CBCLIB_CFLAGS@ CBCLIB_CFLAGS_INSTALLED = @CBCLIB_CFLAGS_INSTALLED@ CBCLIB_DEPENDENCIES = @CBCLIB_DEPENDENCIES@ CBCLIB_LIBS = @CBCLIB_LIBS@ CBCLIB_LIBS_INSTALLED = @CBCLIB_LIBS_INSTALLED@ CBCLIB_PCLIBS = @CBCLIB_PCLIBS@ CBCLIB_PCREQUIRES = @CBCLIB_PCREQUIRES@ CBC_BUILD_CBC_GENERIC_FALSE = @CBC_BUILD_CBC_GENERIC_FALSE@ CBC_BUILD_CBC_GENERIC_TRUE = @CBC_BUILD_CBC_GENERIC_TRUE@ CBC_SVN_REV = @CBC_SVN_REV@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDEFS = @CDEFS@ CFLAGS = @CFLAGS@ CLP_CFLAGS = @CLP_CFLAGS@ CLP_CFLAGS_INSTALLED = @CLP_CFLAGS_INSTALLED@ CLP_DATA = @CLP_DATA@ CLP_DATA_INSTALLED = @CLP_DATA_INSTALLED@ CLP_DEPENDENCIES = @CLP_DEPENDENCIES@ CLP_LIBS = @CLP_LIBS@ CLP_LIBS_INSTALLED = @CLP_LIBS_INSTALLED@ COINDEPEND_CFLAGS = @COINDEPEND_CFLAGS@ COINDEPEND_CFLAGS_INSTALLED = @COINDEPEND_CFLAGS_INSTALLED@ COINDEPEND_DATA = @COINDEPEND_DATA@ COINDEPEND_DATA_INSTALLED = @COINDEPEND_DATA_INSTALLED@ COINDEPEND_DEPENDENCIES = @COINDEPEND_DEPENDENCIES@ COINDEPEND_LIBS = @COINDEPEND_LIBS@ COINDEPEND_LIBS_INSTALLED = @COINDEPEND_LIBS_INSTALLED@ COIN_CC_IS_CL_FALSE = @COIN_CC_IS_CL_FALSE@ COIN_CC_IS_CL_TRUE = @COIN_CC_IS_CL_TRUE@ COIN_CXX_IS_CL_FALSE = @COIN_CXX_IS_CL_FALSE@ COIN_CXX_IS_CL_TRUE = @COIN_CXX_IS_CL_TRUE@ COIN_HAS_ASL_FALSE = @COIN_HAS_ASL_FALSE@ COIN_HAS_ASL_TRUE = @COIN_HAS_ASL_TRUE@ COIN_HAS_CLP_FALSE = @COIN_HAS_CLP_FALSE@ COIN_HAS_CLP_TRUE = @COIN_HAS_CLP_TRUE@ COIN_HAS_COINDEPEND_FALSE = @COIN_HAS_COINDEPEND_FALSE@ COIN_HAS_COINDEPEND_TRUE = @COIN_HAS_COINDEPEND_TRUE@ COIN_HAS_CPX_FALSE = @COIN_HAS_CPX_FALSE@ COIN_HAS_CPX_TRUE = @COIN_HAS_CPX_TRUE@ COIN_HAS_DYLP_FALSE = @COIN_HAS_DYLP_FALSE@ COIN_HAS_DYLP_TRUE = @COIN_HAS_DYLP_TRUE@ COIN_HAS_GLPK_FALSE = @COIN_HAS_GLPK_FALSE@ COIN_HAS_GLPK_TRUE = @COIN_HAS_GLPK_TRUE@ COIN_HAS_GRB_FALSE = @COIN_HAS_GRB_FALSE@ COIN_HAS_GRB_TRUE = @COIN_HAS_GRB_TRUE@ COIN_HAS_MIPLIB3_FALSE = @COIN_HAS_MIPLIB3_FALSE@ COIN_HAS_MIPLIB3_TRUE = @COIN_HAS_MIPLIB3_TRUE@ COIN_HAS_MSK_FALSE = @COIN_HAS_MSK_FALSE@ COIN_HAS_MSK_TRUE = @COIN_HAS_MSK_TRUE@ COIN_HAS_NETLIB_FALSE = @COIN_HAS_NETLIB_FALSE@ COIN_HAS_NETLIB_TRUE = @COIN_HAS_NETLIB_TRUE@ COIN_HAS_OSITESTS_FALSE = @COIN_HAS_OSITESTS_FALSE@ COIN_HAS_OSITESTS_TRUE = @COIN_HAS_OSITESTS_TRUE@ COIN_HAS_PKGCONFIG_FALSE = @COIN_HAS_PKGCONFIG_FALSE@ COIN_HAS_PKGCONFIG_TRUE = @COIN_HAS_PKGCONFIG_TRUE@ COIN_HAS_SAMPLE_FALSE = @COIN_HAS_SAMPLE_FALSE@ COIN_HAS_SAMPLE_TRUE = @COIN_HAS_SAMPLE_TRUE@ COIN_HAS_SPX_FALSE = @COIN_HAS_SPX_FALSE@ COIN_HAS_SPX_TRUE = @COIN_HAS_SPX_TRUE@ COIN_HAS_VOL_FALSE = @COIN_HAS_VOL_FALSE@ COIN_HAS_VOL_TRUE = @COIN_HAS_VOL_TRUE@ COIN_HAS_XPR_FALSE = @COIN_HAS_XPR_FALSE@ COIN_HAS_XPR_TRUE = @COIN_HAS_XPR_TRUE@ COIN_PKG_CONFIG_PATH = @COIN_PKG_CONFIG_PATH@ COIN_PKG_CONFIG_PATH_UNINSTALLED = @COIN_PKG_CONFIG_PATH_UNINSTALLED@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPX_CFLAGS = @CPX_CFLAGS@ CPX_CFLAGS_INSTALLED = @CPX_CFLAGS_INSTALLED@ CPX_DATA = @CPX_DATA@ CPX_DATA_INSTALLED = @CPX_DATA_INSTALLED@ CPX_DEPENDENCIES = @CPX_DEPENDENCIES@ CPX_LIBS = @CPX_LIBS@ CPX_LIBS_INSTALLED = @CPX_LIBS_INSTALLED@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEFS = @CXXDEFS@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBG_CFLAGS = @DBG_CFLAGS@ DBG_CXXFLAGS = @DBG_CXXFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DEPENDENCY_LINKING_FALSE = @DEPENDENCY_LINKING_FALSE@ DEPENDENCY_LINKING_TRUE = @DEPENDENCY_LINKING_TRUE@ DYLP_CFLAGS = @DYLP_CFLAGS@ DYLP_CFLAGS_INSTALLED = @DYLP_CFLAGS_INSTALLED@ DYLP_DATA = @DYLP_DATA@ DYLP_DATA_INSTALLED = @DYLP_DATA_INSTALLED@ DYLP_DEPENDENCIES = @DYLP_DEPENDENCIES@ DYLP_LIBS = @DYLP_LIBS@ DYLP_LIBS_INSTALLED = @DYLP_LIBS_INSTALLED@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GLPK_CFLAGS = @GLPK_CFLAGS@ GLPK_CFLAGS_INSTALLED = @GLPK_CFLAGS_INSTALLED@ GLPK_DATA = @GLPK_DATA@ GLPK_DATA_INSTALLED = @GLPK_DATA_INSTALLED@ GLPK_DEPENDENCIES = @GLPK_DEPENDENCIES@ GLPK_LIBS = @GLPK_LIBS@ GLPK_LIBS_INSTALLED = @GLPK_LIBS_INSTALLED@ GRB_CFLAGS = @GRB_CFLAGS@ GRB_CFLAGS_INSTALLED = @GRB_CFLAGS_INSTALLED@ GRB_DATA = @GRB_DATA@ GRB_DATA_INSTALLED = @GRB_DATA_INSTALLED@ GRB_DEPENDENCIES = @GRB_DEPENDENCIES@ GRB_LIBS = @GRB_LIBS@ GRB_LIBS_INSTALLED = @GRB_LIBS_INSTALLED@ HAVE_EXTERNALS_FALSE = @HAVE_EXTERNALS_FALSE@ HAVE_EXTERNALS_TRUE = @HAVE_EXTERNALS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBEXT = @LIBEXT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOLM4 = @LIBTOOLM4@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_LDFLAGS = @LT_LDFLAGS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MIPLIB3_CFLAGS = @MIPLIB3_CFLAGS@ MIPLIB3_CFLAGS_INSTALLED = @MIPLIB3_CFLAGS_INSTALLED@ MIPLIB3_DATA = @MIPLIB3_DATA@ MIPLIB3_DATA_INSTALLED = @MIPLIB3_DATA_INSTALLED@ MIPLIB3_DEPENDENCIES = @MIPLIB3_DEPENDENCIES@ MIPLIB3_LIBS = @MIPLIB3_LIBS@ MIPLIB3_LIBS_INSTALLED = @MIPLIB3_LIBS_INSTALLED@ MPICC = @MPICC@ MPICXX = @MPICXX@ MSK_CFLAGS = @MSK_CFLAGS@ MSK_CFLAGS_INSTALLED = @MSK_CFLAGS_INSTALLED@ MSK_DATA = @MSK_DATA@ MSK_DATA_INSTALLED = @MSK_DATA_INSTALLED@ MSK_DEPENDENCIES = @MSK_DEPENDENCIES@ MSK_LIBS = @MSK_LIBS@ MSK_LIBS_INSTALLED = @MSK_LIBS_INSTALLED@ NETLIB_CFLAGS = @NETLIB_CFLAGS@ NETLIB_CFLAGS_INSTALLED = @NETLIB_CFLAGS_INSTALLED@ NETLIB_DATA = @NETLIB_DATA@ NETLIB_DATA_INSTALLED = @NETLIB_DATA_INSTALLED@ NETLIB_DEPENDENCIES = @NETLIB_DEPENDENCIES@ NETLIB_LIBS = @NETLIB_LIBS@ NETLIB_LIBS_INSTALLED = @NETLIB_LIBS_INSTALLED@ OBJEXT = @OBJEXT@ OPT_CFLAGS = @OPT_CFLAGS@ OPT_CXXFLAGS = @OPT_CXXFLAGS@ OSICBC_DFLT_SOLVER_CLP_FALSE = @OSICBC_DFLT_SOLVER_CLP_FALSE@ OSICBC_DFLT_SOLVER_CLP_TRUE = @OSICBC_DFLT_SOLVER_CLP_TRUE@ OSICBC_DFLT_SOLVER_CPX_FALSE = @OSICBC_DFLT_SOLVER_CPX_FALSE@ OSICBC_DFLT_SOLVER_CPX_TRUE = @OSICBC_DFLT_SOLVER_CPX_TRUE@ OSICBC_DFLT_SOLVER_DYLP_FALSE = @OSICBC_DFLT_SOLVER_DYLP_FALSE@ OSICBC_DFLT_SOLVER_DYLP_TRUE = @OSICBC_DFLT_SOLVER_DYLP_TRUE@ OSICBC_DFLT_SOLVER_GLPK_FALSE = @OSICBC_DFLT_SOLVER_GLPK_FALSE@ OSICBC_DFLT_SOLVER_GLPK_TRUE = @OSICBC_DFLT_SOLVER_GLPK_TRUE@ OSICBC_DFLT_SOLVER_GRB_FALSE = @OSICBC_DFLT_SOLVER_GRB_FALSE@ OSICBC_DFLT_SOLVER_GRB_TRUE = @OSICBC_DFLT_SOLVER_GRB_TRUE@ OSICBC_DFLT_SOLVER_MSK_FALSE = @OSICBC_DFLT_SOLVER_MSK_FALSE@ OSICBC_DFLT_SOLVER_MSK_TRUE = @OSICBC_DFLT_SOLVER_MSK_TRUE@ OSICBC_DFLT_SOLVER_SPX_FALSE = @OSICBC_DFLT_SOLVER_SPX_FALSE@ OSICBC_DFLT_SOLVER_SPX_TRUE = @OSICBC_DFLT_SOLVER_SPX_TRUE@ OSICBC_DFLT_SOLVER_SYM_FALSE = @OSICBC_DFLT_SOLVER_SYM_FALSE@ OSICBC_DFLT_SOLVER_SYM_TRUE = @OSICBC_DFLT_SOLVER_SYM_TRUE@ OSICBC_DFLT_SOLVER_VOL_FALSE = @OSICBC_DFLT_SOLVER_VOL_FALSE@ OSICBC_DFLT_SOLVER_VOL_TRUE = @OSICBC_DFLT_SOLVER_VOL_TRUE@ OSICBC_DFLT_SOLVER_XPR_FALSE = @OSICBC_DFLT_SOLVER_XPR_FALSE@ OSICBC_DFLT_SOLVER_XPR_TRUE = @OSICBC_DFLT_SOLVER_XPR_TRUE@ OSITESTS_CFLAGS = @OSITESTS_CFLAGS@ OSITESTS_CFLAGS_INSTALLED = @OSITESTS_CFLAGS_INSTALLED@ OSITESTS_DATA = @OSITESTS_DATA@ OSITESTS_DATA_INSTALLED = @OSITESTS_DATA_INSTALLED@ OSITESTS_DEPENDENCIES = @OSITESTS_DEPENDENCIES@ OSITESTS_LIBS = @OSITESTS_LIBS@ OSITESTS_LIBS_INSTALLED = @OSITESTS_LIBS_INSTALLED@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ RPATH_FLAGS = @RPATH_FLAGS@ SAMPLE_CFLAGS = @SAMPLE_CFLAGS@ SAMPLE_CFLAGS_INSTALLED = @SAMPLE_CFLAGS_INSTALLED@ SAMPLE_DATA = @SAMPLE_DATA@ SAMPLE_DATA_INSTALLED = @SAMPLE_DATA_INSTALLED@ SAMPLE_DEPENDENCIES = @SAMPLE_DEPENDENCIES@ SAMPLE_LIBS = @SAMPLE_LIBS@ SAMPLE_LIBS_INSTALLED = @SAMPLE_LIBS_INSTALLED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPX_CFLAGS = @SPX_CFLAGS@ SPX_CFLAGS_INSTALLED = @SPX_CFLAGS_INSTALLED@ SPX_DATA = @SPX_DATA@ SPX_DATA_INSTALLED = @SPX_DATA_INSTALLED@ SPX_DEPENDENCIES = @SPX_DEPENDENCIES@ SPX_LIBS = @SPX_LIBS@ SPX_LIBS_INSTALLED = @SPX_LIBS_INSTALLED@ STRIP = @STRIP@ VERSION = @VERSION@ VOL_CFLAGS = @VOL_CFLAGS@ VOL_CFLAGS_INSTALLED = @VOL_CFLAGS_INSTALLED@ VOL_DATA = @VOL_DATA@ VOL_DATA_INSTALLED = @VOL_DATA_INSTALLED@ VOL_DEPENDENCIES = @VOL_DEPENDENCIES@ VOL_LIBS = @VOL_LIBS@ VOL_LIBS_INSTALLED = @VOL_LIBS_INSTALLED@ VPATH_DISTCLEANFILES = @VPATH_DISTCLEANFILES@ XPR_CFLAGS = @XPR_CFLAGS@ XPR_CFLAGS_INSTALLED = @XPR_CFLAGS_INSTALLED@ XPR_DATA = @XPR_DATA@ XPR_DATA_INSTALLED = @XPR_DATA_INSTALLED@ XPR_DEPENDENCIES = @XPR_DEPENDENCIES@ XPR_LIBS = @XPR_LIBS@ XPR_LIBS_INSTALLED = @XPR_LIBS_INSTALLED@ abs_bin_dir = @abs_bin_dir@ abs_include_dir = @abs_include_dir@ abs_lib_dir = @abs_lib_dir@ abs_source_dir = @abs_source_dir@ ac_c_preproc_warn_flag = @ac_c_preproc_warn_flag@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ ac_ct_PKG_CONFIG = @ac_ct_PKG_CONFIG@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_cxx_preproc_warn_flag = @ac_cxx_preproc_warn_flag@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ coin_doxy_excludes = @coin_doxy_excludes@ coin_doxy_logname = @coin_doxy_logname@ coin_doxy_tagfiles = @coin_doxy_tagfiles@ coin_doxy_tagname = @coin_doxy_tagname@ coin_doxy_usedot = @coin_doxy_usedot@ coin_have_doxygen = @coin_have_doxygen@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_autoconf = @have_autoconf@ have_automake = @have_automake@ have_svn = @have_svn@ have_svnversion = @have_svnversion@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sol_cc_compiler = @sol_cc_compiler@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AUTOMAKE_OPTIONS = foreign ######################################################################## # libCbc # ######################################################################## # Name of the library compiled in this directory. We want it to be installed # in the 'lib' directory lib_LTLIBRARIES = libCbc.la libCbcSolver.la # List all source files for this library, including headers libCbc_la_SOURCES = \ CbcConfig.h \ CbcBranchActual.hpp \ CbcBranchAllDifferent.cpp CbcBranchAllDifferent.hpp \ CbcBranchBase.hpp \ CbcBranchCut.cpp CbcBranchCut.hpp \ CbcBranchDecision.cpp CbcBranchDecision.hpp \ CbcBranchDefaultDecision.cpp CbcBranchDefaultDecision.hpp \ CbcBranchDynamic.cpp CbcBranchDynamic.hpp \ CbcBranchingObject.cpp CbcBranchingObject.hpp \ CbcBranchLotsize.cpp CbcBranchLotsize.hpp \ CbcBranchToFixLots.cpp CbcBranchToFixLots.hpp \ CbcCompareActual.hpp \ CbcCompareBase.hpp \ CbcCompareDefault.cpp CbcCompareDefault.hpp \ CbcCompareDepth.cpp CbcCompareDepth.hpp \ CbcCompareEstimate.cpp CbcCompareEstimate.hpp \ CbcCompareObjective.cpp CbcCompareObjective.hpp \ CbcConsequence.cpp CbcConsequence.hpp \ CbcClique.cpp CbcClique.hpp \ CbcCompare.hpp \ CbcCountRowCut.cpp CbcCountRowCut.hpp \ CbcCutGenerator.cpp CbcCutGenerator.hpp \ CbcCutModifier.cpp CbcCutModifier.hpp \ CbcCutSubsetModifier.cpp CbcCutSubsetModifier.hpp \ CbcDummyBranchingObject.cpp CbcDummyBranchingObject.hpp \ CbcEventHandler.cpp CbcEventHandler.hpp \ CbcFathom.cpp CbcFathom.hpp \ CbcFathomDynamicProgramming.cpp CbcFathomDynamicProgramming.hpp \ CbcFeasibilityBase.hpp \ CbcFixVariable.cpp CbcFixVariable.hpp \ CbcFullNodeInfo.cpp CbcFullNodeInfo.hpp \ CbcFollowOn.cpp CbcFollowOn.hpp \ CbcGeneral.cpp CbcGeneral.hpp \ CbcGeneralDepth.cpp CbcGeneralDepth.hpp \ CbcHeuristic.cpp CbcHeuristic.hpp \ CbcHeuristicDINS.cpp CbcHeuristicDINS.hpp \ CbcHeuristicDive.cpp CbcHeuristicDive.hpp \ CbcHeuristicDiveCoefficient.cpp CbcHeuristicDiveCoefficient.hpp \ CbcHeuristicDiveFractional.cpp CbcHeuristicDiveFractional.hpp \ CbcHeuristicDiveGuided.cpp CbcHeuristicDiveGuided.hpp \ CbcHeuristicDiveLineSearch.cpp CbcHeuristicDiveLineSearch.hpp \ CbcHeuristicDivePseudoCost.cpp CbcHeuristicDivePseudoCost.hpp \ CbcHeuristicDiveVectorLength.cpp CbcHeuristicDiveLength.hpp \ CbcHeuristicFPump.cpp CbcHeuristicFPump.hpp \ CbcHeuristicGreedy.cpp CbcHeuristicGreedy.hpp \ CbcHeuristicLocal.cpp CbcHeuristicLocal.hpp \ CbcHeuristicPivotAndFix.cpp CbcHeuristicPivotAndFix.hpp \ CbcHeuristicRandRound.cpp CbcHeuristicRandRound.hpp \ CbcHeuristicRENS.cpp CbcHeuristicRENS.hpp \ CbcHeuristicRINS.cpp CbcHeuristicRINS.hpp \ CbcHeuristicVND.cpp CbcHeuristicVND.hpp \ CbcMessage.cpp CbcMessage.hpp \ CbcModel.cpp CbcModel.hpp \ CbcNode.cpp CbcNode.hpp \ CbcNodeInfo.cpp CbcNodeInfo.hpp \ CbcNWay.cpp CbcNWay.hpp \ CbcObject.cpp CbcObject.hpp \ CbcObjectUpdateData.cpp CbcObjectUpdateData.hpp \ CbcPartialNodeInfo.cpp CbcPartialNodeInfo.hpp \ CbcSimpleInteger.cpp CbcSimpleInteger.hpp \ CbcSimpleIntegerDynamicPseudoCost.cpp \ CbcSimpleIntegerDynamicPseudoCost.hpp \ CbcSimpleIntegerPseudoCost.cpp \ CbcSimpleIntegerPseudoCost.hpp \ CbcSOS.cpp CbcSOS.hpp \ CbcStatistics.cpp CbcStatistics.hpp \ CbcStrategy.cpp CbcStrategy.hpp \ CbcSubProblem.cpp CbcSubProblem.hpp \ CbcThread.cpp CbcThread.hpp \ CbcTree.cpp CbcTree.hpp \ CbcTreeLocal.cpp CbcTreeLocal.hpp libCbcSolver_la_SOURCES = \ Cbc_C_Interface.cpp Cbc_C_Interface.h \ CbcCbcParam.cpp \ Cbc_ampl.cpp Cbc_ampl.h \ CbcLinked.cpp CbcLinked.hpp CbcLinkedUtils.cpp \ unitTestClp.cpp CbcSolver.cpp \ CbcSolverHeuristics.cpp CbcSolverHeuristics.hpp \ CbcSolverAnalyze.cpp CbcSolverAnalyze.hpp \ CbcMipStartIO.cpp CbcMipStartIO.hpp \ CbcSolverExpandKnapsack.cpp CbcSolverExpandKnapsack.hpp # List all additionally required libraries @DEPENDENCY_LINKING_TRUE@libCbc_la_LIBADD = $(CBCLIB_LIBS) @DEPENDENCY_LINKING_TRUE@libCbcSolver_la_LIBADD = $(CBCLIB_LIBS) libCbc.la # This is for libtool libCbc_la_LDFLAGS = $(LT_LDFLAGS) libCbcSolver_la_LDFLAGS = $(LT_LDFLAGS) ######################################################################## # Additional flags # ######################################################################## # List additional defines AM_CPPFLAGS = $(COINDEPEND_CFLAGS) $(CLP_CFLAGS) $(CPX_CFLAGS) \ $(ASL_CFLAGS) $(am__append_3) -DCOIN_NO_CLP_MESSAGE \ -DUSE_CBCCONFIG # List all source files for this executable, including headers @COIN_HAS_CLP_TRUE@cbc_SOURCES = CoinSolve.cpp # Additional libraries @COIN_HAS_CLP_TRUE@cbc_LDADD = libCbcSolver.la libCbc.la $(CBCLIB_LIBS) $(ASL_LIBS) @COIN_HAS_CLP_TRUE@cbc_DEPENDENCIES = libCbcSolver.la libCbc.la $(CBCLIB_DEPENDENCIES) $(ASL_DEPENDENCIES) # List all source files for this executable, including headers @CBC_BUILD_CBC_GENERIC_TRUE@cbc_generic_SOURCES = \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenBaB.cpp \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenCbcParam.cpp CbcGenCbcParam.hpp CbcGenCbcParamUtils.cpp \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenCtlBlk.cpp CbcGenCtlBlk.hpp \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGeneric.cpp \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenMessages.cpp CbcGenMessages.hpp \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenOsiParam.cpp CbcGenOsiParam.hpp CbcGenOsiParamUtils.cpp \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenParam.cpp CbcGenParam.hpp CbcGenParamUtils.cpp \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenSolution.cpp \ @CBC_BUILD_CBC_GENERIC_TRUE@ CbcGenSolvers.cpp @CBC_BUILD_CBC_GENERIC_TRUE@cbc_generic_LDADD = libCbcSolver.la libCbc.la $(CBCGENERIC_LIBS) @CBC_BUILD_CBC_GENERIC_TRUE@cbc_generic_DEPENDENCIES = libCbcSolver.la libCbc.la $(CBCGENERIC_DEPENDENCIES) # This line is necessary to allow VPATH compilation DEFAULT_INCLUDES = -I. -I`$(CYGPATH_W) $(srcdir)` -I$(top_builddir)/src ######################################################################## # Headers that need to be installed # ######################################################################## # Here list all the header files that are required by a user of the library, # and that therefore should be installed in 'include/coin' includecoindir = $(includedir)/coin includecoin_HEADERS = \ Cbc_C_Interface.h \ CbcBranchActual.hpp \ CbcBranchAllDifferent.hpp \ CbcBranchBase.hpp \ CbcBranchDynamic.hpp \ CbcBranchCut.hpp \ CbcBranchDecision.hpp \ CbcBranchDefaultDecision.hpp \ CbcBranchingObject.hpp \ CbcBranchLotsize.hpp \ CbcBranchToFixLots.hpp \ CbcCompareActual.hpp \ CbcCompareBase.hpp \ CbcCompareDefault.hpp \ CbcCompareDepth.hpp \ CbcCompareEstimate.hpp \ CbcCompareObjective.hpp \ CbcConsequence.hpp \ CbcClique.hpp \ CbcCompare.hpp \ CbcCountRowCut.hpp \ CbcCutGenerator.hpp \ CbcCutModifier.hpp \ CbcCutSubsetModifier.hpp \ CbcDummyBranchingObject.hpp \ CbcFathom.hpp \ CbcEventHandler.hpp \ CbcFathomDynamicProgramming.hpp \ CbcFeasibilityBase.hpp \ CbcFixVariable.hpp \ CbcFollowOn.hpp \ CbcFullNodeInfo.hpp \ CbcGeneral.hpp \ CbcGeneralDepth.hpp \ CbcHeuristic.hpp \ CbcHeuristicDINS.hpp \ CbcHeuristicDive.hpp \ CbcHeuristicDiveCoefficient.hpp \ CbcHeuristicDiveFractional.hpp \ CbcHeuristicDiveGuided.hpp \ CbcHeuristicDiveLineSearch.hpp \ CbcHeuristicDivePseudoCost.hpp \ CbcHeuristicDiveVectorLength.hpp \ CbcHeuristicFPump.hpp \ CbcHeuristicGreedy.hpp \ CbcHeuristicLocal.hpp \ CbcHeuristicPivotAndFix.hpp \ CbcHeuristicRandRound.hpp \ CbcHeuristicRENS.hpp \ CbcHeuristicRINS.hpp \ CbcHeuristicVND.hpp \ CbcMessage.hpp \ CbcModel.hpp \ CbcNode.hpp \ CbcNodeInfo.hpp \ CbcNWay.hpp \ CbcObject.hpp \ CbcObjectUpdateData.hpp \ CbcPartialNodeInfo.hpp \ CbcSimpleInteger.hpp \ CbcSimpleIntegerDynamicPseudoCost.hpp \ CbcSimpleIntegerPseudoCost.hpp \ CbcStrategy.hpp \ CbcSolver.hpp \ CbcMipStartIO.hpp \ CbcSOS.hpp \ CbcSubProblem.hpp \ CbcTree.hpp \ CbcLinked.hpp \ CbcTreeLocal.hpp \ ClpConstraintAmpl.hpp \ ClpAmplObjective.hpp all: config.h config_cbc.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status src/config.h $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_srcdir) && $(AUTOHEADER) rm -f stamp-h1 touch $@ config_cbc.h: stamp-h2 @if test ! -f $@; then \ rm -f stamp-h2; \ $(MAKE) stamp-h2; \ else :; fi stamp-h2: $(srcdir)/config_cbc.h.in $(top_builddir)/config.status @rm -f stamp-h2 cd $(top_builddir) && $(SHELL) ./config.status src/config_cbc.h distclean-hdr: -rm -f config.h stamp-h1 config_cbc.h stamp-h2 install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ else :; fi; \ done uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libCbc.la: $(libCbc_la_OBJECTS) $(libCbc_la_DEPENDENCIES) $(CXXLINK) -rpath $(libdir) $(libCbc_la_LDFLAGS) $(libCbc_la_OBJECTS) $(libCbc_la_LIBADD) $(LIBS) libCbcSolver.la: $(libCbcSolver_la_OBJECTS) $(libCbcSolver_la_DEPENDENCIES) $(CXXLINK) -rpath $(libdir) $(libCbcSolver_la_LDFLAGS) $(libCbcSolver_la_OBJECTS) $(libCbcSolver_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done cbc$(EXEEXT): $(cbc_OBJECTS) $(cbc_DEPENDENCIES) @rm -f cbc$(EXEEXT) $(CXXLINK) $(cbc_LDFLAGS) $(cbc_OBJECTS) $(cbc_LDADD) $(LIBS) cbc-generic$(EXEEXT): $(cbc_generic_OBJECTS) $(cbc_generic_DEPENDENCIES) @rm -f cbc-generic$(EXEEXT) $(CXXLINK) $(cbc_generic_LDFLAGS) $(cbc_generic_OBJECTS) $(cbc_generic_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcBranchAllDifferent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcBranchCut.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcBranchDecision.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcBranchDefaultDecision.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcBranchDynamic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcBranchLotsize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcBranchToFixLots.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcBranchingObject.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcCbcParam.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcClique.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcCompareDefault.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcCompareDepth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcCompareEstimate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcCompareObjective.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcConsequence.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcCountRowCut.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcCutGenerator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcCutModifier.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcCutSubsetModifier.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcDummyBranchingObject.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcEventHandler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcFathom.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcFathomDynamicProgramming.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcFixVariable.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcFollowOn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcFullNodeInfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenBaB.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenCbcParam.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenCbcParamUtils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenCtlBlk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenMessages.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenOsiParam.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenOsiParamUtils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenParam.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenParamUtils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenSolution.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGenSolvers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGeneral.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGeneralDepth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcGeneric.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicDINS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicDive.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicDiveCoefficient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicDiveFractional.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicDiveGuided.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicDiveLineSearch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicDivePseudoCost.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicDiveVectorLength.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicFPump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicGreedy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicLocal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicPivotAndFix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicRENS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicRINS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicRandRound.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcHeuristicVND.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcLinked.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcLinkedUtils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcMessage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcMipStartIO.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcModel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcNWay.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcNodeInfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcObject.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcObjectUpdateData.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcPartialNodeInfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcSOS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcSimpleInteger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcSimpleIntegerDynamicPseudoCost.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcSimpleIntegerPseudoCost.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcSolver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcSolverAnalyze.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcSolverExpandKnapsack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcSolverHeuristics.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcStatistics.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcStrategy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcSubProblem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcTree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcTreeLocal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Cbc_C_Interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Cbc_ampl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinSolve.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unitTestClp.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: install-includecoinHEADERS: $(includecoin_HEADERS) @$(NORMAL_INSTALL) test -z "$(includecoindir)" || $(mkdir_p) "$(DESTDIR)$(includecoindir)" @list='$(includecoin_HEADERS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(includecoinHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includecoindir)/$$f'"; \ $(includecoinHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includecoindir)/$$f"; \ done uninstall-includecoinHEADERS: @$(NORMAL_UNINSTALL) @list='$(includecoin_HEADERS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(includecoindir)/$$f'"; \ rm -f "$(DESTDIR)$(includecoindir)/$$f"; \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) config.h.in config_cbc.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in config_cbc.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) config.h.in config_cbc.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in config_cbc.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) config.h \ config_cbc.h install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includecoindir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @COIN_CXX_IS_CL_FALSE@install-exec-hook: clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-includecoinHEADERS install-exec-am: install-binPROGRAMS install-exec-local \ install-libLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-includecoinHEADERS \ uninstall-info-am uninstall-libLTLIBRARIES uninstall-local .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libLTLIBRARIES clean-libtool ctags \ distclean distclean-compile distclean-generic distclean-hdr \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-exec install-exec-am \ install-exec-hook install-exec-local \ install-includecoinHEADERS install-info install-info-am \ install-libLTLIBRARIES install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-includecoinHEADERS uninstall-info-am \ uninstall-libLTLIBRARIES uninstall-local ######################################################################## # Installing manifest (MSVC++) # ######################################################################## @COIN_CXX_IS_CL_TRUE@install-exec-hook: @COIN_CXX_IS_CL_TRUE@ test -s cbc.exe.manifest && \ @COIN_CXX_IS_CL_TRUE@ mt -manifest cbc.exe.manifest -outputresource:cbc.exe;\ @COIN_CXX_IS_CL_TRUE@ cp cbc.exe $(bindir)/cbc.exe ####################################################################### # Create the Config.h file that has all public defines and install it # ####################################################################### install-exec-local: $(install_sh_DATA) config_cbc.h $(DESTDIR)$(includecoindir)/CbcConfig.h uninstall-local: rm -f $(DESTDIR)$(includecoindir)/CbcConfig.h # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: Cbc-2.8.12/src/CbcBranchingObject.cpp0000644000076600007660000000341012131315050015663 0ustar coincoin// $Id: CbcBranchingObject.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/12/2009 carved from CbcBranchBase #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "OsiChooseVariable.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchBase.hpp" // Default Constructor CbcBranchingObject::CbcBranchingObject() : OsiBranchingObject() { model_ = NULL; originalCbcObject_ = NULL; variable_ = -1; way_ = 0; } // Useful constructor CbcBranchingObject::CbcBranchingObject (CbcModel * model, int variable, int way , double value) : OsiBranchingObject(model->solver(), value) { model_ = model; originalCbcObject_ = NULL; variable_ = variable; way_ = way; } // Copy constructor CbcBranchingObject::CbcBranchingObject ( const CbcBranchingObject & rhs) : OsiBranchingObject(rhs) { model_ = rhs.model_; originalCbcObject_ = rhs.originalCbcObject_; variable_ = rhs.variable_; way_ = rhs.way_; value_ = rhs.value_; } // Assignment operator CbcBranchingObject & CbcBranchingObject::operator=( const CbcBranchingObject & rhs) { if (this != &rhs) { OsiBranchingObject::operator=(rhs); model_ = rhs.model_; originalCbcObject_ = rhs.originalCbcObject_; variable_ = rhs.variable_; way_ = rhs.way_; } return *this; } // Destructor CbcBranchingObject::~CbcBranchingObject () { } Cbc-2.8.12/src/CbcHeuristicVND.cpp0000644000076600007660000002373612131315050015165 0ustar coincoin// $Id: CbcHeuristicVND.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // edwin 12/5/09 carved out of CbcHeuristicRINS #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcHeuristicVND.hpp" #include "CbcBranchActual.hpp" #include "CbcStrategy.hpp" #include "CglPreProcess.hpp" // Default Constructor CbcHeuristicVND::CbcHeuristicVND() : CbcHeuristic() { numberSolutions_ = 0; numberSuccesses_ = 0; numberTries_ = 0; lastNode_ = -999999; howOften_ = 100; decayFactor_ = 0.5; baseSolution_ = NULL; whereFrom_ = 1 + 8 + 255 * 256; stepSize_ = 0; k_ = 0; kmax_ = 0; nDifferent_ = 0; } // Constructor with model - assumed before cuts CbcHeuristicVND::CbcHeuristicVND(CbcModel & model) : CbcHeuristic(model) { numberSolutions_ = 0; numberSuccesses_ = 0; numberTries_ = 0; lastNode_ = -999999; howOften_ = 100; decayFactor_ = 0.5; assert(model.solver()); int numberColumns = model.solver()->getNumCols(); baseSolution_ = new double [numberColumns]; memset(baseSolution_, 0, numberColumns*sizeof(double)); whereFrom_ = 1 + 8 + 255 * 256; stepSize_ = 0; k_ = 0; kmax_ = 0; nDifferent_ = 0; } // Destructor CbcHeuristicVND::~CbcHeuristicVND () { delete [] baseSolution_; } // Clone CbcHeuristic * CbcHeuristicVND::clone() const { return new CbcHeuristicVND(*this); } // Assignment operator CbcHeuristicVND & CbcHeuristicVND::operator=( const CbcHeuristicVND & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); numberSolutions_ = rhs.numberSolutions_; howOften_ = rhs.howOften_; numberSuccesses_ = rhs.numberSuccesses_; numberTries_ = rhs.numberTries_; lastNode_ = rhs.lastNode_; delete [] baseSolution_; if (model_ && rhs.baseSolution_) { int numberColumns = model_->solver()->getNumCols(); baseSolution_ = new double [numberColumns]; memcpy(baseSolution_, rhs.baseSolution_, numberColumns*sizeof(double)); } else { baseSolution_ = NULL; } stepSize_ = rhs.stepSize_; k_ = rhs.k_; kmax_ = rhs.kmax_; nDifferent_ = rhs.nDifferent_; } return *this; } // Create C++ lines to get to current state void CbcHeuristicVND::generateCpp( FILE * fp) { CbcHeuristicVND other; fprintf(fp, "0#include \"CbcHeuristicVND.hpp\"\n"); fprintf(fp, "3 CbcHeuristicVND heuristicVND(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicVND"); if (howOften_ != other.howOften_) fprintf(fp, "3 heuristicVND.setHowOften(%d);\n", howOften_); else fprintf(fp, "4 heuristicVND.setHowOften(%d);\n", howOften_); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicVND);\n"); } // Copy constructor CbcHeuristicVND::CbcHeuristicVND(const CbcHeuristicVND & rhs) : CbcHeuristic(rhs), numberSolutions_(rhs.numberSolutions_), howOften_(rhs.howOften_), numberSuccesses_(rhs.numberSuccesses_), numberTries_(rhs.numberTries_), lastNode_(rhs.lastNode_) { if (model_ && rhs.baseSolution_) { int numberColumns = model_->solver()->getNumCols(); baseSolution_ = new double [numberColumns]; memcpy(baseSolution_, rhs.baseSolution_, numberColumns*sizeof(double)); } else { baseSolution_ = NULL; } stepSize_ = rhs.stepSize_; k_ = rhs.k_; kmax_ = rhs.kmax_; nDifferent_ = rhs.nDifferent_; } // Resets stuff if model changes void CbcHeuristicVND::resetModel(CbcModel * /*model*/) { //CbcHeuristic::resetModel(model); delete [] baseSolution_; if (model_ && baseSolution_) { int numberColumns = model_->solver()->getNumCols(); baseSolution_ = new double [numberColumns]; memset(baseSolution_, 0, numberColumns*sizeof(double)); } else { baseSolution_ = NULL; } } /* First tries setting a variable to better value. If feasible then tries setting others. If not feasible then tries swaps Returns 1 if solution, 0 if not */ int CbcHeuristicVND::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; int returnCode = 0; const double * bestSolution = model_->bestSolution(); if (!bestSolution) return 0; // No solution found yet if (numberSolutions_ < model_->getSolutionCount()) { // new solution - add info numberSolutions_ = model_->getSolutionCount(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double value = bestSolution[iColumn]; if (value < originalLower) { value = originalLower; } else if (value > originalUpper) { value = originalUpper; } } } int numberNodes = model_->getNodeCount(); if (howOften_ == 100) { if (numberNodes < lastNode_ + 12) return 0; // Do at 50 and 100 if ((numberNodes > 40 && numberNodes <= 50) || (numberNodes > 90 && numberNodes < 100)) numberNodes = howOften_; } if ((numberNodes % howOften_) == 0 && (model_->getCurrentPassNumber() == 1 || model_->getCurrentPassNumber() == 999999)) { lastNode_ = model_->getNodeCount(); OsiSolverInterface * solver = model_->solver(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double * currentSolution = solver->getColSolution(); OsiSolverInterface * newSolver = cloneBut(3); // was model_->continuousSolver()->clone(); //const double * colLower = newSolver->getColLower(); //const double * colUpper = newSolver->getColUpper(); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // Sort on distance double * distance = new double [numberIntegers]; int * which = new int [numberIntegers]; int i; int nFix = 0; double tolerance = 10.0 * primalTolerance; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double valueInt = bestSolution[iColumn]; if (valueInt < originalLower) { valueInt = originalLower; } else if (valueInt > originalUpper) { valueInt = originalUpper; } baseSolution_[iColumn] = currentSolution[iColumn]; distance[i] = fabs(currentSolution[iColumn] - valueInt); which[i] = i; if (fabs(currentSolution[iColumn] - valueInt) < tolerance) nFix++; } CoinSort_2(distance, distance + numberIntegers, which); nDifferent_ = numberIntegers - nFix; stepSize_ = nDifferent_ / 10; k_ = stepSize_; //nFix = numberIntegers-stepSize_; for (i = 0; i < nFix; i++) { int j = which[i]; int iColumn = integerVariable[j]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double valueInt = bestSolution[iColumn]; if (valueInt < originalLower) { valueInt = originalLower; } else if (valueInt > originalUpper) { valueInt = originalUpper; } double nearest = floor(valueInt + 0.5); newSolver->setColLower(iColumn, nearest); newSolver->setColUpper(iColumn, nearest); } delete [] distance; delete [] which; if (nFix > numberIntegers / 5) { //printf("%d integers have samish value\n",nFix); returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicVND"); if (returnCode < 0) returnCode = 0; // returned on size else numRuns_++; if ((returnCode&1) != 0) numberSuccesses_++; //printf("return code %d",returnCode); if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; //printf("could add cut with %d elements (if all 0-1)\n",nFix); } else { //printf("\n"); } numberTries_++; if ((numberTries_ % 10) == 0 && numberSuccesses_*3 < numberTries_) howOften_ += static_cast (howOften_ * decayFactor_); } delete newSolver; } return returnCode; } // update model void CbcHeuristicVND::setModel(CbcModel * model) { model_ = model; // Get a copy of original matrix assert(model_->solver()); delete [] baseSolution_; int numberColumns = model->solver()->getNumCols(); baseSolution_ = new double [numberColumns]; memset(baseSolution_, 0, numberColumns*sizeof(double)); } Cbc-2.8.12/src/CoinSolve.cpp0000644000076600007660000002555611534210055014156 0ustar coincoin/* $Id: CoinSolve.cpp 1607 2011-03-04 16:15:41Z lou $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /*! \file CbcSolver.cpp \brief Main routine for the cbc stand-alone solver. */ #include "CbcConfig.h" #include "CoinPragma.hpp" #include "CbcModel.hpp" #include "OsiClpSolverInterface.hpp" /* We have the following compile-time symbols. CBC_OTHER_SOLVER CoinSolve.cpp, CbcSolver.[cpp,hpp], CbcModel.cpp A value of 1 says `cplex'. Other values not defined. The intent with cplex is to apply all of cbc's smarts at the root, then hand the problem over to cplex to finish. Cplex is not used as an alternate lp solver under cbc control. Usage in CbcModel is a fake; a small bit of code that's now `#if 0'. CLP_DEBUG_MALLOC This ties in with the functions clp_malloc, clp_free, and clp_memory, which are defined in CoinOslFactorization.cpp. (Right where you'd expect to find them, eh?). Looks to be a relatively nice debugging wrapper for standard C malloc. Calls standard C malloc/free directly if CLP_DEBUG_MALLOC is not defined. Worth consideration for breaking out as a separate utility. The hooks for new and delete defined here should be incorporated. Absolutely not thread safe --- lots of static variables. Hmmm ... is it still the case that standard C malloc and C++ new/delete do not play well together? 'Cause the hooks here for new and delete will not escape from this file. */ #if CBC_OTHER_SOLVER == 1 # ifndef COIN_HAS_CPX # error "Configuration did not detect cplex installation." # else # include "OsiCpxSolverInterface.hpp" # endif #endif /* Hooks for a debugging wrapper for malloc/free. This bit of definition hooks C++ new / delete and diverts them into the debugging wrapper. */ //#define CLP_DEBUG_MALLOC #ifdef CLP_DEBUG_MALLOC /*extern "C" */void clp_memory(int type); /*extern "C" */ void * clp_malloc(int length); /*extern "C" */ void clp_free(void * array); #include #include #include void * operator new (size_t size) throw (std::bad_alloc) { void * p = clp_malloc(size); return p; } void operator delete (void *p) throw() { clp_free(p); } #endif // CLP_DEBUG_MALLOC #include #include #include #include #include #include // define TEST_MESSAGE_HANDLER to check works on all messages // #define TEST_MESSAGE_HANDLER #ifdef TEST_MESSAGE_HANDLER // This driver shows how to trap messages - this is just as in unitTest.cpp // ****** THis code is similar to MyMessageHandler.hpp and MyMessagehandler.cpp #include "CoinMessageHandler.hpp" /** This just adds a model to CoinMessage and a void pointer so user can trap messages and do useful stuff. This is used in Clp/Test/unitTest.cpp The file pointer is just there as an example of user stuff. -- lh 071026 -- An accurate summary. Nothing is actually happening here except that messages will be prefixed with "==", which serves the purpose of demonstrating that this message handler is active. The extra parameters (CbcModel, FILE) are unused. */ class CbcModel; class MyMessageHandler2 : public CoinMessageHandler { public: /**@name Overrides */ //@{ virtual int print(); //@} /**@name set and get */ //@{ /// Model const CbcModel * model() const; void setModel(CbcModel * model); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ MyMessageHandler2(); /// Constructor with pointer to model MyMessageHandler2(CbcModel * model, FILE * userPointer = NULL); /** Destructor */ virtual ~MyMessageHandler2(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ MyMessageHandler2(const MyMessageHandler2&); /** The copy constructor from an CoinSimplexMessageHandler. */ MyMessageHandler2(const CoinMessageHandler&); MyMessageHandler2& operator=(const MyMessageHandler2&); /// Clone virtual CoinMessageHandler * clone() const ; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Pointer back to model CbcModel * model_; //@} }; //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- MyMessageHandler2::MyMessageHandler2 () : CoinMessageHandler(), model_(NULL) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- MyMessageHandler2::MyMessageHandler2 (const MyMessageHandler2 & rhs) : CoinMessageHandler(rhs), model_(rhs.model_) { } MyMessageHandler2::MyMessageHandler2 (const CoinMessageHandler & rhs) : CoinMessageHandler(), model_(NULL) { } // Constructor with pointer to model MyMessageHandler2::MyMessageHandler2(CbcModel * model, FILE * userPointer) : CoinMessageHandler(), model_(model) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- MyMessageHandler2::~MyMessageHandler2 () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- MyMessageHandler2 & MyMessageHandler2::operator=(const MyMessageHandler2 & rhs) { if (this != &rhs) { CoinMessageHandler::operator=(rhs); model_ = rhs.model_; } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- CoinMessageHandler * MyMessageHandler2::clone() const { return new MyMessageHandler2(*this); } int MyMessageHandler2::print() { // Just add == fprintf(fp_, " == "); fprintf(fp_, "%s\n", messageBuffer_); return 0; } const CbcModel * MyMessageHandler2::model() const { return model_; } void MyMessageHandler2::setModel(CbcModel * model) { model_ = model; } #endif /* TEST_MESSAGE_HANDLER */ //############################################################################# // To use USERCBC or USERCLP change 0 to 1 in defines and add in your fake main program(s) and any other code //#define USER_HAS_FAKE_CBC //#define USER_HAS_FAKE_CLP #ifdef USER_HAS_FAKE_CBC #endif void fakeMain (ClpSimplex & model, OsiSolverInterface & /*osiSolver*/, CbcModel & babSolver) { #ifdef USER_HAS_FAKE_CBC #else printf("Dummy user cbc code - model has %d rows and %d columns\n", model.getNumRows(), model.getNumCols()); // Reduce printout babSolver.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry); // Do complete search babSolver.branchAndBound(); #endif } // Clp stuff #ifdef USER_HAS_FAKE_CLP #endif void fakeMain2 (ClpSimplex & /*model*/, OsiClpSolverInterface & osiSolver, int /*options*/) { #ifdef USER_HAS_FAKE_CLP #else ClpSimplex * lpSolver = osiSolver.getModelPtr(); printf("Dummy user clp code - model has %d rows and %d columns\n", lpSolver->numberRows(), lpSolver->numberColumns()); osiSolver.initialSolve(); #endif } // End any fake main program //############################################################################# // void CbcClpUnitTest (const CbcModel & saveModel); #ifdef CBC_STATISTICS int osi_crunch = 0; static int cbc_resolve = 0; int osi_primal = 0; int osi_dual = 0; int osi_hot = 0; void cbc_resolve_check(const OsiSolverInterface * solver) { cbc_resolve++; printf("R %d stats %d %d %d\n", cbc_resolve, solver->getNumRows(), solver->getNumCols(), solver->getMatrixByCol()->getNumElements()); if ((cbc_resolve % 1000) == 0) printf("RR %d resolve crunch %d primal %d dual %d hot %d\n", cbc_resolve, osi_crunch, osi_primal, osi_dual, osi_hot); } #endif int main (int argc, const char *argv[]) { int returnCode = 0; #ifdef CLP_DEBUG_MALLOC clp_memory(0); #endif { #ifndef CBC_OTHER_SOLVER OsiClpSolverInterface solver1; #elif CBC_OTHER_SOLVER==1 OsiCpxSolverInterface solver1; #endif CbcModel model(solver1); // define TEST_MESSAGE_HANDLER at top of file to check works on all messages #ifdef TEST_MESSAGE_HANDLER MyMessageHandler2 messageHandler(&model); std::cout << "Testing derived message handler" << std::endl; model.passInMessageHandler(&messageHandler); OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model.solver()); // Could use different handlers (if different log levels) clpSolver->passInMessageHandler(&messageHandler); //clpSolver->getModelPtr()->passInMessageHandler(&messageHandler); #endif // initialize CbcMain0(model); #ifdef TEST_MESSAGE_HANDLER // Set log levels same so can use one message handler clpSolver->messageHandler()->setLogLevel(1) ; model.messageHandler()->setLogLevel(1); // switch off some printing void setCbcOrClpPrinting(bool yesNo); setCbcOrClpPrinting(false); #endif returnCode = CbcMain1 (argc, argv, model); } #ifdef CLP_DEBUG_MALLOC clp_memory(1); #endif if (returnCode != 777) { return returnCode; } else { return 0; } } /* Version 1.00.00 November 16 2005. This is to stop me (JJF) messing about too much. Tuning changes should be noted here. The testing next version may be activated by CBC_NEXT_VERSION This applies to OsiClp, Clp etc Version 1.00.01 November 24 2005 Added several classes for advanced users. This can't affect code (if you don't use it) Made some tiny changes (for N way branching) which should not change anything. CbcNWay object class - for N way branching this also allows use of CbcConsequence class. CbcBranchAllDifferent object class - for branching on general integer variables to stop them having same value so branches are x >= y+1 and x <= y-1. Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly) and CglStored which just has a list of cuts which can be activated. Modified preprocess option to SOS Version 1.00.02 December 9 2005 Added use of CbcStrategy to do clean preprocessing Added use of referenceSolver for cleaner repetition of Cbc Version 1.01.00 February 2 2006 Added first try at Ampl interface Made dummy program so real main can be called from other programs */ Cbc-2.8.12/src/CbcConfig.h0000644000076600007660000000253712101340057013526 0ustar coincoin/* Copyright (C) 2011 * All Rights Reserved. * This code is published under the Eclipse Public License. * * $Id: CbcConfig.h 1854 2013-01-28 00:02:55Z stefan $ * * Include file for the configuration of Cbc. * * On systems where the code is configured with the configure script * (i.e., compilation is always done with HAVE_CONFIG_H defined), this * header file includes the automatically generated header file, and * undefines macros that might configure with other Config.h files. * * On systems that are compiled in other ways (e.g., with the * Developer Studio), a header files is included to define those * macros that depend on the operating system and the compiler. The * macros that define the configuration of the particular user setting * (e.g., presence of other COIN-OR packages or third party code) are set * by the files config_*default.h. The project maintainer needs to remember * to update these file and choose reasonable defines. * A user can modify the default setting by editing the config_*default.h files. * */ #ifndef __CBCCONFIG_H__ #define __CBCCONFIG_H__ #ifdef HAVE_CONFIG_H #ifdef CBC_BUILD #include "config.h" #else #include "config_cbc.h" #endif #else /* HAVE_CONFIG_H */ #ifdef CBC_BUILD #include "config_default.h" #else #include "config_cbc_default.h" #endif #endif /* HAVE_CONFIG_H */ #endif /*__CBCCONFIG_H__*/ Cbc-2.8.12/src/CbcHeuristic.hpp0000644000076600007660000005434012130022033014610 0ustar coincoin/* $Id: CbcHeuristic.hpp 1883 2013-04-06 13:33:15Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristic_H #define CbcHeuristic_H #include #include #include "CoinPackedMatrix.hpp" #include "OsiCuts.hpp" #include "CoinHelperFunctions.hpp" #include "OsiBranchingObject.hpp" class OsiSolverInterface; class CbcModel; //############################################################################# class CbcHeuristicNodeList; class CbcBranchingObject; /** A class describing the branching decisions that were made to get to the node where a heuristic was invoked from */ class CbcHeuristicNode { private: void gutsOfConstructor(CbcModel& model); CbcHeuristicNode(); CbcHeuristicNode& operator=(const CbcHeuristicNode&); private: /// The number of branching decisions made int numObjects_; /** The indices of the branching objects. Note: an index may be listed multiple times. E.g., a general integer variable that has been branched on multiple times. */ CbcBranchingObject** brObj_; public: CbcHeuristicNode(CbcModel& model); CbcHeuristicNode(const CbcHeuristicNode& rhs); ~CbcHeuristicNode(); double distance(const CbcHeuristicNode* node) const; double minDistance(const CbcHeuristicNodeList& nodeList) const; bool minDistanceIsSmall(const CbcHeuristicNodeList& nodeList, const double threshold) const; double avgDistance(const CbcHeuristicNodeList& nodeList) const; }; class CbcHeuristicNodeList { private: void gutsOfDelete(); void gutsOfCopy(const CbcHeuristicNodeList& rhs); private: std::vector nodes_; public: CbcHeuristicNodeList() {} CbcHeuristicNodeList(const CbcHeuristicNodeList& rhs); CbcHeuristicNodeList& operator=(const CbcHeuristicNodeList& rhs); ~CbcHeuristicNodeList(); void append(CbcHeuristicNode*& node); void append(const CbcHeuristicNodeList& nodes); inline const CbcHeuristicNode* node(int i) const { return nodes_[i]; } inline int size() const { return static_cast(nodes_.size()); } }; //############################################################################# /** Heuristic base class */ class CbcHeuristic { private: void gutsOfDelete() {} void gutsOfCopy(const CbcHeuristic & rhs); public: // Default Constructor CbcHeuristic (); // Constructor with model - assumed before cuts CbcHeuristic (CbcModel & model); // Copy constructor CbcHeuristic ( const CbcHeuristic &); virtual ~CbcHeuristic(); /// Clone virtual CbcHeuristic * clone() const = 0; /// Assignment operator CbcHeuristic & operator=(const CbcHeuristic& rhs); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); /// Resets stuff if model changes virtual void resetModel(CbcModel * model) = 0; /** returns 0 if no solution, 1 if valid solution with better objective value than one passed in Sets solution values if good, sets objective value This is called after cuts have been added - so can not add cuts */ virtual int solution(double & objectiveValue, double * newSolution) = 0; /** returns 0 if no solution, 1 if valid solution, -1 if just returning an estimate of best possible solution with better objective value than one passed in Sets solution values if good, sets objective value (only if nonzero code) This is called at same time as cut generators - so can add cuts Default is do nothing */ virtual int solution2(double & /*objectiveValue*/, double * /*newSolution*/, OsiCuts & /*cs*/) { return 0; } /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) virtual void validate() {} /** Sets "when" flag - 0 off, 1 at root, 2 other than root, 3 always. If 10 added then don't worry if validate says there are funny objects as user knows it will be fine */ inline void setWhen(int value) { when_ = value; } /// Gets "when" flag - 0 off, 1 at root, 2 other than root, 3 always inline int when() const { return when_; } /// Sets number of nodes in subtree (default 200) inline void setNumberNodes(int value) { numberNodes_ = value; } /// Gets number of nodes in a subtree (default 200) inline int numberNodes() const { return numberNodes_; } /** Switches (does not apply equally to all heuristics) 1 bit - stop once allowable gap on objective reached 2 bit - always do given number of passes 4 bit - weaken cutoff by 5% every 50 passes? 8 bit - if has cutoff and suminf bobbling for 20 passes then first try halving distance to best possible then try keep halving distance to known cutoff 16 bit - needs new solution to run 1024 bit - stop all heuristics on max time */ inline void setSwitches(int value) { switches_ = value; } /** Switches (does not apply equally to all heuristics) 1 bit - stop once allowable gap on objective reached 2 bit - always do given number of passes 4 bit - weaken cutoff by 5% every 50 passes? 8 bit - if has cutoff and suminf bobbling for 20 passes then first try halving distance to best possible then try keep halving distance to known cutoff 16 bit - needs new solution to run 1024 bit - stop all heuristics on max time */ inline int switches() const { return switches_; } /// Whether to exit at once on gap bool exitNow(double bestObjective) const; /// Sets feasibility pump options (-1 is off) inline void setFeasibilityPumpOptions(int value) { feasibilityPumpOptions_ = value; } /// Gets feasibility pump options (-1 is off) inline int feasibilityPumpOptions() const { return feasibilityPumpOptions_; } /// Just set model - do not do anything else inline void setModelOnly(CbcModel * model) { model_ = model; } /// Sets fraction of new(rows+columns)/old(rows+columns) before doing small branch and bound (default 1.0) inline void setFractionSmall(double value) { fractionSmall_ = value; } /// Gets fraction of new(rows+columns)/old(rows+columns) before doing small branch and bound (default 1.0) inline double fractionSmall() const { return fractionSmall_; } /// Get how many solutions the heuristic thought it got inline int numberSolutionsFound() const { return numberSolutionsFound_; } /// Increment how many solutions the heuristic thought it got inline void incrementNumberSolutionsFound() { numberSolutionsFound_++; } /** Do mini branch and bound - return 0 not finished - no solution 1 not finished - solution 2 finished - no solution 3 finished - solution (could add global cut if finished) -1 returned on size -2 time or user event */ int smallBranchAndBound(OsiSolverInterface * solver, int numberNodes, double * newSolution, double & newSolutionValue, double cutoff , std::string name) const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * ) {} /// Create C++ lines to get to current state - does work for base class void generateCpp( FILE * fp, const char * heuristic) ; /// Returns true if can deal with "odd" problems e.g. sos type 2 virtual bool canDealWithOdd() const { return false; } /// return name of heuristic inline const char *heuristicName() const { return heuristicName_.c_str(); } /// set name of heuristic inline void setHeuristicName(const char *name) { heuristicName_ = name; } /// Set random number generator seed void setSeed(int value); /// Get random number generator seed int getSeed() const; /// Sets decay factor (for howOften) on failure inline void setDecayFactor(double value) { decayFactor_ = value; } /// Set input solution void setInputSolution(const double * solution, double objValue); /* Runs if bit set 0 - before cuts at root node (or from doHeuristics) 1 - during cuts at root 2 - after root node cuts 3 - after cuts at other nodes 4 - during cuts at other nodes 8 added if previous heuristic in loop found solution */ inline void setWhereFrom(int value) { whereFrom_ = value; } inline int whereFrom() const { return whereFrom_; } /** Upto this depth we call the tree shallow and the heuristic can be called multiple times. That is, the test whether the current node is far from the others where the jeuristic was invoked will not be done, only the frequency will be tested. After that depth the heuristic will can be invoked only once per node, right before branching. That's when it'll be tested whether the heur should run at all. */ inline void setShallowDepth(int value) { shallowDepth_ = value; } /** How often to invoke the heuristics in the shallow part of the tree */ inline void setHowOftenShallow(int value) { howOftenShallow_ = value; } /** How "far" should this node be from every other where the heuristic was run in order to allow the heuristic to run in this node, too. Currently this is tested, but we may switch to avgDistanceToRun_ in the future. */ inline void setMinDistanceToRun(int value) { minDistanceToRun_ = value; } /** Check whether the heuristic should run at all 0 - before cuts at root node (or from doHeuristics) 1 - during cuts at root 2 - after root node cuts 3 - after cuts at other nodes 4 - during cuts at other nodes 8 added if previous heuristic in loop found solution */ virtual bool shouldHeurRun(int whereFrom); /** Check whether the heuristic should run this time */ bool shouldHeurRun_randomChoice(); void debugNodes(); void printDistanceToNodes(); /// how many times the heuristic has actually run inline int numRuns() const { return numRuns_; } /// How many times the heuristic could run inline int numCouldRun() const { return numCouldRun_; } /*! \brief Clone, but ... If type is - 0 clone the solver for the model, - 1 clone the continuous solver for the model - Add 2 to say without integer variables which are at low priority - Add 4 to say quite likely infeasible so give up easily (clp only). */ OsiSolverInterface * cloneBut(int type); protected: /// Model CbcModel * model_; /// When flag - 0 off, 1 at root, 2 other than root, 3 always int when_; /// Number of nodes in any sub tree int numberNodes_; /** Feasibility pump options , -1 is off >=0 for feasibility pump itself -2 quick proximity search -3 longer proximity search */ int feasibilityPumpOptions_; /// Fraction of new(rows+columns)/old(rows+columns) before doing small branch and bound mutable double fractionSmall_; /// Thread specific random number generator CoinThreadRandom randomNumberGenerator_; /// Name for printing std::string heuristicName_; /// How often to do (code can change) int howOften_; /// How much to increase how often double decayFactor_; /** Switches (does not apply equally to all heuristics) 1 bit - stop once allowable gap on objective reached 2 bit - always do given number of passes 4 bit - weaken cutoff by 5% every 50 passes? 8 bit - if has cutoff and suminf bobbling for 20 passes then first try halving distance to best possible then try keep halving distance to known cutoff 16 bit - needs new solution to run 1024 bit - stop all heuristics on max time */ mutable int switches_; /* Runs if bit set 0 - before cuts at root node (or from doHeuristics) 1 - during cuts at root 2 - after root node cuts 3 - after cuts at other nodes 4 - during cuts at other nodes 8 added if previous heuristic in loop found solution */ int whereFrom_; /** Upto this depth we call the tree shallow and the heuristic can be called multiple times. That is, the test whether the current node is far from the others where the jeuristic was invoked will not be done, only the frequency will be tested. After that depth the heuristic will can be invoked only once per node, right before branching. That's when it'll be tested whether the heur should run at all. */ int shallowDepth_; /** How often to invoke the heuristics in the shallow part of the tree */ int howOftenShallow_; /** How many invocations happened within the same node when in a shallow part of the tree. */ int numInvocationsInShallow_; /** How many invocations happened when in the deep part of the tree. For every node we count only one invocation. */ int numInvocationsInDeep_; /** After how many deep invocations was the heuristic run last time */ int lastRunDeep_; /// how many times the heuristic has actually run int numRuns_; /** How "far" should this node be from every other where the heuristic was run in order to allow the heuristic to run in this node, too. Currently this is tested, but we may switch to avgDistanceToRun_ in the future. */ int minDistanceToRun_; /// The description of the nodes where this heuristic has been applied CbcHeuristicNodeList runNodes_; /// How many times the heuristic could run int numCouldRun_; /// How many solutions the heuristic thought it got int numberSolutionsFound_; /// How many nodes the heuristic did this go mutable int numberNodesDone_; // Input solution - so can be used as seed double * inputSolution_; #ifdef JJF_ZERO /// Lower bounds of last node where the heuristic found a solution double * lowerBoundLastNode_; /// Upper bounds of last node where the heuristic found a solution double * upperBoundLastNode_; #endif }; /** Rounding class */ class CbcRounding : public CbcHeuristic { public: // Default Constructor CbcRounding (); // Constructor with model - assumed before cuts CbcRounding (CbcModel & model); // Copy constructor CbcRounding ( const CbcRounding &); // Destructor ~CbcRounding (); /// Assignment operator CbcRounding & operator=(const CbcRounding& rhs); /// Clone virtual CbcHeuristic * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution with better objective value than one passed in Sets solution values if good, sets objective value (only if good) This is called after cuts have been added - so can not add cuts */ virtual int solution(double & objectiveValue, double * newSolution); /** returns 0 if no solution, 1 if valid solution with better objective value than one passed in Sets solution values if good, sets objective value (only if good) This is called after cuts have been added - so can not add cuts Use solutionValue rather than solvers one */ virtual int solution(double & objectiveValue, double * newSolution, double solutionValue); /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) virtual void validate(); /// Set seed void setSeed(int value) { seed_ = value; } protected: // Data // Original matrix by column CoinPackedMatrix matrix_; // Original matrix by CoinPackedMatrix matrixByRow_; // Down locks unsigned short * down_; // Up locks unsigned short * up_; // Equality locks unsigned short * equal_; // Seed for random stuff int seed_; }; /** Partial solution class If user knows a partial solution this tries to get an integer solution it uses hotstart information */ class CbcHeuristicPartial : public CbcHeuristic { public: // Default Constructor CbcHeuristicPartial (); /** Constructor with model - assumed before cuts Fixes all variables with priority <= given and does given number of nodes */ CbcHeuristicPartial (CbcModel & model, int fixPriority = 10000, int numberNodes = 200); // Copy constructor CbcHeuristicPartial ( const CbcHeuristicPartial &); // Destructor ~CbcHeuristicPartial (); /// Assignment operator CbcHeuristicPartial & operator=(const CbcHeuristicPartial& rhs); /// Clone virtual CbcHeuristic * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution with better objective value than one passed in Sets solution values if good, sets objective value (only if good) This is called after cuts have been added - so can not add cuts */ virtual int solution(double & objectiveValue, double * newSolution); /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) virtual void validate(); /// Set priority level void setFixPriority(int value) { fixPriority_ = value; } /** Check whether the heuristic should run at all */ virtual bool shouldHeurRun(int whereFrom); protected: // Data // All variables with abs priority <= this will be fixed int fixPriority_; }; /** heuristic - just picks up any good solution found by solver - see OsiBabSolver */ class CbcSerendipity : public CbcHeuristic { public: // Default Constructor CbcSerendipity (); /* Constructor with model */ CbcSerendipity (CbcModel & model); // Copy constructor CbcSerendipity ( const CbcSerendipity &); // Destructor ~CbcSerendipity (); /// Assignment operator CbcSerendipity & operator=(const CbcSerendipity& rhs); /// Clone virtual CbcHeuristic * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// update model virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) We leave all variables which are at one at this node of the tree to that value and will initially set all others to zero. We then sort all variables in order of their cost divided by the number of entries in rows which are not yet covered. We randomize that value a bit so that ties will be broken in different ways on different runs of the heuristic. We then choose the best one and set it to one and repeat the exercise. */ virtual int solution(double & objectiveValue, double * newSolution); /// Resets stuff if model changes virtual void resetModel(CbcModel * model); protected: }; /** Just One class - this chooses one at random */ class CbcHeuristicJustOne : public CbcHeuristic { public: // Default Constructor CbcHeuristicJustOne (); // Constructor with model - assumed before cuts CbcHeuristicJustOne (CbcModel & model); // Copy constructor CbcHeuristicJustOne ( const CbcHeuristicJustOne &); // Destructor ~CbcHeuristicJustOne (); /// Clone virtual CbcHeuristicJustOne * clone() const; /// Assignment operator CbcHeuristicJustOne & operator=(const CbcHeuristicJustOne& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /** returns 0 if no solution, 1 if valid solution with better objective value than one passed in Sets solution values if good, sets objective value (only if good) This is called after cuts have been added - so can not add cuts This does Fractional Diving */ virtual int solution(double & objectiveValue, double * newSolution); /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); /// Selects the next variable to branch on /** Returns true if all the fractional variables can be trivially rounded. Returns false, if there is at least one fractional variable that is not trivially roundable. In this case, the bestColumn returned will not be trivially roundable. This is dummy as never called */ virtual bool selectVariableToBranch(OsiSolverInterface* /*solver*/, const double* /*newSolution*/, int& /*bestColumn*/, int& /*bestRound*/) { return true; } /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) virtual void validate(); /// Adds an heuristic with probability void addHeuristic(const CbcHeuristic * heuristic, double probability); /// Normalize probabilities void normalizeProbabilities(); protected: // Data // Probability of running a heuristic double * probabilities_; // Heuristics CbcHeuristic ** heuristic_; // Number of heuristics int numberHeuristics_; }; #endif Cbc-2.8.12/src/CbcBranchToFixLots.cpp0000644000076600007660000005115212131315050015660 0ustar coincoin// $Id: CbcBranchToFixLots.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/13/2009-- carved out of CbcBranchCut #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchCut.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" #include "CbcBranchToFixLots.hpp" /** Default Constructor Equivalent to an unspecified binary variable. */ CbcBranchToFixLots::CbcBranchToFixLots () : CbcBranchCut(), djTolerance_(COIN_DBL_MAX), fractionFixed_(1.0), mark_(NULL), depth_(-1), numberClean_(0), alwaysCreate_(false) { } /* Useful constructor - passed reduced cost tolerance and fraction we would like fixed. Also depth level to do at. Also passed number of 1 rows which when clean triggers fix Always does if all 1 rows cleaned up and number>0 or if fraction columns reached Also whether to create branch if can't reach fraction. */ CbcBranchToFixLots::CbcBranchToFixLots (CbcModel * model, double djTolerance, double fractionFixed, int depth, int numberClean, const char * mark, bool alwaysCreate) : CbcBranchCut(model) { djTolerance_ = djTolerance; fractionFixed_ = fractionFixed; if (mark) { int numberColumns = model->getNumCols(); mark_ = new char[numberColumns]; memcpy(mark_, mark, numberColumns); } else { mark_ = NULL; } depth_ = depth; assert (model); OsiSolverInterface * solver = model_->solver(); matrixByRow_ = *solver->getMatrixByRow(); numberClean_ = numberClean; alwaysCreate_ = alwaysCreate; } // Copy constructor CbcBranchToFixLots::CbcBranchToFixLots ( const CbcBranchToFixLots & rhs) : CbcBranchCut(rhs) { djTolerance_ = rhs.djTolerance_; fractionFixed_ = rhs.fractionFixed_; int numberColumns = model_->getNumCols(); mark_ = CoinCopyOfArray(rhs.mark_, numberColumns); matrixByRow_ = rhs.matrixByRow_; depth_ = rhs.depth_; numberClean_ = rhs.numberClean_; alwaysCreate_ = rhs.alwaysCreate_; } // Clone CbcObject * CbcBranchToFixLots::clone() const { return new CbcBranchToFixLots(*this); } // Assignment operator CbcBranchToFixLots & CbcBranchToFixLots::operator=( const CbcBranchToFixLots & rhs) { if (this != &rhs) { CbcBranchCut::operator=(rhs); djTolerance_ = rhs.djTolerance_; fractionFixed_ = rhs.fractionFixed_; int numberColumns = model_->getNumCols(); delete [] mark_; mark_ = CoinCopyOfArray(rhs.mark_, numberColumns); matrixByRow_ = rhs.matrixByRow_; depth_ = rhs.depth_; numberClean_ = rhs.numberClean_; alwaysCreate_ = rhs.alwaysCreate_; } return *this; } // Destructor CbcBranchToFixLots::~CbcBranchToFixLots () { delete [] mark_; } CbcBranchingObject * CbcBranchToFixLots::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int /*way*/) { // by default way must be -1 //assert (way==-1); //OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * dj = solver->getReducedCost(); int i; int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); // make smaller ? double tolerance = CoinMin(1.0e-8, integerTolerance); // How many fixed are we aiming at int wantedFixed = static_cast (static_cast(numberIntegers) * fractionFixed_); int nSort = 0; int numberFixed = 0; int numberColumns = solver->getNumCols(); int * sort = new int[numberColumns]; double * dsort = new double[numberColumns]; if (djTolerance_ != -1.234567) { int type = shallWe(); assert (type); // Take clean first if (type == 1) { for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { if (!mark_ || !mark_[iColumn]) { if (solution[iColumn] < lower[iColumn] + tolerance) { if (dj[iColumn] > djTolerance_) { dsort[nSort] = -dj[iColumn]; sort[nSort++] = iColumn; } } else if (solution[iColumn] > upper[iColumn] - tolerance) { if (dj[iColumn] < -djTolerance_) { dsort[nSort] = dj[iColumn]; sort[nSort++] = iColumn; } } } } else { numberFixed++; } } // sort CoinSort_2(dsort, dsort + nSort, sort); nSort = CoinMin(nSort, wantedFixed - numberFixed); } else if (type < 10) { int i; //const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); const double * solution = solver->getColSolution(); int numberColumns = solver->getNumCols(); int numberRows = solver->getNumRows(); for (i = 0; i < numberColumns; i++) { sort[i] = i; if (columnLower[i] != columnUpper[i]) { dsort[i] = 1.0e100; } else { dsort[i] = 1.0e50; numberFixed++; } } for (i = 0; i < numberRows; i++) { double rhsValue = rowUpper[i]; bool oneRow = true; // check elements int numberUnsatisfied = 0; for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; double value = elementByRow[j]; double solValue = solution[iColumn]; if (columnLower[iColumn] != columnUpper[iColumn]) { if (solValue < 1.0 - integerTolerance && solValue > integerTolerance) numberUnsatisfied++; if (value != 1.0) { oneRow = false; break; } } else { rhsValue -= value * floor(solValue + 0.5); } } if (oneRow && rhsValue <= 1.0 + tolerance) { if (!numberUnsatisfied) { for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (dsort[iColumn] > 1.0e50) { dsort[iColumn] = 0; nSort++; } } } } } // sort CoinSort_2(dsort, dsort + numberColumns, sort); } else { // new way for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { if (!mark_ || !mark_[iColumn]) { double distanceDown = solution[iColumn] - lower[iColumn]; double distanceUp = upper[iColumn] - solution[iColumn]; double distance = CoinMin(distanceDown, distanceUp); if (distance > 0.001 && distance < 0.5) { dsort[nSort] = distance; sort[nSort++] = iColumn; } } } } // sort CoinSort_2(dsort, dsort + nSort, sort); int n = 0; double sum = 0.0; for (int k = 0; k < nSort; k++) { sum += dsort[k]; if (sum <= djTolerance_) n = k; else break; } nSort = CoinMin(n, numberClean_ / 1000000); } } else { #define FIX_IF_LESS -0.1 // 3 in same row and sum testSolution(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); double bestSum = 1.0; int nBest = -1; int kRow = -1; OsiSolverInterface * solver = model_->solver(); for (int i = 0; i < numberRows; i++) { int numberUnsatisfied = 0; double sum = 0.0; for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (solver->isInteger(iColumn)) { double solValue = solution[iColumn]; if (solValue > 1.0e-5 && solValue < FIX_IF_LESS) { numberUnsatisfied++; sum += solValue; } } } if (numberUnsatisfied >= 3 && sum < FIX_IF_LESS) { // possible if (numberUnsatisfied > nBest || (numberUnsatisfied == nBest && sum < bestSum)) { nBest = numberUnsatisfied; bestSum = sum; kRow = i; } } } assert (nBest > 0); for (int j = rowStart[kRow]; j < rowStart[kRow] + rowLength[kRow]; j++) { int iColumn = column[j]; if (solver->isInteger(iColumn)) { double solValue = solution[iColumn]; if (solValue > 1.0e-5 && solValue < FIX_IF_LESS) { sort[nSort++] = iColumn; } } } } OsiRowCut down; down.setLb(-COIN_DBL_MAX); double rhs = 0.0; for (i = 0; i < nSort; i++) { int iColumn = sort[i]; double distanceDown = solution[iColumn] - lower[iColumn]; double distanceUp = upper[iColumn] - solution[iColumn]; if (distanceDown < distanceUp) { rhs += lower[iColumn]; dsort[i] = 1.0; } else { rhs -= upper[iColumn]; dsort[i] = -1.0; } } down.setUb(rhs); down.setRow(nSort, sort, dsort); down.setEffectiveness(COIN_DBL_MAX); // so will persist delete [] sort; delete [] dsort; // up is same - just with rhs changed OsiRowCut up = down; up.setLb(rhs + 1.0); up.setUb(COIN_DBL_MAX); // Say can fix one way CbcCutBranchingObject * newObject = new CbcCutBranchingObject(model_, down, up, true); if (model_->messageHandler()->logLevel() > 1) printf("creating cut in CbcBranchCut\n"); return newObject; } /* Does a lot of the work, Returns 0 if no good, 1 if dj, 2 if clean, 3 if both 10 if branching on ones away from bound */ int CbcBranchToFixLots::shallWe() const { int returnCode = 0; OsiSolverInterface * solver = model_->solver(); int numberRows = matrixByRow_.getNumRows(); //if (numberRows!=solver->getNumRows()) //return 0; const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * dj = solver->getReducedCost(); int i; int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); if (numberClean_ > 1000000) { int wanted = numberClean_ % 1000000; int * sort = new int[numberIntegers]; double * dsort = new double[numberIntegers]; int nSort = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { if (!mark_ || !mark_[iColumn]) { double distanceDown = solution[iColumn] - lower[iColumn]; double distanceUp = upper[iColumn] - solution[iColumn]; double distance = CoinMin(distanceDown, distanceUp); if (distance > 0.001 && distance < 0.5) { dsort[nSort] = distance; sort[nSort++] = iColumn; } } } } // sort CoinSort_2(dsort, dsort + nSort, sort); int n = 0; double sum = 0.0; for (int k = 0; k < nSort; k++) { sum += dsort[k]; if (sum <= djTolerance_) n = k; else break; } delete [] sort; delete [] dsort; return (n >= wanted) ? 10 : 0; } double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); // make smaller ? double tolerance = CoinMin(1.0e-8, integerTolerance); // How many fixed are we aiming at int wantedFixed = static_cast (static_cast(numberIntegers) * fractionFixed_); if (djTolerance_ < 1.0e10) { int nSort = 0; int numberFixed = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { if (!mark_ || !mark_[iColumn]) { if (solution[iColumn] < lower[iColumn] + tolerance) { if (dj[iColumn] > djTolerance_) { nSort++; } } else if (solution[iColumn] > upper[iColumn] - tolerance) { if (dj[iColumn] < -djTolerance_) { nSort++; } } } } else { numberFixed++; } } if (numberFixed + nSort < wantedFixed && !alwaysCreate_) { returnCode = 0; } else if (numberFixed < wantedFixed) { returnCode = 1; } else { returnCode = 0; } } if (numberClean_) { // see how many rows clean int i; //const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); const double * solution = solver->getColSolution(); int numberClean = 0; bool someToDoYet = false; int numberColumns = solver->getNumCols(); char * mark = new char[numberColumns]; int numberFixed = 0; for (i = 0; i < numberColumns; i++) { if (columnLower[i] != columnUpper[i]) { mark[i] = 0; } else { mark[i] = 1; numberFixed++; } } int numberNewFixed = 0; for (i = 0; i < numberRows; i++) { double rhsValue = rowUpper[i]; bool oneRow = true; // check elements int numberUnsatisfied = 0; for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; double value = elementByRow[j]; double solValue = solution[iColumn]; if (columnLower[iColumn] != columnUpper[iColumn]) { if (solValue < 1.0 - integerTolerance && solValue > integerTolerance) numberUnsatisfied++; if (value != 1.0) { oneRow = false; break; } } else { rhsValue -= value * floor(solValue + 0.5); } } if (oneRow && rhsValue <= 1.0 + tolerance) { if (numberUnsatisfied) { someToDoYet = true; } else { numberClean++; for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (columnLower[iColumn] != columnUpper[iColumn] && !mark[iColumn]) { mark[iColumn] = 1; numberNewFixed++; } } } } } delete [] mark; //printf("%d clean, %d old fixed, %d new fixed\n", // numberClean,numberFixed,numberNewFixed); if (someToDoYet && numberClean < numberClean_ && numberNewFixed + numberFixed < wantedFixed) { } else if (numberFixed < wantedFixed) { returnCode |= 2; } else { } } return returnCode; } double CbcBranchToFixLots::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { preferredWay = -1; CbcNode * node = model_->currentNode(); int depth; if (node) depth = CoinMax(node->depth(), 0); else return 0.0; if (depth_ < 0) { return 0.0; } else if (depth_ > 0) { if ((depth % depth_) != 0) return 0.0; } if (djTolerance_ != -1.234567) { if (!shallWe()) return 0.0; else return 1.0e20; } else { // See if 3 in same row and sum testSolution(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); double bestSum = 1.0; int nBest = -1; OsiSolverInterface * solver = model_->solver(); for (int i = 0; i < numberRows; i++) { int numberUnsatisfied = 0; double sum = 0.0; for (int j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (solver->isInteger(iColumn)) { double solValue = solution[iColumn]; if (solValue > 1.0e-5 && solValue < FIX_IF_LESS) { numberUnsatisfied++; sum += solValue; } } } if (numberUnsatisfied >= 3 && sum < FIX_IF_LESS) { // possible if (numberUnsatisfied > nBest || (numberUnsatisfied == nBest && sum < bestSum)) { nBest = numberUnsatisfied; bestSum = sum; } } } if (nBest > 0) return 1.0e20; else return 0.0; } } // Redoes data when sequence numbers change void CbcBranchToFixLots::redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns) { model_ = model; if (mark_) { OsiSolverInterface * solver = model_->solver(); int numberColumnsNow = solver->getNumCols(); char * temp = new char[numberColumnsNow]; memset(temp, 0, numberColumnsNow); for (int i = 0; i < numberColumns; i++) { int j = originalColumns[i]; temp[i] = mark_[j]; } delete [] mark_; mark_ = temp; } OsiSolverInterface * solver = model_->solver(); matrixByRow_ = *solver->getMatrixByRow(); } Cbc-2.8.12/src/CbcTree.hpp0000644000076600007660000003017712053473106013571 0ustar coincoin/* $Id: CbcTree.hpp 1813 2012-11-22 19:00:22Z forrest $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcTree_H #define CbcTree_H #include #include #include #include "CoinHelperFunctions.hpp" #include "CbcCompare.hpp" /*! \brief Using MS heap implementation It's unclear if this is needed any longer, or even if it should be allowed. Cbc occasionally tries to do things to the tree (typically tweaking the comparison predicate) that can cause a violation of the heap property (parent better than either child). In a debug build, Microsoft's heap implementation does checks that detect this and fail. This symbol switched to an alternate implementation of CbcTree, and there are clearly differences, but no explanation as to why or what for. As of 100921, the code is cleaned up to make it through `cbc -unitTest' without triggering `Invalid heap' in an MSVS debug build. The method validateHeap() can be used for debugging if this turns up again. */ //#define CBC_DUBIOUS_HEAP #if defined(_MSC_VER) || defined(__MNO_CYGWIN) //#define CBC_DUBIOUS_HEAP #endif #if 1 //ndef CBC_DUBIOUS_HEAP /*! \brief Controls search tree debugging In order to have validateHeap() available, set CBC_DEBUG_HEAP to 1 or higher. - 1 calls validateHeap() after each change to the heap - 2 will print a line for major operations (clean, set comparison, etc.) - 3 will print information about each push and pop #define CBC_DEBUG_HEAP 1 */ /*! \class CbcTree \brief Implementation of the live set as a heap. This class is used to hold the set of live nodes in the search tree. */ class CbcTree { public: /*! \name Constructors and related */ //@{ /// Default Constructor CbcTree (); /// Copy constructor CbcTree (const CbcTree &rhs); /// = operator CbcTree & operator=(const CbcTree &rhs); /// Destructor virtual ~CbcTree(); /// Clone virtual CbcTree * clone() const; /// Create C++ lines to get to current state virtual void generateCpp(FILE *) {} //@} /*! \name Heap access and maintenance methods */ //@{ /// Set comparison function and resort heap void setComparison(CbcCompareBase &compare); /// Return the top node of the heap virtual CbcNode * top() const; /// Add a node to the heap virtual void push(CbcNode *x); /// Remove the top node from the heap virtual void pop() ; /*! \brief Gets best node and takes off heap Before returning the node from the top of the heap, the node is offered an opportunity to reevaluate itself. Callers should be prepared to check that the node returned is suitable for use. */ virtual CbcNode * bestNode(double cutoff); /*! \brief Rebuild the heap */ virtual void rebuild() ; //@} /*! \name Direct node access methods */ //@{ /// Test for an empty tree virtual bool empty() ; /// Return size virtual int size() const { return static_cast(nodes_.size()); } /// Return a node pointer inline CbcNode * operator [] (int i) const { return nodes_[i]; } /// Return a node pointer inline CbcNode * nodePointer (int i) const { return nodes_[i]; } void realpop(); /** After changing data in the top node, fix the heap */ void fixTop(); void realpush(CbcNode * node); //@} /*! \name Search tree maintenance */ //@{ /*! \brief Prune the tree using an objective function cutoff This routine removes all nodes with objective worse than the specified cutoff value. It also sets bestPossibleObjective to the best objective over remaining nodes. */ virtual void cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective); /// Get best on list using alternate method CbcNode * bestAlternate(); /// We may have got an intelligent tree so give it one more chance virtual void endSearch() {} /// Get best possible objective function in the tree virtual double getBestPossibleObjective(); /// Reset maximum node number inline void resetNodeNumbers() { maximumNodeNumber_ = 0; } /// Get maximum node number inline int maximumNodeNumber() const { return maximumNodeNumber_; } /// Set number of branches inline void setNumberBranching(int value) { numberBranching_ = value; } /// Get number of branches inline int getNumberBranching() const { return numberBranching_; } /// Set maximum branches inline void setMaximumBranching(int value) { maximumBranching_ = value; } /// Get maximum branches inline int getMaximumBranching() const { return maximumBranching_; } /// Get branched variables inline unsigned int * branched() const { return branched_; } /// Get bounds inline int * newBounds() const { return newBound_; } /// Adds branching information to complete state void addBranchingInformation(const CbcModel * model, const CbcNodeInfo * nodeInfo, const double * currentLower, const double * currentUpper); /// Increase space for data void increaseSpace(); //@} # if CBC_DEBUG_HEAP > 0 /*! \name Debugging methods */ //@{ /*! \brief Check that the heap property is satisfied. */ void validateHeap() ; //@} # endif protected: /// Storage vector for the heap std::vector nodes_; /// Sort predicate for heap ordering. CbcCompare comparison_; /// Maximum "node" number so far to split ties int maximumNodeNumber_; /// Size of variable list int numberBranching_; /// Maximum size of variable list int maximumBranching_; /** Integer variables branched or bounded top bit set if new upper bound next bit set if a branch */ unsigned int * branched_; /// New bound int * newBound_; }; #ifdef JJF_ZERO // not used /*! \brief Implementation of live set as a managed array. This class is used to hold the set of live nodes in the search tree. */ class CbcTreeArray : public CbcTree { public: // Default Constructor CbcTreeArray (); // Copy constructor CbcTreeArray ( const CbcTreeArray & rhs); // = operator CbcTreeArray & operator=(const CbcTreeArray & rhs); virtual ~CbcTreeArray(); /// Clone virtual CbcTree * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * ) {} /*! \name Heap access and maintenance methods */ //@{ /// Set comparison function and resort heap void setComparison(CbcCompareBase &compare); /// Add a node to the heap virtual void push(CbcNode * x); /// Gets best node and takes off heap virtual CbcNode * bestNode(double cutoff); //@} /*! \name vector methods */ //@{ /// Test if empty *** note may be overridden virtual bool empty() ; //@} /*! \name Search tree maintenance */ //@{ /*! \brief Prune the tree using an objective function cutoff This routine removes all nodes with objective worst than the specified cutoff value. It also sets bestPossibleObjective to best of all on tree before deleting. */ void cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective); /// Get best possible objective function in the tree virtual double getBestPossibleObjective(); //@} protected: /// Returns /// Last node CbcNode * lastNode_; /// Last node popped CbcNode * lastNodePopped_; /// Not used yet int switches_; }; /// New style #include "CoinSearchTree.hpp" /*! \class tree \brief Implementation of live set as a heap. This class is used to hold the set of live nodes in the search tree. */ class CbcNewTree : public CbcTree, public CoinSearchTreeManager { public: // Default Constructor CbcNewTree (); // Copy constructor CbcNewTree ( const CbcNewTree & rhs); // = operator CbcNewTree & operator=(const CbcNewTree & rhs); virtual ~CbcNewTree(); /// Clone virtual CbcNewTree * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * ) {} /*! \name Heap access and maintenance methods */ //@{ /// Set comparison function and resort heap void setComparison(CbcCompareBase &compare); /// Return the top node of the heap virtual CbcNode * top() const; /// Add a node to the heap virtual void push(CbcNode * x); /// Remove the top node from the heap virtual void pop() ; /// Gets best node and takes off heap virtual CbcNode * bestNode(double cutoff); //@} /*! \name vector methods */ //@{ /// Test if empty *** note may be overridden virtual bool empty() ; /// Return size inline int size() const { return nodes_.size(); } /// [] operator inline CbcNode * operator [] (int i) const { return nodes_[i]; } /// Return a node pointer inline CbcNode * nodePointer (int i) const { return nodes_[i]; } //@} /*! \name Search tree maintenance */ //@{ /*! \brief Prune the tree using an objective function cutoff This routine removes all nodes with objective worst than the specified cutoff value. It also sets bestPossibleObjective to best of all on tree before deleting. */ void cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective); /// Get best on list using alternate method CbcNode * bestAlternate(); /// We may have got an intelligent tree so give it one more chance virtual void endSearch() {} //@} protected: }; #endif #else /* CBC_DUBIOUS_HEAP is defined See note at top of file. This code is highly suspect. -- lh, 100921 -- */ class CbcTree { public: // Default Constructor CbcTree (); // Copy constructor CbcTree ( const CbcTree & rhs); // = operator CbcTree & operator=(const CbcTree & rhs); virtual ~CbcTree(); /// Clone virtual CbcTree * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) {} /*! \name Heap access and maintenance methods */ //@{ /// Set comparison function and resort heap void setComparison(CbcCompareBase &compare); /// Return the top node of the heap virtual CbcNode * top() const; /// Add a node to the heap virtual void push(CbcNode * x); /// Remove the top node from the heap virtual void pop() ; /// Gets best node and takes off heap virtual CbcNode * bestNode(double cutoff); //@} /*! \name vector methods */ //@{ /// Test if empty *** note may be overridden //virtual bool empty() ; /// Return size inline int size() const { return nodes_.size(); } /// [] operator inline CbcNode * operator [] (int i) const { return nodes_[i]; } /// Return a node pointer inline CbcNode * nodePointer (int i) const { return nodes_[i]; } virtual bool empty(); //inline int size() const { return size_; } void realpop(); /** After changing data in the top node, fix the heap */ void fixTop(); void realpush(CbcNode * node); //@} /*! \name Search tree maintenance */ //@{ /*! \brief Prune the tree using an objective function cutoff This routine removes all nodes with objective worst than the specified cutoff value. It also sets bestPossibleObjective to best of all on tree before deleting. */ void cleanTree(CbcModel * model, double cutoff, double & bestPossibleObjective); /// Get best on list using alternate method CbcNode * bestAlternate(); /// We may have got an intelligent tree so give it one more chance virtual void endSearch() {} /// Reset maximum node number inline void resetNodeNumbers() { maximumNodeNumber_ = 0; } /// Get maximum node number inline int maximumNodeNumber() const { return maximumNodeNumber_; } //@} protected: std::vector nodes_; CbcCompare comparison_; ///> Sort function for heap ordering. /// Maximum "node" number so far to split ties int maximumNodeNumber_; }; #endif #endif Cbc-2.8.12/src/CbcFathomDynamicProgramming.hpp0000644000076600007660000001331711510742604017614 0ustar coincoin/* $Id: CbcFathomDynamicProgramming.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcFathomDynamicProgramming_H #define CbcFathomDynamicProgramming_H #include "CbcFathom.hpp" //############################################################################# /** FathomDynamicProgramming class. The idea is that after some branching the problem will be effectively smaller than the original problem and maybe there will be a more specialized technique which can completely fathom this branch quickly. This is a dynamic programming implementation which is very fast for some specialized problems. It expects small integral rhs, an all integer problem and positive integral coefficients. At present it can not do general set covering problems just set partitioning. It can find multiple optima for various rhs combinations. The main limiting factor is size of state space. Each 1 rhs doubles the size of the problem. 2 or 3 rhs quadruples, 4,5,6,7 by 8 etc. */ class CbcFathomDynamicProgramming : public CbcFathom { public: // Default Constructor CbcFathomDynamicProgramming (); // Constructor with model - assumed before cuts CbcFathomDynamicProgramming (CbcModel & model); // Copy constructor CbcFathomDynamicProgramming(const CbcFathomDynamicProgramming & rhs); virtual ~CbcFathomDynamicProgramming(); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); /// Clone virtual CbcFathom * clone() const; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /** returns 0 if no fathoming attempted, 1 fully fathomed , 2 incomplete search, 3 incomplete search but treat as complete. If solution then newSolution will not be NULL and will be freed by CbcModel. It is expected that the solution is better than best so far but CbcModel will double check. If returns 3 then of course there is no guarantee of global optimum */ virtual int fathom(double *& newSolution); /// Maximum size allowed inline int maximumSize() const { return maximumSizeAllowed_; } inline void setMaximumSize(int value) { maximumSizeAllowed_ = value; } /// Returns type of algorithm and sets up arrays int checkPossible(int allowableSize = 0); // set algorithm inline void setAlgorithm(int value) { algorithm_ = value; } /** Tries a column returns true if was used in making any changes. */ bool tryColumn(int numberElements, const int * rows, const double * coefficients, double cost, int upper = COIN_INT_MAX); /// Returns cost array inline const double * cost() const { return cost_; } /// Returns back array inline const int * back() const { return back_; } /// Gets bit pattern for target result inline int target() const { return target_; } /// Sets bit pattern for target result inline void setTarget(int value) { target_ = value; } private: /// Does deleteions void gutsOfDelete(); /** Adds one attempt of one column of type 0, returns true if was used in making any changes */ bool addOneColumn0(int numberElements, const int * rows, double cost); /** Adds one attempt of one column of type 1, returns true if was used in making any changes. At present the user has to call it once for each possible value */ bool addOneColumn1(int numberElements, const int * rows, const int * coefficients, double cost); /** Adds one attempt of one column of type 1, returns true if was used in making any changes. At present the user has to call it once for each possible value. This version is when there are enough 1 rhs to do faster */ bool addOneColumn1A(int numberElements, const int * rows, const int * coefficients, double cost); /// Gets bit pattern from original column int bitPattern(int numberElements, const int * rows, const int * coefficients); /// Gets bit pattern from original column int bitPattern(int numberElements, const int * rows, const double * coefficients); /// Fills in original column (dense) from bit pattern - returning number nonzero int decodeBitPattern(int bitPattern, int * values, int numberRows); protected: /// Size of states (power of 2 unless just one constraint) int size_; /** Type - 0 coefficients and rhs all 1, 1 - coefficients > 1 or rhs > 1 */ int type_; /// Space for states double * cost_; /// Which state produced this cheapest one int * back_; /// Some rows may be satisified so we need a lookup int * lookup_; /// Space for sorted indices int * indices_; /// Number of active rows int numberActive_; /// Maximum size allowed int maximumSizeAllowed_; /// Start bit for each active row int * startBit_; /// Number bits for each active row int * numberBits_; /// Effective rhs int * rhs_; /// Space for sorted coefficients int * coefficients_; /// Target pattern int target_; /// Number of Non 1 rhs int numberNonOne_; /// Current bit pattern int bitPattern_; /// Current algorithm int algorithm_; private: /// Illegal Assignment operator CbcFathomDynamicProgramming & operator=(const CbcFathomDynamicProgramming& rhs); }; #endif Cbc-2.8.12/src/CbcConsequence.hpp0000644000076600007660000000236712131315050015130 0ustar coincoin// $Id: CbcConsequence.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/12/2009 carved from CbcBranchBase #ifndef CbcConsequence_H #define CbcConsequence_H class OsiSolverInterface; /** Abstract base class for consequent bounds. When a variable is branched on it normally interacts with other variables by means of equations. There are cases where we want to step outside LP and do something more directly e.g. fix bounds. This class is for that. At present it need not be virtual as only instance is CbcFixVariable, but ... */ class CbcConsequence { public: // Default Constructor CbcConsequence (); // Copy constructor CbcConsequence ( const CbcConsequence & rhs); // Assignment operator CbcConsequence & operator=( const CbcConsequence & rhs); /// Clone virtual CbcConsequence * clone() const = 0; /// Destructor virtual ~CbcConsequence (); /** Apply to an LP solver. Action depends on state */ virtual void applyToSolver(OsiSolverInterface * solver, int state) const = 0; protected: }; #endif Cbc-2.8.12/src/CbcMipStartIO.cpp0000644000076600007660000002120212306375215014650 0ustar coincoin#include #include #include #include #include #include #include #include #include #include #include #include "CbcMessage.hpp" #include "CbcHeuristic.hpp" #include #include "CbcMipStartIO.hpp" #include "CoinTime.hpp" using namespace std; bool isNumericStr( const char *str ) { const size_t l = strlen(str); for ( size_t i=0 ; i > &colValues, double &/*solObj*/ ) { #define STR_SIZE 256 FILE *f = fopen( fileName, "r" ); if (!f) return 1; char line[STR_SIZE]; int nLine = 0; char printLine[STR_SIZE]; while (fgets( line, STR_SIZE, f )) { ++nLine; char col[4][STR_SIZE]; int nread = sscanf( line, "%s %s %s %s", col[0], col[1], col[2], col[3] ); if (!nread) continue; /* line with variable value */ if (strlen(col[0])&&isdigit(col[0][0])&&(nread>=3)) { if (!isNumericStr(col[0])) { sprintf( printLine, "Reading: %s, line %d - first column in mipstart file should be numeric, ignoring.", fileName, nLine ); model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol; continue; } if (!isNumericStr(col[2])) { sprintf( printLine, "Reading: %s, line %d - Third column in mipstart file should be numeric, ignoring.", fileName, nLine ); model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol; continue; } //int idx = atoi( col[0] ); char *name = col[1]; double value = atof( col[2] ); //double obj = 0.0; // if (nread >= 4) // obj = atof( col[3] ); colValues.push_back( pair(string(name),value) ); } } if (colValues.size()) { sprintf( printLine,"mipstart values read for %d variables.", (int)colValues.size()); model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol; if (colValues.size()getNumCols()) { int numberColumns = model->getNumCols(); OsiSolverInterface * solver = model->solver(); vector< pair< string, double > > fullValues; /* for fast search of column names */ map< string, int > colIdx; for (int i=0;i(solver->getColName(i),0.0) ); colIdx[solver->getColName(i)] = i; } for ( int i=0 ; (i<(int)colValues.size()) ; ++i ) { map< string, int >::const_iterator mIt = colIdx.find( colValues[i].first ); if ( mIt != colIdx.end() ) { const int idx = mIt->second; double v = colValues[i].second; fullValues[idx].second=v; } } colValues=fullValues; } } else { sprintf( printLine, "No mipstart solution read from %s", fileName ); model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol; return 1; } fclose(f); return 0; } int computeCompleteSolution( CbcModel * model, const vector< string > colNames, const std::vector< std::pair< std::string, double > > &colValues, double *sol, double &obj ) { int status = 0; double compObj = COIN_DBL_MAX; bool foundIntegerSol = false; OsiSolverInterface *lp = model->solver()->clone(); map< string, int > colIdx; assert( ((int)colNames.size()) == lp->getNumCols() ); /* for fast search of column names */ for ( int i=0 ; (i<(int)colNames.size()) ; ++i ) colIdx[colNames[i]] = i; char printLine[STR_SIZE]; int fixed = 0; int notFound = 0; char colNotFound[256] = ""; int nContinuousFixed = 0; for ( int i=0 ; (i<(int)colValues.size()) ; ++i ) { map< string, int >::const_iterator mIt = colIdx.find( colValues[i].first ); if ( mIt == colIdx.end() ) { if (!notFound) strcpy( colNotFound, colValues[i].first.c_str() ); notFound++; } else { const int idx = mIt->second; double v = colValues[i].second; if (v<1e-8) v = 0.0; if (lp->isInteger(idx)) // just to avoid small v = floor( v+0.5 ); // fractional garbage else nContinuousFixed++; lp->setColBounds( idx, v, v ); ++fixed; } } if (!fixed) { model->messageHandler()->message(CBC_GENERAL, model->messages()) << "Warning: MIPstart solution is not valid, ignoring it." << CoinMessageEol; goto TERMINATE; } if ( notFound >= ( ((double)colNames.size()) * 0.5 ) ) { sprintf( printLine, "Warning: %d column names were not found (e.g. %s) while filling solution.", notFound, colNotFound ); model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol; } lp->initialSolve(); if (!lp->isProvenOptimal()) { model->messageHandler()->message(CBC_GENERAL, model->messages()) << "Warning: mipstart values could not be used to build a solution." << CoinMessageEol; if (nContinuousFixed) { model->messageHandler()->message(CBC_GENERAL, model->messages()) << "Trying just fixing integer variables." << CoinMessageEol; int numberColumns = lp->getNumCols(); const double * oldLower = model->solver()->getColLower(); const double * oldUpper = model->solver()->getColUpper(); for ( int i=0 ; iisInteger(i)) { lp->setColLower(i,oldLower[i]); lp->setColUpper(i,oldUpper[i]); } } lp->initialSolve(); if (!lp->isProvenOptimal()) model->messageHandler()->message(CBC_GENERAL, model->messages()) << "Still no good." << CoinMessageEol; } if (!lp->isProvenOptimal()) { status = 1; goto TERMINATE; } } /* some additional effort is needed to provide an integer solution */ if ( lp->getFractionalIndices().size() > 0 ) { sprintf( printLine,"MIPStart solution provided values for %d of %d integer variables, %d variables are still fractional.", fixed, lp->getNumIntegers(), (int)lp->getFractionalIndices().size() ); model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol; double start = CoinCpuTime(); #if 1 CbcSerendipity heuristic(*model); heuristic.setFractionSmall(2.0); heuristic.setFeasibilityPumpOptions(1008013); int returnCode = heuristic.smallBranchAndBound(lp, 1000, sol, compObj, model->getCutoff(), "ReduceInMIPStart"); if ((returnCode&1) != 0) { sprintf( printLine,"Mini branch and bound defined values for remaining variables in %.2f seconds.", CoinCpuTime()-start); model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol; foundIntegerSol = true; obj = compObj; } #else CbcModel babModel( *lp ); babModel.setLogLevel( 0 ); babModel.setMaximumNodes( 500 ); babModel.setMaximumSeconds( 60 ); babModel.branchAndBound(); if (babModel.bestSolution()) { sprintf( printLine,"Mini branch and bound defined values for remaining variables in %.2f seconds.", CoinCpuTime()-start); model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol; copy( babModel.bestSolution(), babModel.bestSolution()+babModel.getNumCols(), sol ); foundIntegerSol = true; obj = compObj = babModel.getObjValue(); } #endif else { model->messageHandler()->message(CBC_GENERAL, model->messages()) << "Warning: mipstart values could not be used to build a solution." << CoinMessageEol; status = 1; goto TERMINATE; } } else { foundIntegerSol = true; obj = compObj = lp->getObjValue(); copy( lp->getColSolution(), lp->getColSolution()+lp->getNumCols(), sol ); } if ( foundIntegerSol ) { sprintf( printLine,"mipstart provided solution with cost %g", compObj); model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol; for ( int i=0 ; (igetNumCols()) ; ++i ) { if (sol[i]<1e-8) sol[i] = 0.0; else if (lp->isInteger(i)) sol[i] = floor( sol[i]+0.5 ); } } TERMINATE: delete lp; return status; } #undef STR_SIZE Cbc-2.8.12/src/CbcCompareObjective.hpp0000644000076600007660000000265312131315050016077 0ustar coincoin// $Id: CbcCompareObjective.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCompareActual #ifndef CbcCompareObjective_H #define CbcCompareObjective_H //############################################################################# /* These are alternative strategies for node traversal. They can take data etc for fine tuning At present the node list is stored as a heap and the "test" comparison function returns true if node y is better than node x. */ #include "CbcNode.hpp" #include "CbcCompareBase.hpp" #include "CbcCompare.hpp" class CbcModel; class CbcCompareObjective : public CbcCompareBase { public: // Default Constructor CbcCompareObjective (); virtual ~CbcCompareObjective(); // Copy constructor CbcCompareObjective ( const CbcCompareObjective &rhs); // Assignment operator CbcCompareObjective & operator=( const CbcCompareObjective& rhs); /// Clone virtual CbcCompareBase * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp); /* This returns true if objective value of node y is less than objective value of node x */ virtual bool test (CbcNode * x, CbcNode * y); }; #endif //CbcCompareObjective_H Cbc-2.8.12/src/CbcMipStartIO.hpp0000644000076600007660000000153512131315050014647 0ustar coincoin#ifndef MIPSTARTIO_HPP_INCLUDED #define MIPSTARTIO_HPP_INCLUDED #include #include #include class CbcModel; class OsiSolverInterface; /* tries to read mipstart (solution file) from fileName, filling colValues and obj returns 0 with success, 1 otherwise */ int readMIPStart( CbcModel * model, const char *fileName, std::vector< std::pair< std::string, double > > &colValues, double &solObj ); /* from a partial list of variables tries to fill the remaining variable values */ int computeCompleteSolution( CbcModel * model, const std::vector< std::string > colNames, const std::vector< std::pair< std::string, double > > &colValues, double *sol, double &obj ); #endif // MIPSTARTIO_HPP_INCLUDED Cbc-2.8.12/src/CbcSolverExpandKnapsack.hpp0000644000076600007660000000201612131315050016735 0ustar coincoin/* $Id: CbcSolverExpandKnapsack.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /*! \file CbcSolverExpandKnapsack.hpp \brief Expanding possibilities of x*y, where x*y are both integers, constructing a knapsack constraint. Results in a tighter model. */ #ifndef CbcSolverExpandKnapsack_H #define CbcSolverExpandKnapsack_H OsiSolverInterface * expandKnapsack(CoinModel & model, int * whichColumn, int * knapsackStart, int * knapsackRow, int &numberKnapsack, CglStored & stored, int logLevel, int fixedPriority, int SOSPriority, CoinModel & tightenedModel); void afterKnapsack(const CoinModel & coinModel2, const int * whichColumn, const int * knapsackStart, const int * knapsackRow, int numberKnapsack, const double * knapsackSolution, double * solution, int logLevel); #endif Cbc-2.8.12/src/CbcSolverAnalyze.cpp0000644000076600007660000003422612131315050015450 0ustar coincoin/* $Id: CbcSolverAnalyze.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /*! \file CbcSolverAnalyze.cpp Look to see if a constraint is all-integer (variables & coeffs), or could be all integer. Consider whether one or two continuous variables can be declared integer. John's comment is that integer preprocessing might do a better job, so we should consider whether this routine should stay. No hurry to get rid of it, in my opinion -- lh, 091210 -- */ #include "CbcConfig.h" #include "CoinPragma.hpp" #include "OsiClpSolverInterface.hpp" #include "ClpMessage.hpp" #include "CbcModel.hpp" #ifndef CBC_OTHER_SOLVER int * analyze(OsiClpSolverInterface * solverMod, int & numberChanged, double & increment, bool changeInt, CoinMessageHandler * generalMessageHandler, bool noPrinting) { bool noPrinting_ = noPrinting; OsiSolverInterface * solver = solverMod->clone(); char generalPrint[200]; if (0) { // just get increment CbcModel model(*solver); model.analyzeObjective(); double increment2 = model.getCutoffIncrement(); printf("initial cutoff increment %g\n", increment2); } const double *objective = solver->getObjCoefficients() ; const double *lower = solver->getColLower() ; const double *upper = solver->getColUpper() ; int numberColumns = solver->getNumCols() ; int numberRows = solver->getNumRows(); double direction = solver->getObjSense(); int iRow, iColumn; // Row copy CoinPackedMatrix matrixByRow(*solver->getMatrixByRow()); const double * elementByRow = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); // Column copy CoinPackedMatrix matrixByCol(*solver->getMatrixByCol()); const double * element = matrixByCol.getElements(); const int * row = matrixByCol.getIndices(); const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); const int * columnLength = matrixByCol.getVectorLengths(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); char * ignore = new char [numberRows]; int * changed = new int[numberColumns]; int * which = new int[numberRows]; double * changeRhs = new double[numberRows]; memset(changeRhs, 0, numberRows*sizeof(double)); memset(ignore, 0, numberRows); numberChanged = 0; int numberInteger = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8 && solver->isInteger(iColumn)) numberInteger++; } bool finished = false; while (!finished) { int saveNumberChanged = numberChanged; for (iRow = 0; iRow < numberRows; iRow++) { int numberContinuous = 0; double value1 = 0.0, value2 = 0.0; bool allIntegerCoeff = true; double sumFixed = 0.0; int jColumn1 = -1, jColumn2 = -1; for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int jColumn = column[j]; double value = elementByRow[j]; if (upper[jColumn] > lower[jColumn] + 1.0e-8) { if (!solver->isInteger(jColumn)) { if (numberContinuous == 0) { jColumn1 = jColumn; value1 = value; } else { jColumn2 = jColumn; value2 = value; } numberContinuous++; } else { if (fabs(value - floor(value + 0.5)) > 1.0e-12) allIntegerCoeff = false; } } else { sumFixed += lower[jColumn] * value; } } double low = rowLower[iRow]; if (low > -1.0e20) { low -= sumFixed; if (fabs(low - floor(low + 0.5)) > 1.0e-12) allIntegerCoeff = false; } double up = rowUpper[iRow]; if (up < 1.0e20) { up -= sumFixed; if (fabs(up - floor(up + 0.5)) > 1.0e-12) allIntegerCoeff = false; } if (!allIntegerCoeff) continue; // can't do if (numberContinuous == 1) { // see if really integer // This does not allow for complicated cases if (low == up) { if (fabs(value1) > 1.0e-3) { value1 = 1.0 / value1; if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) { // integer changed[numberChanged++] = jColumn1; solver->setInteger(jColumn1); if (upper[jColumn1] > 1.0e20) solver->setColUpper(jColumn1, 1.0e20); if (lower[jColumn1] < -1.0e20) solver->setColLower(jColumn1, -1.0e20); } } } else { if (fabs(value1) > 1.0e-3) { value1 = 1.0 / value1; if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) { // This constraint will not stop it being integer ignore[iRow] = 1; } } } } else if (numberContinuous == 2) { if (low == up) { /* need general theory - for now just look at 2 cases - 1 - +- 1 one in column and just costs i.e. matching objective 2 - +- 1 two in column but feeds into G/L row which will try and minimize */ if (fabs(value1) == 1.0 && value1*value2 == -1.0 && !lower[jColumn1] && !lower[jColumn2]) { int n = 0; int i; double objChange = direction * (objective[jColumn1] + objective[jColumn2]); double bound = CoinMin(upper[jColumn1], upper[jColumn2]); bound = CoinMin(bound, 1.0e20); for ( i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) { int jRow = row[i]; double value = element[i]; if (jRow != iRow) { which[n++] = jRow; changeRhs[jRow] = value; } } for ( i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) { int jRow = row[i]; double value = element[i]; if (jRow != iRow) { if (!changeRhs[jRow]) { which[n++] = jRow; changeRhs[jRow] = value; } else { changeRhs[jRow] += value; } } } if (objChange >= 0.0) { // see if all rows OK bool good = true; for (i = 0; i < n; i++) { int jRow = which[i]; double value = changeRhs[jRow]; if (value) { value *= bound; if (rowLength[jRow] == 1) { if (value > 0.0) { double rhs = rowLower[jRow]; if (rhs > 0.0) { double ratio = rhs / value; if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12) good = false; } } else { double rhs = rowUpper[jRow]; if (rhs < 0.0) { double ratio = rhs / value; if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12) good = false; } } } else if (rowLength[jRow] == 2) { if (value > 0.0) { if (rowLower[jRow] > -1.0e20) good = false; } else { if (rowUpper[jRow] < 1.0e20) good = false; } } else { good = false; } } } if (good) { // both can be integer changed[numberChanged++] = jColumn1; solver->setInteger(jColumn1); if (upper[jColumn1] > 1.0e20) solver->setColUpper(jColumn1, 1.0e20); if (lower[jColumn1] < -1.0e20) solver->setColLower(jColumn1, -1.0e20); changed[numberChanged++] = jColumn2; solver->setInteger(jColumn2); if (upper[jColumn2] > 1.0e20) solver->setColUpper(jColumn2, 1.0e20); if (lower[jColumn2] < -1.0e20) solver->setColLower(jColumn2, -1.0e20); } } // clear for (i = 0; i < n; i++) { changeRhs[which[i]] = 0.0; } } } } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8 && !solver->isInteger(iColumn)) { double value; value = upper[iColumn]; if (value < 1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12) continue; value = lower[iColumn]; if (value > -1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12) continue; bool integer = true; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (!ignore[iRow]) { integer = false; break; } } if (integer) { // integer changed[numberChanged++] = iColumn; solver->setInteger(iColumn); if (upper[iColumn] > 1.0e20) solver->setColUpper(iColumn, 1.0e20); if (lower[iColumn] < -1.0e20) solver->setColLower(iColumn, -1.0e20); } } } finished = numberChanged == saveNumberChanged; } delete [] which; delete [] changeRhs; delete [] ignore; //if (numberInteger&&!noPrinting_) //printf("%d integer variables",numberInteger); if (changeInt) { //if (!noPrinting_) { //if (numberChanged) // printf(" and %d variables made integer\n",numberChanged); //else // printf("\n"); //} delete [] ignore; //increment=0.0; if (!numberChanged) { delete [] changed; delete solver; return NULL; } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (solver->isInteger(iColumn)) solverMod->setInteger(iColumn); } delete solver; return changed; } } else { //if (!noPrinting_) { //if (numberChanged) // printf(" and %d variables could be made integer\n",numberChanged); //else // printf("\n"); //} // just get increment int logLevel = generalMessageHandler->logLevel(); CbcModel model(*solver); if (!model.defaultHandler()) model.passInMessageHandler(generalMessageHandler); if (noPrinting_) model.setLogLevel(0); model.analyzeObjective(); generalMessageHandler->setLogLevel(logLevel); double increment2 = model.getCutoffIncrement(); if (increment2 > increment && increment2 > 0.0) { if (!noPrinting_) { sprintf(generalPrint, "Cutoff increment increased from %g to %g", increment, increment2); CoinMessages generalMessages = solverMod->getModelPtr()->messages(); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } increment = increment2; } delete solver; numberChanged = 0; delete [] changed; return NULL; } } #endif // ifndef CBC_OTHER_SOLVER Cbc-2.8.12/src/CbcClique.hpp0000644000076600007660000002424012131315050014074 0ustar coincoin// $Id: CbcClique.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/9/2009-- carved out of CbcBranchActual #ifndef CbcClique_H #define CbcClique_H /** \brief Branching object for cliques A clique is defined to be a set of binary variables where fixing any one variable to its `strong' value fixes all other variables. An example is the most common SOS1 construction: a set of binary variables x_j s.t. SUM{j} x_j = 1. Setting any one variable to 1 forces all other variables to 0. (See comments for CbcSOS below.) Other configurations are possible, however: Consider x1-x2+x3 <= 0. Setting x1 (x3) to 1 forces x2 to 1 and x3 (x1) to 0. Setting x2 to 0 forces x1 and x3 to 0. The proper point of view to take when interpreting CbcClique is `generalisation of SOS1 on binary variables.' To get into the proper frame of mind, here's an example. Consider the following sequence, where x_j = (1-y_j): \verbatim x1 + x2 + x3 <= 1 all strong at 1 x1 - y2 + x3 <= 0 y2 strong at 0; x1, x3 strong at 1 -y1 - y2 + x3 <= -1 y1, y2 strong at 0, x3 strong at 1 -y1 - y2 - y3 <= -2 all strong at 0 \endverbatim The first line is a standard SOS1 on binary variables. Variables with +1 coefficients are `SOS-style' and variables with -1 coefficients are `non-SOS-style'. So #numberNonSOSMembers_ simply tells you how many variables have -1 coefficients. The implicit rhs for a clique is 1-numberNonSOSMembers_. */ class CbcClique : public CbcObject { public: /// Default Constructor CbcClique (); /** Useful constructor (which are integer indices) slack can denote a slack in set. If type == NULL then as if 1 */ CbcClique (CbcModel * model, int cliqueType, int numberMembers, const int * which, const char * type, int identifier, int slack = -1); /// Copy constructor CbcClique ( const CbcClique &); /// Clone virtual CbcObject * clone() const; /// Assignment operator CbcClique & operator=( const CbcClique& rhs); /// Destructor virtual ~CbcClique (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /// This looks at solution and sets bounds to contain solution virtual void feasibleRegion(); /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Number of members inline int numberMembers() const { return numberMembers_; } /** \brief Number of variables with -1 coefficient Number of non-SOS members, i.e., fixing to zero is strong. See comments at head of class, and comments for #type_. */ inline int numberNonSOSMembers() const { return numberNonSOSMembers_; } /// Members (indices in range 0 ... numberIntegers_-1) inline const int * members() const { return members_; } /*! \brief Type of each member, i.e., which way is strong. This also specifies whether a variable has a +1 or -1 coefficient. - 0 => -1 coefficient, 0 is strong value - 1 => +1 coefficient, 1 is strong value If unspecified, all coefficients are assumed to be positive. Indexed as 0 .. numberMembers_-1 */ inline char type(int index) const { if (type_) return type_[index]; else return 1; } /// Clique type: 0 is <=, 1 is == inline int cliqueType() const { return cliqueType_; } /// Redoes data when sequence numbers change virtual void redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns); protected: /// data /// Number of members int numberMembers_; /// Number of Non SOS members i.e. fixing to zero is strong int numberNonSOSMembers_; /// Members (indices in range 0 ... numberIntegers_-1) int * members_; /** \brief Strong value for each member. This also specifies whether a variable has a +1 or -1 coefficient. - 0 => -1 coefficient, 0 is strong value - 1 => +1 coefficient, 1 is strong value If unspecified, all coefficients are assumed to be positive. Indexed as 0 .. numberMembers_-1 */ char * type_; /** \brief Clique type 0 defines a <= relation, 1 an equality. The assumed value of the rhs is numberNonSOSMembers_+1. (See comments for the class.) */ int cliqueType_; /** \brief Slack variable for the clique Identifies the slack variable for the clique (typically added to convert a <= relation to an equality). Value is sequence number within clique menbers. */ int slack_; }; /** Branching object for unordered cliques Intended for cliques which are long enough to make it worthwhile but <= 64 members. There will also be ones for long cliques. Variable_ is the clique id number (redundant, as the object also holds a pointer to the clique. */ class CbcCliqueBranchingObject : public CbcBranchingObject { public: // Default Constructor CbcCliqueBranchingObject (); // Useful constructor CbcCliqueBranchingObject (CbcModel * model, const CbcClique * clique, int way, int numberOnDownSide, const int * down, int numberOnUpSide, const int * up); // Copy constructor CbcCliqueBranchingObject ( const CbcCliqueBranchingObject &); // Assignment operator CbcCliqueBranchingObject & operator=( const CbcCliqueBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; // Destructor virtual ~CbcCliqueBranchingObject (); using CbcBranchingObject::branch ; /// Does next branch and updates state virtual double branch(); using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return CliqueBranchObj; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const; /** Compare the \c this with \c brObj. \c this and \c brObj must be of the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); private: /// data const CbcClique * clique_; /// downMask - bit set to fix to weak bounds, not set to leave unfixed unsigned int downMask_[2]; /// upMask - bit set to fix to weak bounds, not set to leave unfixed unsigned int upMask_[2]; }; /** Unordered Clique Branching Object class. These are for cliques which are > 64 members Variable is number of clique. */ class CbcLongCliqueBranchingObject : public CbcBranchingObject { public: // Default Constructor CbcLongCliqueBranchingObject (); // Useful constructor CbcLongCliqueBranchingObject (CbcModel * model, const CbcClique * clique, int way, int numberOnDownSide, const int * down, int numberOnUpSide, const int * up); // Copy constructor CbcLongCliqueBranchingObject ( const CbcLongCliqueBranchingObject &); // Assignment operator CbcLongCliqueBranchingObject & operator=( const CbcLongCliqueBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; // Destructor virtual ~CbcLongCliqueBranchingObject (); using CbcBranchingObject::branch ; /// Does next branch and updates state virtual double branch(); using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return LongCliqueBranchObj; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const; /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); private: /// data const CbcClique * clique_; /// downMask - bit set to fix to weak bounds, not set to leave unfixed unsigned int * downMask_; /// upMask - bit set to fix to weak bounds, not set to leave unfixed unsigned int * upMask_; }; #endif Cbc-2.8.12/src/CbcGenOsiParamUtils.cpp0000644000076600007660000003572412131315050016044 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenOsiParamUtils.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include "CoinFinite.hpp" #include "CoinParam.hpp" #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcGenCtlBlk.hpp" #include "CbcGenParam.hpp" #include "CbcGenCbcParam.hpp" #include "CbcGenOsiParam.hpp" /*! \file CbcOsiParamUtils \brief Implementation functions for CbcOsiParam parameters. */ namespace { char svnid[] = "$Id: CbcGenOsiParamUtils.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } namespace CbcOsiParamUtils { /* Function to set up OSI parameters. Does not include solver-specific parameters. ALGORITHM is commented out in CoinSolve. */ void addCbcOsiParams (int &numberParameters, CoinParamVec ¶meters, OsiSolverInterface *osi) { CbcOsiParam *param ; OsiHintParam key ; bool sense ; OsiHintStrength strength ; int ival ; double dval ; param = new CbcOsiParam(CbcOsiParam::KEEPNAMES, "keepN!ames", "Whether to keep row and column names on import.", "off", 1) ; param->appendKwd("on") ; param->setPushFunc(pushCbcOsiKwd) ; param->setObj(osi) ; param->setLongHelp( "Row and column names are human-friendly, but maintaining names takes up space and time. Specifying -keepnames off >before< importing a problem will discard any name information." ) ; parameters.push_back(param) ; (void) osi->getIntParam(OsiMaxNumIteration, ival) ; param = new CbcOsiParam(CbcOsiParam::MAXITERATION, "maxIt!erations", "Iteration limit for OSI solver.", 0, COIN_INT_MAX, ival) ; param->setPushFunc(pushCbcOsiInt) ; param->setObj(osi) ; param->setLongHelp( "Limits the number of iterations the OSI solver can perform when solving a problem." ) ; parameters.push_back(param) ; (void) osi->getIntParam(OsiMaxNumIterationHotStart, ival) ; param = new CbcOsiParam(CbcOsiParam::MAXHOTITS, "hot!StartMaxIts", "Iteration limit for OSI solver hot start.", 0, COIN_INT_MAX, ival) ; param->setPushFunc(pushCbcOsiInt) ; param->setObj(osi) ; param->setLongHelp( "Limits the number of iterations the OSI solver can perform when solving a problem from a hot start. In the context of cbc, this limits the number of iterations expended on each LP during strong branching." ) ; parameters.push_back(param) ; /* Simplified to on/off for OsiSolverInterface, where it goes in as a hint. */ (void) osi->getHintParam(OsiDoPresolveInInitial, sense, strength) ; if (sense == true) { ival = 1 ; } else { ival = 0 ; } param = new CbcOsiParam(CbcOsiParam::PRESOLVE, "presolve", "Whether to presolve problem", "off", ival) ; param->appendKwd("on") ; param->setPushFunc(pushCbcOsiHint) ; param->setObj(osi) ; param->setLongHelp( "Presolve analyzes the model to find such things as redundant constraints, constraints which fix some variables, constraints which can be transformed into bounds, etc. For the initial solve of any problem this is worth doing unless you know that it will have no effect." ) ; parameters.push_back(param) ; param = new CbcOsiParam(CbcOsiParam::PRIMALTOLERANCE, "primalT!olerance", "For an optimal solution no primal infeasibility may exceed this value", 1.0e-20, 1.0e12) ; param->setPushFunc(pushCbcOsiDbl) ; param->setObj(osi) ; param ->setLongHelp( "Normally the default tolerance is fine, but you may want to increase it a bit if a primal run seems to be having a hard time" ) ; parameters.push_back(param) ; /* Simplified for OsiSolverInterface, which just takes a hint. */ (void) osi->getHintParam(OsiDoScale, sense, strength) ; if (sense == true) { ival = 1 ; } else { ival = 0 ; } param = new CbcOsiParam(CbcOsiParam::SCALING, "scal!ing", "Whether to scale problem", "off", ival) ; param ->appendKwd("on") ; param->setPushFunc(pushCbcOsiHint) ; param->setObj(osi) ; param ->setLongHelp( "Scaling can help in solving problems which might otherwise fail because of lack of accuracy. It can also reduce the number of iterations. It is not applied if the range of elements is small. When unscaled it is possible that there may be small primal and/or infeasibilities." ) ; parameters.push_back(param) ; ival = osi->messageHandler()->logLevel() ; param = new CbcOsiParam(CbcOsiParam::SOLVERLOGLEVEL, "slog!Level", "Level of detail in Solver output", -1, 63, ival) ; param->setPushFunc(pushCbcOsiLogLevel) ; param->setObj(osi) ; param ->setLongHelp( "If 0 then there should be no output in normal circumstances. 1 is probably the best value for most uses, while 2 and 3 give more information." ) ; parameters.push_back(param) ; numberParameters = parameters.size() ; assert (numberParameters <= parameters.capacity()) ; } void loadOsiParamObj (const CoinParamVec paramVec, int first, int last, OsiSolverInterface *obj) { int i ; /* Load the OsiSolverInterface object into the parameters */ for (i = first ; i <= last ; i++) { CbcOsiParam *osiParam = dynamic_cast(paramVec[i]) ; assert (osiParam != 0) ; osiParam->setObj(obj) ; } return ; } /* Function to set default values for solver appropriate for cbc-generic. */ void setOsiSolverInterfaceDefaults (OsiSolverInterface *osi) { bool result ; /* OsiNameDiscipline isn't supported by all solvers, so check to see that it worked. If not, fall back to zero. */ osi->setIntParam(OsiMaxNumIteration, 1000000) ; osi->setIntParam(OsiMaxNumIterationHotStart, 1000) ; result = osi->setIntParam(OsiNameDiscipline, 1) ; if (!result) { result = osi->setIntParam(OsiNameDiscipline, 0) ; } /* Primal and dual feasibility tolerances (OsiPrimalTolerance and OsiDualTolerance, respectively) are left to the discretion of the solver. */ osi->setDblParam(OsiDualObjectiveLimit, 1.0e100) ; osi->setDblParam(OsiPrimalObjectiveLimit, 1.0e100) ; osi->setDblParam(OsiObjOffset, 0.0) ; osi->setHintParam(OsiDoPresolveInInitial, true, OsiHintDo) ; osi->setHintParam(OsiDoDualInInitial, true, OsiHintIgnore) ; osi->setHintParam(OsiDoPresolveInResolve, false, OsiHintTry) ; osi->setHintParam(OsiDoDualInInitial, true, OsiHintTry) ; osi->setHintParam(OsiDoScale, true, OsiHintDo) ; osi->setHintParam(OsiDoCrash, true, OsiHintIgnore) ; osi->setHintParam(OsiDoReducePrint, true, OsiHintDo) ; osi->setHintParam(OsiDoInBranchAndCut, true, OsiHintTry) ; return ; } /* Function to push an integer parameter. */ int pushCbcOsiInt (CoinParam *param) { assert (param != 0) ; CbcOsiParam *osiParam = dynamic_cast(param) ; assert (osiParam != 0) ; OsiSolverInterface *osi = osiParam->obj() ; assert (osi != 0) ; int val = osiParam->intVal() ; CbcOsiParam::CbcOsiParamCode code = osiParam->paramCode() ; assert (osi != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default, so that all we need to do is correct to 0 (no error) if we're successful. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* Translate the parameter code from CbcOsiParamCode into the correct key for CbcIntParam. */ OsiIntParam key ; switch (code) { case CbcOsiParam::MAXITERATION: { key = OsiMaxNumIteration ; break ; } case CbcOsiParam::MAXHOTITS: { key = OsiMaxNumIterationHotStart ; break ; } default: { std::cerr << "pushCbcOsiIntParam: no equivalent OsiIntParam for " << "parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } bool setOK = osi->setIntParam(key, val) ; if (setOK == false) { retval = -1 ; } return (retval) ; } /* Function to push a double parameter. */ int pushCbcOsiDbl (CoinParam *param) { assert (param != 0) ; CbcOsiParam *osiParam = dynamic_cast(param) ; assert (osiParam != 0) ; OsiSolverInterface *osi = osiParam->obj() ; assert (osi != 0) ; double val = osiParam->dblVal() ; CbcOsiParam::CbcOsiParamCode code = osiParam->paramCode() ; assert (osi != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default, so that all we need to do is correct to 0 (no error) if we're successful. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* Translate the parameter code from CbcOsiParamCode into the correct key for CbcDblParam. */ OsiDblParam key ; switch (code) { case CbcOsiParam::PRIMALTOLERANCE: { key = OsiPrimalTolerance ; break ; } case CbcOsiParam::DUALTOLERANCE: { key = OsiDualTolerance ; ; break ; } case CbcOsiParam::DUALBOUND: { key = OsiDualObjectiveLimit ; break ; } default: { std::cerr << "pushCbcOsiDblParam: no equivalent OsiDblParam for " << "parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } bool setOK = osi->setDblParam(key, val) ; if (setOK == false) { retval = -1 ; } return (retval) ; } /* Function to push a keyword-valued parameter. This can translate into integer as well as string-valued parameters. */ int pushCbcOsiKwd (CoinParam *param) { assert (param != 0) ; CbcOsiParam *osiParam = dynamic_cast(param) ; assert (osiParam != 0) ; OsiSolverInterface *osi = osiParam->obj() ; assert (osi != 0) ; std::string str = osiParam->kwdVal() ; CbcOsiParam::CbcOsiParamCode code = osiParam->paramCode() ; int retval = 0 ; /* Figure out what we're doing and set the relevant field. */ OsiIntParam key ; switch (code) { case CbcOsiParam::KEEPNAMES: { if (str == "on" || str == "off") { int discipline ; if (str == "on") { discipline = 1 ; } else { discipline = 0 ; } bool recog = osi->setIntParam(OsiNameDiscipline, discipline) ; if (recog == false) { std::cerr << "pushCbcOsiKwdParam(KEEPNAMES): underlying solver does not " << "recognise name discipline " << discipline << "." << std::endl ; retval = +1 ; } } else { std::cerr << "pushCbcOsiKwdParam(KEEPNAMES): unrecognised keyword `" << str << "'." << std::endl ; retval = -1 ; } break ; } default: { std::cerr << "pushCbcGenKwdParam: unrecognised parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } return (retval) ; } /* Function to set the solver's output level. To cover all the bases, adjust the message handler and set the hint. Nothing can go fatally wrong here, but we'll return non-fatal error if the solver rejects the hint. The implementor of an OSI has wide latitude with hints, and may elect to set a log level as part of handling the hint. Do that first and then explicitly set the message handler log level to be sure the new value isn't overridden. */ int pushCbcOsiLogLevel (CoinParam *param) { assert (param != 0) ; CbcOsiParam *osiParam = dynamic_cast(param) ; assert (osiParam != 0) ; OsiSolverInterface *osi = osiParam->obj() ; assert(osi != 0) ; int lvl = param->intVal() ; /* Setup to return nonfatal/fatal error (1/-1) by default, so that all we need to do is correct to 0 (no error) if we're successful. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* Now try to do the right thing with a hint. Harder to say -- assume that log level 1 is `normal'. */ OsiHintStrength strength ; bool sense ; if (lvl < 1) { strength = OsiHintDo ; sense = true ; } else if (lvl == 1) { strength = OsiHintIgnore ; sense = true ; } else if (lvl == 2) { strength = OsiHintTry ; sense = false ; } else { strength = OsiHintDo ; sense = false ; } bool setOK = osi->setHintParam(OsiDoReducePrint, sense, strength) ; /* Recover the message handler and set the log level directly. */ CoinMessageHandler *hndl = osi->messageHandler() ; assert (hndl != 0) ; hndl->setLogLevel(lvl) ; if (setOK) { return (0) ; } else { return (retval) ; } } /* Function for parameters that are enabled/disabled with a hint. */ int pushCbcOsiHint (CoinParam *param) { assert (param != 0) ; CbcOsiParam *osiParam = dynamic_cast(param) ; assert (osiParam != 0) ; OsiSolverInterface *osi = osiParam->obj() ; assert(osi != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default, so that all we need to do is correct to 0 (no error) if we're successful. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* Set the sense for the hint. */ std::string kwd = param->kwdVal() ; bool sense ; if (kwd == "off") { sense = false ; } else { sense = true ; } /* Grab the parameter code and translate to an OSI parameter key. */ CbcOsiParam::CbcOsiParamCode code = osiParam->paramCode() ; OsiHintParam key ; switch (code) { case CbcOsiParam::PRESOLVE: { key = OsiDoPresolveInInitial ; break ; } case CbcOsiParam::SCALING: { key = OsiDoScale ; break ; } default: { std::cerr << "pushCbcOsiHint: no equivalent OsiHintParam for " << "parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } bool setOK = osi->setHintParam(key, sense, OsiHintDo) ; if (setOK) { return (0) ; } else { return (retval) ; } } } // end namespace CbcOsiParamUtils Cbc-2.8.12/src/CbcGeneralDepth.cpp0000644000076600007660000006361612131315050015221 0ustar coincoin// $Id: CbcGeneralDepth.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcGeneralDepth.hpp" #include "CbcBranchActual.hpp" #include "CbcHeuristicDive.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #include "CoinWarmStartBasis.hpp" #include "ClpNode.hpp" #include "CbcBranchDynamic.hpp" // Default Constructor CbcGeneralDepth::CbcGeneralDepth () : CbcGeneral(), maximumDepth_(0), maximumNodes_(0), whichSolution_(-1), numberNodes_(0), nodeInfo_(NULL) { } // Useful constructor (which are integer indices) CbcGeneralDepth::CbcGeneralDepth (CbcModel * model, int maximumDepth) : CbcGeneral(model), maximumDepth_(maximumDepth), maximumNodes_(0), whichSolution_(-1), numberNodes_(0), nodeInfo_(NULL) { assert(maximumDepth_ < 1000000); if (maximumDepth_ > 0) maximumNodes_ = (1 << maximumDepth_) + 1 + maximumDepth_; else if (maximumDepth_ < 0) maximumNodes_ = 1 + 1 - maximumDepth_; else maximumNodes_ = 0; #define MAX_NODES 100 maximumNodes_ = CoinMin(maximumNodes_, 1 + maximumDepth_ + MAX_NODES); if (maximumNodes_) { nodeInfo_ = new ClpNodeStuff(); nodeInfo_->maximumNodes_ = maximumNodes_; ClpNodeStuff * info = nodeInfo_; // for reduced costs and duals info->solverOptions_ |= 7; if (maximumDepth_ > 0) { info->nDepth_ = maximumDepth_; } else { info->nDepth_ = - maximumDepth_; info->solverOptions_ |= 32; } ClpNode ** nodeInfo = new ClpNode * [maximumNodes_]; for (int i = 0; i < maximumNodes_; i++) nodeInfo[i] = NULL; info->nodeInfo_ = nodeInfo; } else { nodeInfo_ = NULL; } } // Copy constructor CbcGeneralDepth::CbcGeneralDepth ( const CbcGeneralDepth & rhs) : CbcGeneral(rhs) { maximumDepth_ = rhs.maximumDepth_; maximumNodes_ = rhs.maximumNodes_; whichSolution_ = -1; numberNodes_ = 0; if (maximumNodes_) { assert (rhs.nodeInfo_); nodeInfo_ = new ClpNodeStuff(*rhs.nodeInfo_); nodeInfo_->maximumNodes_ = maximumNodes_; ClpNodeStuff * info = nodeInfo_; if (maximumDepth_ > 0) { info->nDepth_ = maximumDepth_; } else { info->nDepth_ = - maximumDepth_; info->solverOptions_ |= 32; } if (!info->nodeInfo_) { ClpNode ** nodeInfo = new ClpNode * [maximumNodes_]; for (int i = 0; i < maximumNodes_; i++) nodeInfo[i] = NULL; info->nodeInfo_ = nodeInfo; } } else { nodeInfo_ = NULL; } } // Clone CbcObject * CbcGeneralDepth::clone() const { return new CbcGeneralDepth(*this); } // Assignment operator CbcGeneralDepth & CbcGeneralDepth::operator=( const CbcGeneralDepth & rhs) { if (this != &rhs) { CbcGeneral::operator=(rhs); delete nodeInfo_; maximumDepth_ = rhs.maximumDepth_; maximumNodes_ = rhs.maximumNodes_; whichSolution_ = -1; numberNodes_ = 0; if (maximumDepth_) { assert (rhs.nodeInfo_); nodeInfo_ = new ClpNodeStuff(*rhs.nodeInfo_); nodeInfo_->maximumNodes_ = maximumNodes_; } else { nodeInfo_ = NULL; } } return *this; } // Destructor CbcGeneralDepth::~CbcGeneralDepth () { delete nodeInfo_; } // Infeasibility - large is 0.5 double CbcGeneralDepth::infeasibility(const OsiBranchingInformation * /*info*/, int &/*preferredWay*/) const { whichSolution_ = -1; // should use genuine OsiBranchingInformation usefulInfo = model_->usefulInformation(); // for now assume only called when correct //if (usefulInfo.depth_>=4&&!model_->parentModel() // &&(usefulInfo.depth_%2)==0) { if (true) { OsiSolverInterface * solver = model_->solver(); OsiClpSolverInterface * clpSolver = dynamic_cast (solver); if (clpSolver) { if ((model_->moreSpecialOptions()&33554432)==0) { ClpNodeStuff * info = nodeInfo_; info->integerTolerance_ = model_->getIntegerTolerance(); info->integerIncrement_ = model_->getCutoffIncrement(); info->numberBeforeTrust_ = model_->numberBeforeTrust(); info->stateOfSearch_ = model_->stateOfSearch(); // Compute "small" change in branch int nBranches = model_->getIntParam(CbcModel::CbcNumberBranches); if (nBranches) { double average = model_->getDblParam(CbcModel::CbcSumChange) / static_cast(nBranches); info->smallChange_ = CoinMax(average * 1.0e-5, model_->getDblParam(CbcModel::CbcSmallestChange)); info->smallChange_ = CoinMax(info->smallChange_, 1.0e-8); } else { info->smallChange_ = 1.0e-8; } int numberIntegers = model_->numberIntegers(); double * down = new double[numberIntegers]; double * up = new double[numberIntegers]; int * priority = new int[numberIntegers]; int * numberDown = new int[numberIntegers]; int * numberUp = new int[numberIntegers]; int * numberDownInfeasible = new int[numberIntegers]; int * numberUpInfeasible = new int[numberIntegers]; model_->fillPseudoCosts(down, up, priority, numberDown, numberUp, numberDownInfeasible, numberUpInfeasible); info->fillPseudoCosts(down, up, priority, numberDown, numberUp, numberDownInfeasible, numberUpInfeasible, numberIntegers); info->presolveType_ = 1; delete [] down; delete [] up; delete [] numberDown; delete [] numberUp; delete [] numberDownInfeasible; delete [] numberUpInfeasible; bool takeHint; OsiHintStrength strength; solver->getHintParam(OsiDoReducePrint, takeHint, strength); ClpSimplex * simplex = clpSolver->getModelPtr(); int saveLevel = simplex->logLevel(); if (strength != OsiHintIgnore && takeHint && saveLevel == 1) simplex->setLogLevel(0); clpSolver->setBasis(); whichSolution_ = simplex->fathomMany(info); //printf("FAT %d nodes, %d iterations\n", //info->numberNodesExplored_,info->numberIterations_); //printf("CbcBranch %d rows, %d columns\n",clpSolver->getNumRows(), // clpSolver->getNumCols()); model_->incrementExtra(info->numberNodesExplored_, info->numberIterations_); // update pseudo costs double smallest = 1.0e50; double largest = -1.0; OsiObject ** objects = model_->objects(); #ifndef NDEBUG const int * integerVariable = model_->integerVariable(); #endif for (int i = 0; i < numberIntegers; i++) { #ifndef NDEBUG CbcSimpleIntegerDynamicPseudoCost * obj = dynamic_cast (objects[i]) ; assert (obj && obj->columnNumber() == integerVariable[i]); #else CbcSimpleIntegerDynamicPseudoCost * obj = static_cast (objects[i]) ; #endif if (info->numberUp_[i] > 0) { if (info->downPseudo_[i] > largest) largest = info->downPseudo_[i]; if (info->downPseudo_[i] < smallest) smallest = info->downPseudo_[i]; if (info->upPseudo_[i] > largest) largest = info->upPseudo_[i]; if (info->upPseudo_[i] < smallest) smallest = info->upPseudo_[i]; obj->updateAfterMini(info->numberDown_[i], info->numberDownInfeasible_[i], info->downPseudo_[i], info->numberUp_[i], info->numberUpInfeasible_[i], info->upPseudo_[i]); } } //printf("range of costs %g to %g\n",smallest,largest); simplex->setLogLevel(saveLevel); numberNodes_ = info->nNodes_; } else { // Try diving // See if any diving heuristics set to do dive+save CbcHeuristicDive * dive=NULL; for (int i = 0; i < model_->numberHeuristics(); i++) { CbcHeuristicDive * possible = dynamic_cast(model_->heuristic(i)); if (possible&&possible->maxSimplexIterations()==COIN_INT_MAX) { // if more than one then rotate later? //if (possible->canHeuristicRun()) { dive=possible; break; } } assert (dive); // otherwise moreSpecial should have been turned off CbcSubProblem ** nodes=NULL; int branchState=dive->fathom(model_,numberNodes_,nodes); if (branchState) { printf("new solution\n"); whichSolution_=numberNodes_-1; } else { whichSolution_=-1; } #if 0 if (0) { for (int iNode=0;iNodepush(nodes[iNode]) ; } assert (node->nodeInfo()); if (node->nodeInfo()->numberBranchesLeft()) { tree_->push(node) ; } else { node->setActive(false); } } #endif //delete [] nodes; model_->setTemporaryPointer(reinterpret_cast(nodes)); // end try diving } int numberDo = numberNodes_; if (numberDo > 0 || whichSolution_ >= 0) { return 0.5; } else { // no solution return COIN_DBL_MAX; // say infeasible } } else { return -1.0; } } else { return -1.0; } } // This looks at solution and sets bounds to contain solution void CbcGeneralDepth::feasibleRegion() { // Other stuff should have done this } // Redoes data when sequence numbers change void CbcGeneralDepth::redoSequenceEtc(CbcModel * /*model*/, int /*numberColumns*/, const int * /*originalColumns*/) { } //#define CHECK_PATH #ifdef CHECK_PATH extern const double * debuggerSolution_Z; extern int numberColumns_Z; extern int gotGoodNode_Z; #endif CbcBranchingObject * CbcGeneralDepth::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int /*way*/) { int numberDo = numberNodes_; if (whichSolution_ >= 0 && (model_->moreSpecialOptions()&33554432)==0) numberDo--; assert (numberDo > 0); // create object CbcGeneralBranchingObject * branch = new CbcGeneralBranchingObject(model_); // skip solution branch->numberSubProblems_ = numberDo; // If parentBranch_ back in then will have to be 2* branch->numberSubLeft_ = numberDo; branch->setNumberBranches(numberDo); CbcSubProblem * sub = new CbcSubProblem[numberDo]; int iProb = 0; branch->subProblems_ = sub; branch->numberRows_ = model_->solver()->getNumRows(); int iNode; //OsiSolverInterface * solver = model_->solver(); OsiClpSolverInterface * clpSolver = dynamic_cast (solver); assert (clpSolver); ClpSimplex * simplex = clpSolver->getModelPtr(); int numberColumns = simplex->numberColumns(); if ((model_->moreSpecialOptions()&33554432)==0) { double * lowerBefore = CoinCopyOfArray(simplex->getColLower(), numberColumns); double * upperBefore = CoinCopyOfArray(simplex->getColUpper(), numberColumns); ClpNodeStuff * info = nodeInfo_; double * weight = new double[numberNodes_]; int * whichNode = new int [numberNodes_]; // Sort for (iNode = 0; iNode < numberNodes_; iNode++) { if (iNode != whichSolution_) { double objectiveValue = info->nodeInfo_[iNode]->objectiveValue(); double sumInfeasibilities = info->nodeInfo_[iNode]->sumInfeasibilities(); int numberInfeasibilities = info->nodeInfo_[iNode]->numberInfeasibilities(); double thisWeight = 0.0; #if 1 // just closest thisWeight = 1.0e9 * numberInfeasibilities; thisWeight += sumInfeasibilities; thisWeight += 1.0e-7 * objectiveValue; // Try estimate thisWeight = info->nodeInfo_[iNode]->estimatedSolution(); #else thisWeight = 1.0e-3 * numberInfeasibilities; thisWeight += 1.0e-5 * sumInfeasibilities; thisWeight += objectiveValue; #endif whichNode[iProb] = iNode; weight[iProb++] = thisWeight; } } assert (iProb == numberDo); CoinSort_2(weight, weight + numberDo, whichNode); for (iProb = 0; iProb < numberDo; iProb++) { iNode = whichNode[iProb]; ClpNode * node = info->nodeInfo_[iNode]; // move bounds node->applyNode(simplex, 3); // create subproblem sub[iProb] = CbcSubProblem(clpSolver, lowerBefore, upperBefore, node->statusArray(), node->depth()); sub[iProb].objectiveValue_ = node->objectiveValue(); sub[iProb].sumInfeasibilities_ = node->sumInfeasibilities(); sub[iProb].numberInfeasibilities_ = node->numberInfeasibilities(); #ifdef CHECK_PATH if (simplex->numberColumns() == numberColumns_Z) { bool onOptimal = true; const double * columnLower = simplex->columnLower(); const double * columnUpper = simplex->columnUpper(); for (int i = 0; i < numberColumns_Z; i++) { if (iNode == gotGoodNode_Z) printf("good %d %d %g %g\n", iNode, i, columnLower[i], columnUpper[i]); if (columnUpper[i] < debuggerSolution_Z[i] || columnLower[i] > debuggerSolution_Z[i] && simplex->isInteger(i)) { onOptimal = false; break; } } if (onOptimal) { printf("adding to node %x as %d - objs\n", this, iProb); for (int j = 0; j <= iProb; j++) printf("%d %g\n", j, sub[j].objectiveValue_); } } #endif } delete [] weight; delete [] whichNode; const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); // restore bounds for ( int j = 0; j < numberColumns; j++) { if (lowerBefore[j] != lower[j]) solver->setColLower(j, lowerBefore[j]); if (upperBefore[j] != upper[j]) solver->setColUpper(j, upperBefore[j]); } delete [] upperBefore; delete [] lowerBefore; } else { // from diving CbcSubProblem ** nodes = reinterpret_cast (model_->temporaryPointer()); assert (nodes); int adjustDepth=info->depth_; assert (numberDo); numberNodes_=0; for (iProb = 0; iProb < numberDo; iProb++) { if ((nodes[iProb]->problemStatus_&2)==0) { // create subproblem (and swap way and/or make inactive) sub[numberNodes_].takeOver(*nodes[iProb],true); // but adjust depth sub[numberNodes_].depth_+=adjustDepth; numberNodes_++; } delete nodes[iProb]; } branch->numberSubProblems_ = numberNodes_; branch->numberSubLeft_ = numberNodes_; branch->setNumberBranches(numberNodes_); if (!numberNodes_) { // infeasible delete branch; branch=NULL; } delete [] nodes; } return branch; } // Default Constructor CbcGeneralBranchingObject::CbcGeneralBranchingObject() : CbcBranchingObject(), subProblems_(NULL), node_(NULL), numberSubProblems_(0), numberSubLeft_(0), whichNode_(-1), numberRows_(0) { // printf("CbcGeneral %x default constructor\n",this); } // Useful constructor CbcGeneralBranchingObject::CbcGeneralBranchingObject (CbcModel * model) : CbcBranchingObject(model, -1, -1, 0.5), subProblems_(NULL), node_(NULL), numberSubProblems_(0), numberSubLeft_(0), whichNode_(-1), numberRows_(0) { //printf("CbcGeneral %x useful constructor\n",this); } // Copy constructor CbcGeneralBranchingObject::CbcGeneralBranchingObject ( const CbcGeneralBranchingObject & rhs) : CbcBranchingObject(rhs), subProblems_(NULL), node_(rhs.node_), numberSubProblems_(rhs.numberSubProblems_), numberSubLeft_(rhs.numberSubLeft_), whichNode_(rhs.whichNode_), numberRows_(rhs.numberRows_) { abort(); if (numberSubProblems_) { subProblems_ = new CbcSubProblem[numberSubProblems_]; for (int i = 0; i < numberSubProblems_; i++) subProblems_[i] = rhs.subProblems_[i]; } } // Assignment operator CbcGeneralBranchingObject & CbcGeneralBranchingObject::operator=( const CbcGeneralBranchingObject & rhs) { if (this != &rhs) { abort(); CbcBranchingObject::operator=(rhs); delete [] subProblems_; numberSubProblems_ = rhs.numberSubProblems_; numberSubLeft_ = rhs.numberSubLeft_; whichNode_ = rhs.whichNode_; numberRows_ = rhs.numberRows_; if (numberSubProblems_) { subProblems_ = new CbcSubProblem[numberSubProblems_]; for (int i = 0; i < numberSubProblems_; i++) subProblems_[i] = rhs.subProblems_[i]; } else { subProblems_ = NULL; } node_ = rhs.node_; } return *this; } CbcBranchingObject * CbcGeneralBranchingObject::clone() const { return (new CbcGeneralBranchingObject(*this)); } // Destructor CbcGeneralBranchingObject::~CbcGeneralBranchingObject () { //printf("CbcGeneral %x destructor\n",this); delete [] subProblems_; } bool doingDoneBranch = false; double CbcGeneralBranchingObject::branch() { double cutoff = model_->getCutoff(); //printf("GenB %x whichNode %d numberLeft %d which %d\n", // this,whichNode_,numberBranchesLeft(),branchIndex()); if (whichNode_ < 0) { assert (node_); bool applied = false; while (numberBranchesLeft()) { int which = branchIndex(); decrementNumberBranchesLeft(); CbcSubProblem * thisProb = subProblems_ + which; if (thisProb->objectiveValue_ < cutoff) { //printf("branch %x (sub %x) which now %d\n",this, // subProblems_,which); OsiSolverInterface * solver = model_->solver(); thisProb->apply(solver); OsiClpSolverInterface * clpSolver = dynamic_cast (solver); assert (clpSolver); // Move status to basis clpSolver->setWarmStart(NULL); //ClpSimplex * simplex = clpSolver->getModelPtr(); node_->setObjectiveValue(thisProb->objectiveValue_); node_->setSumInfeasibilities(thisProb->sumInfeasibilities_); node_->setNumberUnsatisfied(thisProb->numberInfeasibilities_); applied = true; doingDoneBranch = true; break; } else if (numberBranchesLeft()) { node_->nodeInfo()->branchedOn() ; } } if (!applied) { // no good one node_->setObjectiveValue(cutoff + 1.0e20); node_->setSumInfeasibilities(1.0); node_->setNumberUnsatisfied(1); assert (whichNode_ < 0); } } else { decrementNumberBranchesLeft(); CbcSubProblem * thisProb = subProblems_ + whichNode_; assert (thisProb->objectiveValue_ < cutoff); OsiSolverInterface * solver = model_->solver(); thisProb->apply(solver); //OsiClpSolverInterface * clpSolver //= dynamic_cast (solver); //assert (clpSolver); // Move status to basis //clpSolver->setWarmStart(NULL); } return 0.0; } /* Double checks in case node can change its mind! Can change objective etc */ void CbcGeneralBranchingObject::checkIsCutoff(double cutoff) { assert (node_); int first = branchIndex(); int last = first + numberBranchesLeft(); for (int which = first; which < last; which++) { CbcSubProblem * thisProb = subProblems_ + which; if (thisProb->objectiveValue_ < cutoff) { node_->setObjectiveValue(thisProb->objectiveValue_); node_->setSumInfeasibilities(thisProb->sumInfeasibilities_); node_->setNumberUnsatisfied(thisProb->numberInfeasibilities_); break; } } } // Print what would happen void CbcGeneralBranchingObject::print() { //printf("CbcGeneralObject has %d subproblems\n",numberSubProblems_); } // Fill in current objective etc void CbcGeneralBranchingObject::state(double & objectiveValue, double & sumInfeasibilities, int & numberUnsatisfied, int which) const { assert (which >= 0 && which < numberSubProblems_); const CbcSubProblem * thisProb = subProblems_ + which; objectiveValue = thisProb->objectiveValue_; sumInfeasibilities = thisProb->sumInfeasibilities_; numberUnsatisfied = thisProb->numberInfeasibilities_; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcGeneralBranchingObject::compareOriginalObject (const CbcBranchingObject* /*brObj*/) const { throw("must implement"); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcGeneralBranchingObject::compareBranchingObject (const CbcBranchingObject* /*brObj*/, const bool /*replaceIfOverlap*/) { throw("must implement"); } // Default Constructor CbcOneGeneralBranchingObject::CbcOneGeneralBranchingObject() : CbcBranchingObject(), object_(NULL), whichOne_(-1) { //printf("CbcOneGeneral %x default constructor\n",this); } // Useful constructor CbcOneGeneralBranchingObject::CbcOneGeneralBranchingObject (CbcModel * model, CbcGeneralBranchingObject * object, int whichOne) : CbcBranchingObject(model, -1, -1, 0.5), object_(object), whichOne_(whichOne) { //printf("CbcOneGeneral %x useful constructor object %x %d left\n",this, // object_,object_->numberSubLeft_); numberBranches_ = 1; } // Copy constructor CbcOneGeneralBranchingObject::CbcOneGeneralBranchingObject ( const CbcOneGeneralBranchingObject & rhs) : CbcBranchingObject(rhs), object_(rhs.object_), whichOne_(rhs.whichOne_) { } // Assignment operator CbcOneGeneralBranchingObject & CbcOneGeneralBranchingObject::operator=( const CbcOneGeneralBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); object_ = rhs.object_; whichOne_ = rhs.whichOne_; } return *this; } CbcBranchingObject * CbcOneGeneralBranchingObject::clone() const { return (new CbcOneGeneralBranchingObject(*this)); } // Destructor CbcOneGeneralBranchingObject::~CbcOneGeneralBranchingObject () { //printf("CbcOneGeneral %x destructor object %x %d left\n",this, // object_,object_->numberSubLeft_); assert (object_->numberSubLeft_ > 0 && object_->numberSubLeft_ < 1000000); if (!object_->decrementNumberLeft()) { // printf("CbcGeneral %x yy destructor\n",object_); delete object_; } } double CbcOneGeneralBranchingObject::branch() { assert (numberBranchesLeft()); decrementNumberBranchesLeft(); assert (!numberBranchesLeft()); object_->setWhichNode(whichOne_); object_->branch(); return 0.0; } /* Double checks in case node can change its mind! Can change objective etc */ void CbcOneGeneralBranchingObject::checkIsCutoff(double /*cutoff*/) { assert (numberBranchesLeft()); } // Print what would happen void CbcOneGeneralBranchingObject::print() { //printf("CbcOneGeneralObject has 1 subproblem\n"); } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcOneGeneralBranchingObject::compareOriginalObject (const CbcBranchingObject* /*brObj*/) const { throw("must implement"); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcOneGeneralBranchingObject::compareBranchingObject (const CbcBranchingObject* /*brObj*/, const bool /*replaceIfOverlap*/) { throw("must implement"); } #endif Cbc-2.8.12/src/CbcStatistics.hpp0000644000076600007660000000502311510742604015013 0ustar coincoin/* $Id: CbcStatistics.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcStatistics_H #define CbcStatistics_H #include "CbcModel.hpp" /** For gathering statistics */ class CbcStatistics { public: // Default Constructor CbcStatistics (); // Branch CbcStatistics(CbcNode * node, CbcModel * model); ~CbcStatistics(); // Copy CbcStatistics(const CbcStatistics & rhs); // Assignment CbcStatistics& operator=(const CbcStatistics & rhs); // Update at end of branch void endOfBranch(int numberIterations, double objectiveValue); // Update number of infeasibilities void updateInfeasibility(int numberInfeasibilities); // Branch found to be infeasible by chooseBranch void sayInfeasible(); // Just prints void print(const int * sequenceLookup = NULL) const; // Node number inline int node() const { return id_; } // Parent node number inline int parentNode() const { return parentId_; } // depth inline int depth() const { return depth_; } // way inline int way() const { return way_; } // value inline double value() const { return value_; } // starting objective inline double startingObjective() const { return startingObjective_; } // Unsatisfied at beginning inline int startingInfeasibility() const { return startingInfeasibility_; } // starting objective inline double endingObjective() const { return endingObjective_; } // Unsatisfied at end inline int endingInfeasibility() const { return endingInfeasibility_; } // Number iterations inline int numberIterations() const { return numberIterations_; } protected: // Data /// Value double value_; /// Starting objective double startingObjective_; /// Ending objective double endingObjective_; /// id int id_; /// parent id int parentId_; /// way -1 or +1 is first branch -10 or +10 is second branch int way_; /// sequence number branched on int sequence_; /// depth int depth_; /// starting number of integer infeasibilities int startingInfeasibility_; /// ending number of integer infeasibilities int endingInfeasibility_; /// number of iterations int numberIterations_; }; #endif Cbc-2.8.12/src/CbcHeuristicLocal.cpp0000644000076600007660000016352412075572125015607 0ustar coincoin/* $Id: CbcHeuristicLocal.cpp 1839 2013-01-16 18:41:25Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcHeuristicLocal.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcBranchActual.hpp" #include "CbcStrategy.hpp" #include "CglPreProcess.hpp" // Default Constructor CbcHeuristicLocal::CbcHeuristicLocal() : CbcHeuristic() { numberSolutions_ = 0; swap_ = 0; used_ = NULL; lastRunDeep_ = -1000000; switches_ |= 16; // needs a new solution } // Constructor with model - assumed before cuts CbcHeuristicLocal::CbcHeuristicLocal(CbcModel & model) : CbcHeuristic(model) { numberSolutions_ = 0; swap_ = 0; lastRunDeep_ = -1000000; switches_ |= 16; // needs a new solution // Get a copy of original matrix assert(model.solver()); if (model.solver()->getNumRows()) { matrix_ = *model.solver()->getMatrixByCol(); } int numberColumns = model.solver()->getNumCols(); used_ = new int[numberColumns]; memset(used_, 0, numberColumns*sizeof(int)); } // Destructor CbcHeuristicLocal::~CbcHeuristicLocal () { delete [] used_; } // Clone CbcHeuristic * CbcHeuristicLocal::clone() const { return new CbcHeuristicLocal(*this); } // Create C++ lines to get to current state void CbcHeuristicLocal::generateCpp( FILE * fp) { CbcHeuristicLocal other; fprintf(fp, "0#include \"CbcHeuristicLocal.hpp\"\n"); fprintf(fp, "3 CbcHeuristicLocal heuristicLocal(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicLocal"); if (swap_ != other.swap_) fprintf(fp, "3 heuristicLocal.setSearchType(%d);\n", swap_); else fprintf(fp, "4 heuristicLocal.setSearchType(%d);\n", swap_); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicLocal);\n"); } // Copy constructor CbcHeuristicLocal::CbcHeuristicLocal(const CbcHeuristicLocal & rhs) : CbcHeuristic(rhs), matrix_(rhs.matrix_), numberSolutions_(rhs.numberSolutions_), swap_(rhs.swap_) { if (model_ && rhs.used_) { int numberColumns = model_->solver()->getNumCols(); used_ = CoinCopyOfArray(rhs.used_, numberColumns); } else { used_ = NULL; } } // Assignment operator CbcHeuristicLocal & CbcHeuristicLocal::operator=( const CbcHeuristicLocal & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); matrix_ = rhs.matrix_; numberSolutions_ = rhs.numberSolutions_; swap_ = rhs.swap_; delete [] used_; if (model_ && rhs.used_) { int numberColumns = model_->solver()->getNumCols(); used_ = CoinCopyOfArray(rhs.used_, numberColumns); } else { used_ = NULL; } } return *this; } // Resets stuff if model changes void CbcHeuristicLocal::resetModel(CbcModel * /*model*/) { //CbcHeuristic::resetModel(model); delete [] used_; if (model_ && used_) { int numberColumns = model_->solver()->getNumCols(); used_ = new int[numberColumns]; memset(used_, 0, numberColumns*sizeof(int)); } else { used_ = NULL; } } /* Run a mini-BaB search after fixing all variables not marked as used by solution(). (See comments there for semantics.) Return values are: 1: smallBranchAndBound found a solution 0: everything else The degree of overload as return codes from smallBranchAndBound are folded into 0 is such that it's impossible to distinguish return codes that really require attention from a simple `nothing of interest'. */ // This version fixes stuff and does IP int CbcHeuristicLocal::solutionFix(double & objectiveValue, double * newSolution, const int * /*keep*/) { /* If when is set to off (0), or set to root (1) and we're not at the root, return. If this heuristic discovered the current solution, don't continue. */ numCouldRun_++; // See if to do if (!when() || (when() == 1 && model_->phase() != 1)) return 0; // switched off // Don't do if it was this heuristic which found solution! if (this == model_->lastHeuristic()) return 0; /* Load up a new solver with the solution. Why continuousSolver(), as opposed to solver()? */ OsiSolverInterface * newSolver = model_->continuousSolver()->clone(); const double * colLower = newSolver->getColLower(); //const double * colUpper = newSolver->getColUpper(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); /* The net effect here is that anything that hasn't moved from its lower bound will be fixed at lower bound. See comments in solution() w.r.t. asymmetric treatment of upper and lower bounds. */ int i; int nFix = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); newSolver->setColLower(iColumn, CoinMax(colLower[iColumn], originalLower)); if (!used_[iColumn]) { newSolver->setColUpper(iColumn, colLower[iColumn]); nFix++; } } /* Try a `small' branch-and-bound search. The notion here is that we've fixed a lot of variables and reduced the amount of `free' problem to a point where a small BaB search will suffice to fully explore the remaining problem. This routine will execute integer presolve, then call branchAndBound to do the actual search. */ int returnCode = 0; #ifdef CLP_INVESTIGATE2 printf("Fixing %d out of %d (%d continuous)\n", nFix, numberIntegers, newSolver->getNumCols() - numberIntegers); #endif if (nFix*10 <= numberIntegers) { // see if we can fix more int * which = new int [2*(numberIntegers-nFix)]; int * sort = which + (numberIntegers - nFix); int n = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (used_[iColumn]) { which[n] = iColumn; sort[n++] = used_[iColumn]; } } CoinSort_2(sort, sort + n, which); // only half fixed in total n = CoinMin(n, numberIntegers / 2 - nFix); int allow = CoinMax(numberSolutions_ - 2, sort[0]); int nFix2 = 0; for (i = 0; i < n; i++) { int iColumn = integerVariable[i]; if (used_[iColumn] <= allow) { newSolver->setColUpper(iColumn, colLower[iColumn]); nFix2++; } else { break; } } delete [] which; nFix += nFix2; #ifdef CLP_INVESTIGATE2 printf("Number fixed increased from %d to %d\n", nFix - nFix2, nFix); #endif } if (nFix*10 > numberIntegers) { returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, objectiveValue, objectiveValue, "CbcHeuristicLocal"); /* -2 is return due to user event, and -1 is overloaded with what look to be two contradictory meanings. */ if (returnCode < 0) { returnCode = 0; // returned on size int numberColumns = newSolver->getNumCols(); int numberContinuous = numberColumns - numberIntegers; if (numberContinuous > 2*numberIntegers && nFix*10 < numberColumns) { #define LOCAL_FIX_CONTINUOUS #ifdef LOCAL_FIX_CONTINUOUS //const double * colUpper = newSolver->getColUpper(); const double * colLower = newSolver->getColLower(); int nAtLb = 0; //double sumDj=0.0; const double * dj = newSolver->getReducedCost(); double direction = newSolver->getObjSense(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { if (!used_[iColumn]) { //double djValue = dj[iColumn]*direction; nAtLb++; //sumDj += djValue; } } } if (nAtLb) { // fix some continuous double * sort = new double[nAtLb]; int * which = new int [nAtLb]; //double threshold = CoinMax((0.01*sumDj)/static_cast(nAtLb),1.0e-6); int nFix2 = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { if (!used_[iColumn]) { double djValue = dj[iColumn] * direction; if (djValue > 1.0e-6) { sort[nFix2] = -djValue; which[nFix2++] = iColumn; } } } } CoinSort_2(sort, sort + nFix2, which); int divisor = 2; nFix2 = CoinMin(nFix2, (numberColumns - nFix) / divisor); for (int i = 0; i < nFix2; i++) { int iColumn = which[i]; newSolver->setColUpper(iColumn, colLower[iColumn]); } delete [] sort; delete [] which; #ifdef CLP_INVESTIGATE2 printf("%d integers have zero value, and %d continuous fixed at lb\n", nFix, nFix2); #endif returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, objectiveValue, objectiveValue, "CbcHeuristicLocal"); if (returnCode < 0) returnCode = 0; // returned on size } #endif } } } /* If the result is complete exploration with a solution (3) or proven infeasibility (2), we could generate a cut (the AI folks would call it a nogood) to prevent us from going down this route in the future. */ if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } delete newSolver; return returnCode; } /* First tries setting a variable to better value. If feasible then tries setting others. If not feasible then tries swaps Returns 1 if solution, 0 if not The main body of this routine implements an O((q^2)/2) brute force search around the current solution, for q = number of integer variables. Call this the inc/dec heuristic. For each integer variable x, first decrement the value. Then, for integer variables x, ..., x, try increment and decrement. If one of these permutations produces a better solution, remember it. Then repeat, with x incremented. If we find a better solution, update our notion of current solution and continue. The net effect is a greedy walk: As each improving pair is found, the current solution is updated and the search continues from this updated solution. Way down at the end, we call solutionFix, which will create a drastically restricted problem based on variables marked as used, then do mini-BaC on the restricted problem. This can occur even if we don't try the inc/dec heuristic. This would be more obvious if the inc/dec heuristic were broken out as a separate routine and solutionFix had a name that reflected where it was headed. The return code of 0 is grossly overloaded, because it maps to a return code of 0 from solutionFix, which is itself grossly overloaded. See comments in solutionFix and in CbcHeuristic::smallBranchAndBound. */ int CbcHeuristicLocal::solution(double & solutionValue, double * betterSolution) { /* Execute only if a new solution has been discovered since the last time we were called. */ numCouldRun_++; // See if frequency kills off idea int swap = swap_%100; int skip = swap_/100; int nodeCount = model_->getNodeCount(); if (nodeCountgetSolutionCount() && (numberSolutions_ == howOftenShallow_ || nodeCount < lastRunDeep_+2*skip)) return 0; howOftenShallow_ = numberSolutions_; numberSolutions_ = model_->getSolutionCount(); if (nodeCount 10*rows). And cost is proportional to number of integer variables --- shouldn't we use that? Why wait until we have more than one solution? */ if ((model_->getNumCols() > 100000 && model_->getNumCols() > 10*model_->getNumRows()) || numberSolutions_ <= 1) return 0; // probably not worth it // worth trying OsiSolverInterface * solver = model_->solver(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); const double * solution = model_->bestSolution(); /* Shouldn't this test be redundant if we've already checked that numberSolutions_ > 1? Stronger: shouldn't this be an assertion? */ if (!solution) return 0; // No solution found yet const double * objective = solver->getObjCoefficients(); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); int numberRows = matrix_.getNumRows(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; double direction = solver->getObjSense(); double newSolutionValue = model_->getObjValue() * direction; int returnCode = 0; numRuns_++; // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Get solution array for heuristic solution int numberColumns = solver->getNumCols(); double * newSolution = new double [numberColumns]; memcpy(newSolution, solution, numberColumns*sizeof(double)); #ifdef LOCAL_FIX_CONTINUOUS // mark continuous used const double * columnLower = solver->getColLower(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!solver->isInteger(iColumn)) { if (solution[iColumn] > columnLower[iColumn] + 1.0e-8) used_[iColumn] = numberSolutions_; } } #endif // way is 1 if down possible, 2 if up possible, 3 if both possible char * way = new char[numberIntegers]; // corrected costs double * cost = new double[numberIntegers]; // for array to mark infeasible rows after iColumn branch char * mark = new char[numberRows]; memset(mark, 0, numberRows); // space to save values so we don't introduce rounding errors double * save = new double[numberRows]; /* Force variables within their original bounds, then to the nearest integer. Overall, we seem to be prepared to cope with noninteger bounds. Is this necessary? Seems like we'd be better off to force the bounds to integrality as part of preprocessing. More generally, why do we need to do this? This solution should have been cleaned and checked when it was accepted as a solution! Once the value is set, decide whether we can move up or down. The only place that used_ is used is in solutionFix; if a variable is not flagged as used, it will be fixed (at lower bound). Why the asymmetric treatment? This makes some sense for binary variables (for which there are only two options). But for general integer variables, why not make a similar test against the original upper bound? */ // clean solution for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double value = newSolution[iColumn]; if (value < originalLower) { value = originalLower; newSolution[iColumn] = value; } else if (value > originalUpper) { value = originalUpper; newSolution[iColumn] = value; } double nearest = floor(value + 0.5); //assert(fabs(value-nearest)<10.0*primalTolerance); value = nearest; newSolution[iColumn] = nearest; // if away from lower bound mark that fact if (nearest > originalLower) { used_[iColumn] = numberSolutions_; } cost[i] = direction * objective[iColumn]; /* Given previous computation we're checking that value is at least 1 away from the original bounds. */ int iway = 0; if (value > originalLower + 0.5) iway = 1; if (value < originalUpper - 0.5) iway |= 2; way[i] = static_cast(iway); } /* Calculate lhs of each constraint for groomed solution. */ // get row activities double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); for (i = 0; i < numberColumns; i++) { int j; double value = newSolution[i]; if (value) { for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } /* Check that constraints are satisfied. For small infeasibility, force the activity within bound. Again, why is this necessary if the current solution was accepted as a valid solution? Why are we scanning past the first unacceptable constraint? */ // check was feasible - if not adjust (cleaning may move) // if very infeasible then give up bool tryHeuristic = true; for (i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i]) { if (rowActivity[i] < rowLower[i] - 10.0*primalTolerance) tryHeuristic = false; rowActivity[i] = rowLower[i]; } else if (rowActivity[i] > rowUpper[i]) { if (rowActivity[i] < rowUpper[i] + 10.0*primalTolerance) tryHeuristic = false; rowActivity[i] = rowUpper[i]; } } /* This bit of code is not quite totally redundant: it'll bail at 10,000 instead of 100,000. Potentially we can do a lot of work to get here, only to abandon it. */ // Switch off if may take too long if (model_->getNumCols() > 10000 && model_->getNumCols() > 10*model_->getNumRows()) tryHeuristic = false; /* Try the inc/dec heuristic? */ if (tryHeuristic) { // total change in objective double totalChange = 0.0; // local best change in objective double bestChange = 0.0; // maybe just do 1000 int maxIntegers = numberIntegers; if (((swap/10) &1) != 0) { maxIntegers = CoinMin(1000,numberIntegers); } /* Outer loop to walk integer variables. Call the current variable x. At the end of this loop, bestChange will contain the best (negative) change in the objective for any single pair. The trouble is, we're limited to monotonically increasing improvement. Suppose we discover an improvement of 10 for some pair. If, later in the search, we discover an improvement of 9 for some other pair, we will not use it. That seems wasteful. */ for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; bestChange = 0.0; int endInner = CoinMin(numberIntegers,i+maxIntegers); double objectiveCoefficient = cost[i]; int k; int j; int goodK = -1; int wayK = -1, wayI = -1; /* Try decrementing x. */ if ((way[i]&1) != 0) { int numberInfeasible = 0; /* Adjust row activities where x has a nonzero coefficient. Save the old values for restoration. Mark any rows that become infeasible as a result of the decrement. */ // save row activities and adjust for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; save[iRow] = rowActivity[iRow]; rowActivity[iRow] -= element[j]; if (rowActivity[iRow] < rowLower[iRow] - primalTolerance || rowActivity[iRow] > rowUpper[iRow] + primalTolerance) { // mark row mark[iRow] = 1; numberInfeasible++; } } /* Run through the remaining integer variables. Try increment and decrement on each one. If the potential objective change is better than anything we've seen so far, do a full evaluation of x in that direction. If we can repair all infeasibilities introduced by pushing x down, we have a winner. Remember the best variable, and the direction for x and x. */ // try down for (k = i + 1; k < endInner; k++) { if ((way[k]&1) != 0) { // try down if (-objectiveCoefficient - cost[k] < bestChange) { // see if feasible down bool good = true; int numberMarked = 0; int kColumn = integerVariable[k]; for (j = columnStart[kColumn]; j < columnStart[kColumn] + columnLength[kColumn]; j++) { int iRow = row[j]; double newValue = rowActivity[iRow] - element[j]; if (newValue < rowLower[iRow] - primalTolerance || newValue > rowUpper[iRow] + primalTolerance) { good = false; break; } else if (mark[iRow]) { // made feasible numberMarked++; } } if (good && numberMarked == numberInfeasible) { // better solution goodK = k; wayK = -1; wayI = -1; bestChange = -objectiveCoefficient - cost[k]; } } } if ((way[k]&2) != 0) { // try up if (-objectiveCoefficient + cost[k] < bestChange) { // see if feasible up bool good = true; int numberMarked = 0; int kColumn = integerVariable[k]; for (j = columnStart[kColumn]; j < columnStart[kColumn] + columnLength[kColumn]; j++) { int iRow = row[j]; double newValue = rowActivity[iRow] + element[j]; if (newValue < rowLower[iRow] - primalTolerance || newValue > rowUpper[iRow] + primalTolerance) { good = false; break; } else if (mark[iRow]) { // made feasible numberMarked++; } } if (good && numberMarked == numberInfeasible) { // better solution goodK = k; wayK = 1; wayI = -1; bestChange = -objectiveCoefficient + cost[k]; } } } } /* Remove effect of decrementing x by restoring original lhs values. */ // restore row activities for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] = save[iRow]; mark[iRow] = 0; } } /* Try to increment x. Actions as for decrement. */ if ((way[i]&2) != 0) { int numberInfeasible = 0; // save row activities and adjust for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; save[iRow] = rowActivity[iRow]; rowActivity[iRow] += element[j]; if (rowActivity[iRow] < rowLower[iRow] - primalTolerance || rowActivity[iRow] > rowUpper[iRow] + primalTolerance) { // mark row mark[iRow] = 1; numberInfeasible++; } } // try up for (k = i + 1; k < endInner; k++) { if ((way[k]&1) != 0) { // try down if (objectiveCoefficient - cost[k] < bestChange) { // see if feasible down bool good = true; int numberMarked = 0; int kColumn = integerVariable[k]; for (j = columnStart[kColumn]; j < columnStart[kColumn] + columnLength[kColumn]; j++) { int iRow = row[j]; double newValue = rowActivity[iRow] - element[j]; if (newValue < rowLower[iRow] - primalTolerance || newValue > rowUpper[iRow] + primalTolerance) { good = false; break; } else if (mark[iRow]) { // made feasible numberMarked++; } } if (good && numberMarked == numberInfeasible) { // better solution goodK = k; wayK = -1; wayI = 1; bestChange = objectiveCoefficient - cost[k]; } } } if ((way[k]&2) != 0) { // try up if (objectiveCoefficient + cost[k] < bestChange) { // see if feasible up bool good = true; int numberMarked = 0; int kColumn = integerVariable[k]; for (j = columnStart[kColumn]; j < columnStart[kColumn] + columnLength[kColumn]; j++) { int iRow = row[j]; double newValue = rowActivity[iRow] + element[j]; if (newValue < rowLower[iRow] - primalTolerance || newValue > rowUpper[iRow] + primalTolerance) { good = false; break; } else if (mark[iRow]) { // made feasible numberMarked++; } } if (good && numberMarked == numberInfeasible) { // better solution goodK = k; wayK = 1; wayI = 1; bestChange = objectiveCoefficient + cost[k]; } } } } // restore row activities for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] = save[iRow]; mark[iRow] = 0; } } /* We've found a pair x and x which produce a better solution. Update our notion of current solution to match. Why does this not update newSolutionValue? */ if (goodK >= 0) { // we found something - update solution for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += wayI * element[j]; } newSolution[iColumn] += wayI; int kColumn = integerVariable[goodK]; for (j = columnStart[kColumn]; j < columnStart[kColumn] + columnLength[kColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += wayK * element[j]; } newSolution[kColumn] += wayK; /* Adjust motion range for x. We may have banged up against a bound with that last move. */ // See if k can go further ? const OsiObject * object = model_->object(goodK); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double value = newSolution[kColumn]; int iway = 0; if (value > originalLower + 0.5) iway = 1; if (value < originalUpper - 0.5) iway |= 2; way[goodK] = static_cast(iway); totalChange += bestChange; } } /* End of loop to try increment/decrement of integer variables. newSolutionValue does not necessarily match the current newSolution, and bestChange simply reflects the best single change. Still, that's sufficient to indicate that there's been at least one change. Check that we really do have a valid solution. */ if (totalChange + newSolutionValue < solutionValue) { // paranoid check memset(rowActivity, 0, numberRows*sizeof(double)); for (i = 0; i < numberColumns; i++) { int j; double value = newSolution[i]; if (value) { for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } int numberBad = 0; double sumBad = 0.0; // check was approximately feasible for (i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i]) { sumBad += rowLower[i] - rowActivity[i]; if (rowActivity[i] < rowLower[i] - 10.0*primalTolerance) numberBad++; } else if (rowActivity[i] > rowUpper[i]) { sumBad += rowUpper[i] - rowActivity[i]; if (rowActivity[i] > rowUpper[i] + 10.0*primalTolerance) numberBad++; } } if (!numberBad) { for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double value = newSolution[iColumn]; // if away from lower bound mark that fact if (value > originalLower) { used_[iColumn] = numberSolutions_; } } /* Copy the solution to the array returned to the client. Grab a basis from the solver (which, if it exists, is almost certainly infeasible, but it should be ok for a dual start). The value returned as solutionValue is conservative because of handling of newSolutionValue and bestChange, as described above. */ // new solution memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); CoinWarmStartBasis * basis = dynamic_cast(solver->getWarmStart()) ; if (basis) { model_->setBestSolutionBasis(* basis); delete basis; } returnCode = 1; solutionValue = newSolutionValue + bestChange; } else { // bad solution - should not happen so debug if see message COIN_DETAIL_PRINT(printf("Local search got bad solution with %d infeasibilities summing to %g\n", numberBad, sumBad)); } } } /* We're done. Clean up. */ delete [] newSolution; delete [] rowActivity; delete [] way; delete [] cost; delete [] save; delete [] mark; /* Do we want to try swapping values between solutions? swap_ is set elsewhere; it's not adjusted during heuristic execution. Again, redundant test. We shouldn't be here if numberSolutions_ = 1. */ if (numberSolutions_ > 1 && (swap%10) == 1) { // try merge int returnCode2 = solutionFix( solutionValue, betterSolution, NULL); if (returnCode2) returnCode = 1; } return returnCode; } // update model void CbcHeuristicLocal::setModel(CbcModel * model) { model_ = model; // Get a copy of original matrix assert(model_->solver()); if (model_->solver()->getNumRows()) { matrix_ = *model_->solver()->getMatrixByCol(); } delete [] used_; int numberColumns = model->solver()->getNumCols(); used_ = new int[numberColumns]; memset(used_, 0, numberColumns*sizeof(int)); } // Default Constructor CbcHeuristicProximity::CbcHeuristicProximity() : CbcHeuristic() { feasibilityPump_ = NULL; numberSolutions_ = 0; used_ = NULL; lastRunDeep_ = -1000000; switches_ |= 16; // needs a new solution } // Constructor with model - assumed before cuts CbcHeuristicProximity::CbcHeuristicProximity(CbcModel & model) : CbcHeuristic(model) { feasibilityPump_ = NULL; numberSolutions_ = 0; lastRunDeep_ = -1000000; switches_ |= 16; // needs a new solution int numberColumns = model.solver()->getNumCols(); used_ = new int[numberColumns]; memset(used_, 0, numberColumns*sizeof(int)); } // Destructor CbcHeuristicProximity::~CbcHeuristicProximity () { delete feasibilityPump_; delete [] used_; } // Clone CbcHeuristic * CbcHeuristicProximity::clone() const { return new CbcHeuristicProximity(*this); } // Create C++ lines to get to current state void CbcHeuristicProximity::generateCpp( FILE * fp) { CbcHeuristicProximity other; fprintf(fp, "0#include \"CbcHeuristicProximity.hpp\"\n"); fprintf(fp, "3 CbcHeuristicProximity heuristicProximity(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicProximity"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicProximity);\n"); } // Copy constructor CbcHeuristicProximity::CbcHeuristicProximity(const CbcHeuristicProximity & rhs) : CbcHeuristic(rhs), numberSolutions_(rhs.numberSolutions_) { feasibilityPump_ = NULL; if (model_ && rhs.used_) { int numberColumns = model_->solver()->getNumCols(); used_ = CoinCopyOfArray(rhs.used_, numberColumns); if (rhs.feasibilityPump_) feasibilityPump_ = new CbcHeuristicFPump(*rhs.feasibilityPump_); } else { used_ = NULL; } } // Assignment operator CbcHeuristicProximity & CbcHeuristicProximity::operator=( const CbcHeuristicProximity & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); numberSolutions_ = rhs.numberSolutions_; delete [] used_; delete feasibilityPump_; feasibilityPump_ = NULL; if (model_ && rhs.used_) { int numberColumns = model_->solver()->getNumCols(); used_ = CoinCopyOfArray(rhs.used_, numberColumns); if (rhs.feasibilityPump_) feasibilityPump_ = new CbcHeuristicFPump(*rhs.feasibilityPump_); } else { used_ = NULL; } } return *this; } // Resets stuff if model changes void CbcHeuristicProximity::resetModel(CbcModel * /*model*/) { //CbcHeuristic::resetModel(model); delete [] used_; if (model_ && used_) { int numberColumns = model_->solver()->getNumCols(); used_ = new int[numberColumns]; memset(used_, 0, numberColumns*sizeof(int)); } else { used_ = NULL; } } /* Run a mini-BaB search after changing objective Return values are: 1: smallBranchAndBound found a solution 0: everything else The degree of overload as return codes from smallBranchAndBound are folded into 0 is such that it's impossible to distinguish return codes that really require attention from a simple `nothing of interest'. */ int CbcHeuristicProximity::solution(double & solutionValue, double * betterSolution) { if (feasibilityPumpOptions_ == -3 && numCouldRun_==0 && !feasibilityPump_ ) { // clone feasibility pump for (int i = 0; i < model_->numberHeuristics(); i++) { const CbcHeuristicFPump* pump = dynamic_cast(model_->heuristic(i)); if (pump) { feasibilityPump_ = new CbcHeuristicFPump(*pump); break; } } } /* Execute only if a new solution has been discovered since the last time we were called. */ numCouldRun_++; int nodeCount = model_->getNodeCount(); if (numberSolutions_ == model_->getSolutionCount()) return 0; if (!model_->bestSolution()) return 0; // odd - because in parallel mode numberSolutions_ = model_->getSolutionCount(); lastRunDeep_ = nodeCount; numRuns_++; //howOftenShallow_ = numberSolutions_; /* Load up a new solver with the solution. Why continuousSolver(), as opposed to solver()? */ OsiSolverInterface * newSolver = model_->continuousSolver()->clone(); int numberColumns=newSolver->getNumCols(); double * obj = CoinCopyOfArray(newSolver->getObjCoefficients(),numberColumns); int * indices = new int [numberColumns]; int n=0; for (int i=0;igetCutoff(); assert (cutoff<1.0e20); if (model_->getCutoffIncrement()<1.0e-4) cutoff -= 0.01; double offset; newSolver->getDblParam(OsiObjOffset, offset); newSolver->setDblParam(OsiObjOffset, 0.0); newSolver->addRow(n,indices,obj,-COIN_DBL_MAX,cutoff+offset); delete [] indices; memset(obj,0,numberColumns*sizeof(double)); newSolver->setDblParam(OsiDualObjectiveLimit, 1.0e20); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double * solutionIn = model_->bestSolution(); for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (fabs(solutionIn[iColumn])<1.0e-5) obj[iColumn]=1.0; else if (fabs(solutionIn[iColumn]-1.0)<1.0e-5) obj[iColumn]=-1.0; } newSolver->setObjective(obj); delete [] obj; //newSolver->writeMps("xxxx"); int maxSolutions = model_->getMaximumSolutions(); model_->setMaximumSolutions(1); bool pumpAdded = false; if (feasibilityPumpOptions_ == -3 && feasibilityPump_) { // add back feasibility pump pumpAdded = true; for (int i = 0; i < model_->numberHeuristics(); i++) { const CbcHeuristicFPump* pump = dynamic_cast(model_->heuristic(i)); if (pump) { pumpAdded = false; break; } } if (pumpAdded) model_->addHeuristic(feasibilityPump_); } int returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, 1.0e20, "CbcHeuristicProximity"); if (pumpAdded) { // take off feasibility pump int lastHeuristic = model_->numberHeuristics()-1; model_->setNumberHeuristics(lastHeuristic); delete model_->heuristic(lastHeuristic); } model_->setMaximumSolutions(maxSolutions); /* -2 is return due to user event, and -1 is overloaded with what look to be two contradictory meanings. */ if (returnCode < 0) { returnCode = 0; } /* If the result is complete exploration with a solution (3) or proven infeasibility (2), we could generate a cut (the AI folks would call it a nogood) to prevent us from going down this route in the future. */ if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } char proxPrint[200]; if ((returnCode&1) != 0) { // redo objective const double * obj = model_->continuousSolver()->getObjCoefficients(); solutionValue = - offset; int sumIncrease=0.0; int sumDecrease=0.0; int numberIncrease=0; int numberDecrease=0; for (int i=0;iisInteger(i)) { int change=static_cast(floor(solutionIn[i]-betterSolution[i]+0.5)); if (change>0) { numberIncrease++; sumIncrease+=change; } else if (change<0) { numberDecrease++; sumDecrease-=change; } } } sprintf(proxPrint,"Proximity search ran %d nodes (out of %d) - in new solution %d increased (%d), %d decreased (%d)", numberNodesDone_,numberNodes_, numberIncrease,sumIncrease,numberDecrease,sumDecrease); } else { sprintf(proxPrint,"Proximity search ran %d nodes - no new solution", numberNodesDone_); } model_->messageHandler()->message(CBC_FPUMP1, model_->messages()) << proxPrint << CoinMessageEol; delete newSolver; return returnCode; } // update model void CbcHeuristicProximity::setModel(CbcModel * model) { model_ = model; // Get a copy of original matrix assert(model_->solver()); delete [] used_; int numberColumns = model->solver()->getNumCols(); used_ = new int[numberColumns]; memset(used_, 0, numberColumns*sizeof(int)); } // Default Constructor CbcHeuristicNaive::CbcHeuristicNaive() : CbcHeuristic() { large_ = 1.0e6; } // Constructor with model - assumed before cuts CbcHeuristicNaive::CbcHeuristicNaive(CbcModel & model) : CbcHeuristic(model) { large_ = 1.0e6; } // Destructor CbcHeuristicNaive::~CbcHeuristicNaive () { } // Clone CbcHeuristic * CbcHeuristicNaive::clone() const { return new CbcHeuristicNaive(*this); } // Create C++ lines to get to current state void CbcHeuristicNaive::generateCpp( FILE * fp) { CbcHeuristicNaive other; fprintf(fp, "0#include \"CbcHeuristicProximity.hpp\"\n"); fprintf(fp, "3 CbcHeuristicNaive naive(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "naive"); if (large_ != other.large_) fprintf(fp, "3 naive.setLarge(%g);\n", large_); else fprintf(fp, "4 naive.setLarge(%g);\n", large_); fprintf(fp, "3 cbcModel->addHeuristic(&naive);\n"); } // Copy constructor CbcHeuristicNaive::CbcHeuristicNaive(const CbcHeuristicNaive & rhs) : CbcHeuristic(rhs), large_(rhs.large_) { } // Assignment operator CbcHeuristicNaive & CbcHeuristicNaive::operator=( const CbcHeuristicNaive & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); large_ = rhs.large_; } return *this; } // Resets stuff if model changes void CbcHeuristicNaive::resetModel(CbcModel * model) { CbcHeuristic::resetModel(model); } int CbcHeuristicNaive::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; // See if to do bool atRoot = model_->getNodeCount() == 0; int passNumber = model_->getCurrentPassNumber(); if (!when() || (when() == 1 && model_->phase() != 1) || !atRoot || passNumber != 1) return 0; // switched off // Don't do if it was this heuristic which found solution! if (this == model_->lastHeuristic()) return 0; numRuns_++; double cutoff; model_->solver()->getDblParam(OsiDualObjectiveLimit, cutoff); double direction = model_->solver()->getObjSense(); cutoff *= direction; cutoff = CoinMin(cutoff, solutionValue); OsiSolverInterface * solver = model_->continuousSolver(); if (!solver) solver = model_->solver(); const double * colLower = solver->getColLower(); const double * colUpper = solver->getColUpper(); const double * objective = solver->getObjCoefficients(); int numberColumns = model_->getNumCols(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; bool solutionFound = false; CoinWarmStartBasis saveBasis; CoinWarmStartBasis * basis = dynamic_cast(solver->getWarmStart()) ; if (basis) { saveBasis = * basis; delete basis; } // First just fix all integers as close to zero as possible OsiSolverInterface * newSolver = cloneBut(7); // wassolver->clone(); for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; double value; if (lower > 0.0) value = lower; else if (upper < 0.0) value = upper; else value = 0.0; newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); } newSolver->initialSolve(); if (newSolver->isProvenOptimal()) { double solValue = newSolver->getObjValue() * direction ; if (solValue < cutoff) { // we have a solution solutionFound = true; solutionValue = solValue; memcpy(betterSolution, newSolver->getColSolution(), numberColumns*sizeof(double)); COIN_DETAIL_PRINT(printf("Naive fixing close to zero gave solution of %g\n", solutionValue)); cutoff = solValue - model_->getCutoffIncrement(); } } // Now fix all integers as close to zero if not zero or large cost int nFix = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; double value; if (fabs(objective[i]) > 0.0 && fabs(objective[i]) < large_) { nFix++; if (lower > 0.0) value = lower; else if (upper < 0.0) value = upper; else value = 0.0; newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); } else { // set back to original newSolver->setColLower(iColumn, lower); newSolver->setColUpper(iColumn, upper); } } const double * solution = solver->getColSolution(); if (nFix) { newSolver->setWarmStart(&saveBasis); newSolver->setColSolution(solution); newSolver->initialSolve(); if (newSolver->isProvenOptimal()) { double solValue = newSolver->getObjValue() * direction ; if (solValue < cutoff) { // try branch and bound double * newSolution = new double [numberColumns]; COIN_DETAIL_PRINT(printf("%d fixed after fixing costs\n", nFix)); int returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, solutionValue, solutionValue, "CbcHeuristicNaive1"); if (returnCode < 0) returnCode = 0; // returned on size if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } if (returnCode == 1) { // solution solutionFound = true; memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); COIN_DETAIL_PRINT(printf("Naive fixing zeros gave solution of %g\n", solutionValue)); cutoff = solutionValue - model_->getCutoffIncrement(); } delete [] newSolution; } } } #if 1 newSolver->setObjSense(-direction); // maximize newSolver->setWarmStart(&saveBasis); newSolver->setColSolution(solution); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double value = solution[iColumn]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; double newLower; double newUpper; if (newSolver->isInteger(iColumn)) { newLower = CoinMax(lower, floor(value) - 2.0); newUpper = CoinMin(upper, ceil(value) + 2.0); } else { newLower = CoinMax(lower, value - 1.0e5); newUpper = CoinMin(upper, value + 1.0e-5); } newSolver->setColLower(iColumn, newLower); newSolver->setColUpper(iColumn, newUpper); } newSolver->initialSolve(); if (newSolver->isProvenOptimal()) { double solValue = newSolver->getObjValue() * direction ; if (solValue < cutoff) { nFix = 0; newSolver->setObjSense(direction); // correct direction //const double * thisSolution = newSolver->getColSolution(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double value = solution[iColumn]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; double newLower = lower; double newUpper = upper; if (newSolver->isInteger(iColumn)) { if (value < lower + 1.0e-6) { nFix++; newUpper = lower; } else if (value > upper - 1.0e-6) { nFix++; newLower = upper; } else { newLower = CoinMax(lower, floor(value) - 2.0); newUpper = CoinMin(upper, ceil(value) + 2.0); } } newSolver->setColLower(iColumn, newLower); newSolver->setColUpper(iColumn, newUpper); } // try branch and bound double * newSolution = new double [numberColumns]; COIN_DETAIL_PRINT(printf("%d fixed after maximizing\n", nFix)); int returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, solutionValue, solutionValue, "CbcHeuristicNaive1"); if (returnCode < 0) returnCode = 0; // returned on size if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } if (returnCode == 1) { // solution solutionFound = true; memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); COIN_DETAIL_PRINT(printf("Naive maximizing gave solution of %g\n", solutionValue)); cutoff = solutionValue - model_->getCutoffIncrement(); } delete [] newSolution; } } #endif delete newSolver; return solutionFound ? 1 : 0; } // update model void CbcHeuristicNaive::setModel(CbcModel * model) { model_ = model; } // Default Constructor CbcHeuristicCrossover::CbcHeuristicCrossover() : CbcHeuristic(), numberSolutions_(0), useNumber_(3) { setWhen(1); } // Constructor with model - assumed before cuts CbcHeuristicCrossover::CbcHeuristicCrossover(CbcModel & model) : CbcHeuristic(model), numberSolutions_(0), useNumber_(3) { setWhen(1); for (int i = 0; i < 10; i++) random_[i] = model.randomNumberGenerator()->randomDouble(); } // Destructor CbcHeuristicCrossover::~CbcHeuristicCrossover () { } // Clone CbcHeuristic * CbcHeuristicCrossover::clone() const { return new CbcHeuristicCrossover(*this); } // Create C++ lines to get to current state void CbcHeuristicCrossover::generateCpp( FILE * fp) { CbcHeuristicCrossover other; fprintf(fp, "0#include \"CbcHeuristicProximity.hpp\"\n"); fprintf(fp, "3 CbcHeuristicCrossover crossover(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "crossover"); if (useNumber_ != other.useNumber_) fprintf(fp, "3 crossover.setNumberSolutions(%d);\n", useNumber_); else fprintf(fp, "4 crossover.setNumberSolutions(%d);\n", useNumber_); fprintf(fp, "3 cbcModel->addHeuristic(&crossover);\n"); } // Copy constructor CbcHeuristicCrossover::CbcHeuristicCrossover(const CbcHeuristicCrossover & rhs) : CbcHeuristic(rhs), attempts_(rhs.attempts_), numberSolutions_(rhs.numberSolutions_), useNumber_(rhs.useNumber_) { memcpy(random_, rhs.random_, 10*sizeof(double)); } // Assignment operator CbcHeuristicCrossover & CbcHeuristicCrossover::operator=( const CbcHeuristicCrossover & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); useNumber_ = rhs.useNumber_; attempts_ = rhs.attempts_; numberSolutions_ = rhs.numberSolutions_; memcpy(random_, rhs.random_, 10*sizeof(double)); } return *this; } // Resets stuff if model changes void CbcHeuristicCrossover::resetModel(CbcModel * model) { CbcHeuristic::resetModel(model); } int CbcHeuristicCrossover::solution(double & solutionValue, double * betterSolution) { if (when_ == 0) return 0; numCouldRun_++; bool useBest = (numberSolutions_ != model_->getSolutionCount()); if (!useBest && (when_ % 10) == 1) return 0; numberSolutions_ = model_->getSolutionCount(); OsiSolverInterface * continuousSolver = model_->continuousSolver(); int useNumber = CoinMin(model_->numberSavedSolutions(), useNumber_); if (useNumber < 2 || !continuousSolver) return 0; // Fix later if (!useBest) abort(); numRuns_++; double cutoff; model_->solver()->getDblParam(OsiDualObjectiveLimit, cutoff); double direction = model_->solver()->getObjSense(); cutoff *= direction; cutoff = CoinMin(cutoff, solutionValue); OsiSolverInterface * solver = cloneBut(2); // But reset bounds solver->setColLower(continuousSolver->getColLower()); solver->setColUpper(continuousSolver->getColUpper()); int numberColumns = solver->getNumCols(); // Fixed double * fixed = new double [numberColumns]; for (int i = 0; i < numberColumns; i++) fixed[i] = -COIN_DBL_MAX; int whichSolution[10]; for (int i = 0; i < useNumber; i++) whichSolution[i] = i; for (int i = 0; i < useNumber; i++) { int k = whichSolution[i]; const double * solution = model_->savedSolution(k); for (int j = 0; j < numberColumns; j++) { if (solver->isInteger(j)) { if (fixed[j] == -COIN_DBL_MAX) fixed[j] = floor(solution[j] + 0.5); else if (fabs(fixed[j] - solution[j]) > 1.0e-7) fixed[j] = COIN_DBL_MAX; } } } const double * colLower = solver->getColLower(); for (int i = 0; i < numberColumns; i++) { if (solver->isInteger(i)) { double value = fixed[i]; if (value != COIN_DBL_MAX) { if (when_ < 10) { solver->setColLower(i, value); solver->setColUpper(i, value); } else if (value == colLower[i]) { solver->setColUpper(i, value); } } } } int returnCode = smallBranchAndBound(solver, numberNodes_, betterSolution, solutionValue, solutionValue, "CbcHeuristicCrossover"); if (returnCode < 0) returnCode = 0; // returned on size if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } delete solver; return returnCode; } // update model void CbcHeuristicCrossover::setModel(CbcModel * model) { model_ = model; if (model) { for (int i = 0; i < 10; i++) random_[i] = model->randomNumberGenerator()->randomDouble(); } } Cbc-2.8.12/src/CbcObject.hpp0000644000076600007660000002260712131315050014065 0ustar coincoin// $Id: CbcObject.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/12/2009 carved from CbcBranchBase #ifndef CbcObject_H #define CbcObject_H #include #include #include "OsiBranchingObject.hpp" class OsiSolverInterface; class OsiSolverBranch; class CbcModel; class CbcNode; class CbcNodeInfo; class CbcBranchingObject; class OsiChooseVariable; class CbcObjectUpdateData; //############################################################################# /** Abstract base class for `objects'. It now just has stuff that OsiObject does not have The branching model used in Cbc is based on the idea of an object. In the abstract, an object is something that has a feasible region, can be evaluated for infeasibility, can be branched on (i.e., there's some constructive action to be taken to move toward feasibility), and allows comparison of the effect of branching. This class (CbcObject) is the base class for an object. To round out the branching model, the class CbcBranchingObject describes how to perform a branch, and the class CbcBranchDecision describes how to compare two CbcBranchingObjects. To create a new type of object you need to provide three methods: #infeasibility(), #feasibleRegion(), and #createCbcBranch(), described below. This base class is primarily virtual to allow for any form of structure. Any form of discontinuity is allowed. \todo The notion that all branches are binary (two arms) is wired into the implementation of CbcObject, CbcBranchingObject, and CbcBranchDecision. Changing this will require a moderate amount of recoding. */ // This can be used if object wants to skip strong branching typedef struct { CbcBranchingObject * possibleBranch; // what a branch would do double upMovement; // cost going up (and initial away from feasible) double downMovement; // cost going down int numIntInfeasUp ; // without odd ones int numObjInfeasUp ; // just odd ones bool finishedUp; // true if solver finished int numItersUp ; // number of iterations in solver int numIntInfeasDown ; // without odd ones int numObjInfeasDown ; // just odd ones bool finishedDown; // true if solver finished int numItersDown; // number of iterations in solver int objectNumber; // Which object it is int fix; // 0 if no fix, 1 if we can fix up, -1 if we can fix down } CbcStrongInfo; class CbcObject : public OsiObject { public: // Default Constructor CbcObject (); // Useful constructor CbcObject (CbcModel * model); // Copy constructor CbcObject ( const CbcObject &); // Assignment operator CbcObject & operator=( const CbcObject& rhs); /// Clone virtual CbcObject * clone() const = 0; /// Destructor virtual ~CbcObject (); /** Infeasibility of the object This is some measure of the infeasibility of the object. It should be scaled to be in the range [0.0, 0.5], with 0.0 indicating the object is satisfied. The preferred branching direction is returned in preferredWay, This is used to prepare for strong branching but should also think of case when no strong branching The object may also compute an estimate of cost of going "up" or "down". This will probably be based on pseudo-cost ideas */ #ifdef CBC_NEW_STYLE_BRANCH virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const = 0; #else virtual double infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { return infeasibility(preferredWay); } virtual double infeasibility(int &/*preferredWay*/) const { throw CoinError("Need code", "infeasibility", "CbcBranchBase"); } #endif /** For the variable(s) referenced by the object, look at the current solution and set bounds to match the solution. */ virtual void feasibleRegion() = 0; /// Dummy one for compatibility virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; /** For the variable(s) referenced by the object, look at the current solution and set bounds to match the solution. Returns measure of how much it had to move solution to make feasible */ virtual double feasibleRegion(OsiSolverInterface * solver) const ; /** Create a branching object and indicate which way to branch first. The branching object has to know how to create branches (fix variables, etc.) */ #ifdef CBC_NEW_STYLE_BRANCH virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) = 0; #else virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * /* solver */, const OsiBranchingInformation * /* info */, int /* way */) { // return createBranch(solver, info, way); return NULL; } virtual OsiBranchingObject * createBranch(OsiSolverInterface * /*solver*/, const OsiBranchingInformation * /*info*/, int /*way*/) const { throw CoinError("Need code", "createBranch", "CbcBranchBase"); } #endif /** Create an Osibranching object and indicate which way to branch first. The branching object has to know how to create branches (fix variables, etc.) */ virtual OsiBranchingObject * createOsiBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const; /** Create an OsiSolverBranch object This returns NULL if branch not represented by bound changes */ virtual OsiSolverBranch * solverBranch() const; /** \brief Given a valid solution (with reduced costs, etc.), return a branching object which would give a new feasible point in a good direction. If the method cannot generate a feasible point (because there aren't any, or because it isn't bright enough to find one), it should return null. */ virtual CbcBranchingObject * preferredNewFeasible() const { return NULL; } /** \brief Given a valid solution (with reduced costs, etc.), return a branching object which would give a new feasible point in a bad direction. If the method cannot generate a feasible point (because there aren't any, or because it isn't bright enough to find one), it should return null. */ virtual CbcBranchingObject * notPreferredNewFeasible() const { return NULL; } /** Reset variable bounds to their original values. Bounds may be tightened, so it may be good to be able to set this info in object. */ virtual void resetBounds(const OsiSolverInterface * ) {} /** Returns floor and ceiling i.e. closest valid points */ virtual void floorCeiling(double & floorValue, double & ceilingValue, double value, double tolerance) const; /** Pass in information on branch just done and create CbcObjectUpdateData instance. If object does not need data then backward pointer will be NULL. Assumes can get information from solver */ virtual CbcObjectUpdateData createUpdateInformation(const OsiSolverInterface * solver, const CbcNode * node, const CbcBranchingObject * branchingObject); /// Update object by CbcObjectUpdateData virtual void updateInformation(const CbcObjectUpdateData & ) {} /// Identifier (normally column number in matrix) inline int id() const { return id_; } /** Set identifier (normally column number in matrix) but 1000000000 to 1100000000 means optional branching object i.e. code would work without it */ inline void setId(int value) { id_ = value; } /** Return true if optional branching object i.e. code would work without it */ inline bool optionalObject() const { return (id_ >= 1000000000 && id_ < 1100000000); } /// Get position in object_ list inline int position() const { return position_; } /// Set position in object_ list inline void setPosition(int position) { position_ = position; } /// update model inline void setModel(CbcModel * model) { model_ = model; } /// Return model inline CbcModel * model() const { return model_; } /// If -1 down always chosen first, +1 up always, 0 normal inline int preferredWay() const { return preferredWay_; } /// Set -1 down always chosen first, +1 up always, 0 normal inline void setPreferredWay(int value) { preferredWay_ = value; } /// Redoes data when sequence numbers change virtual void redoSequenceEtc(CbcModel * , int , const int * ) {} /// Initialize for branching virtual void initializeForBranching(CbcModel * ) {} protected: /// data /// Model CbcModel * model_; /// Identifier (normally column number in matrix) int id_; /// Position in object list int position_; /// If -1 down always chosen first, +1 up always, 0 normal int preferredWay_; }; #endif Cbc-2.8.12/src/CbcBranchAllDifferent.cpp0000644000076600007660000001047012131315050016322 0ustar coincoin// $Id: CbcBranchAllDifferent.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/13/2009-- carved out of CbcBranchCut #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchCut.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" #include "CbcBranchAllDifferent.hpp" /** Default Constructor */ CbcBranchAllDifferent::CbcBranchAllDifferent () : CbcBranchCut(), numberInSet_(0), which_(NULL) { } /* Useful constructor - passed set of variables */ CbcBranchAllDifferent::CbcBranchAllDifferent (CbcModel * model, int numberInSet, const int * members) : CbcBranchCut(model) { numberInSet_ = numberInSet; which_ = CoinCopyOfArray(members, numberInSet_); } // Copy constructor CbcBranchAllDifferent::CbcBranchAllDifferent ( const CbcBranchAllDifferent & rhs) : CbcBranchCut(rhs) { numberInSet_ = rhs.numberInSet_; which_ = CoinCopyOfArray(rhs.which_, numberInSet_); } // Clone CbcObject * CbcBranchAllDifferent::clone() const { return new CbcBranchAllDifferent(*this); } // Assignment operator CbcBranchAllDifferent & CbcBranchAllDifferent::operator=( const CbcBranchAllDifferent & rhs) { if (this != &rhs) { CbcBranchCut::operator=(rhs); delete [] which_; numberInSet_ = rhs.numberInSet_; which_ = CoinCopyOfArray(rhs.which_, numberInSet_); } return *this; } // Destructor CbcBranchAllDifferent::~CbcBranchAllDifferent () { delete [] which_; } CbcBranchingObject * CbcBranchAllDifferent::createCbcBranch(OsiSolverInterface * /*solver*/ , const OsiBranchingInformation * /*info*/, int /*way*/) { // by default way must be -1 //assert (way==-1); const double * solution = model_->testSolution(); double * values = new double[numberInSet_]; int * which = new int[numberInSet_]; int i; for (i = 0; i < numberInSet_; i++) { int iColumn = which_[i]; values[i] = solution[iColumn]; which[i] = iColumn; } CoinSort_2(values, values + numberInSet_, which); double last = -1.0; double closest = 1.0; int worst = -1; for (i = 0; i < numberInSet_; i++) { if (values[i] - last < closest) { closest = values[i] - last; worst = i - 1; } last = values[i]; } assert (closest <= 0.99999); OsiRowCut down; down.setLb(-COIN_DBL_MAX); down.setUb(-1.0); int pair[2]; double elements[] = {1.0, -1.0}; pair[0] = which[worst]; pair[1] = which[worst+1]; delete [] values; delete [] which; down.setRow(2, pair, elements); // up is same - just with rhs changed OsiRowCut up = down; up.setLb(1.0); up.setUb(COIN_DBL_MAX); // Say is not a fix type branch CbcCutBranchingObject * newObject = new CbcCutBranchingObject(model_, down, up, false); if (model_->messageHandler()->logLevel() > 1) printf("creating cut in CbcBranchCut\n"); return newObject; } double CbcBranchAllDifferent::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { preferredWay = -1; //OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); //const double * lower = solver->getColLower(); //const double * upper = solver->getColUpper(); double * values = new double[numberInSet_]; int i; for (i = 0; i < numberInSet_; i++) { int iColumn = which_[i]; values[i] = solution[iColumn]; } std::sort(values, values + numberInSet_); double last = -1.0; double closest = 1.0; for (i = 0; i < numberInSet_; i++) { if (values[i] - last < closest) { closest = values[i] - last; } last = values[i]; } delete [] values; if (closest > 0.99999) return 0.0; else return 0.5*(1.0 - closest); } Cbc-2.8.12/src/CbcConsequence.cpp0000644000076600007660000000153212131315050015114 0ustar coincoin// $Id: CbcConsequence.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/12/2009 carved from CbcBranchBase #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "CbcConsequence.hpp" // Default constructor CbcConsequence::CbcConsequence() { } // Destructor CbcConsequence::~CbcConsequence () { } // Copy constructor CbcConsequence::CbcConsequence ( const CbcConsequence & /*rhs*/) { } // Assignment operator CbcConsequence & CbcConsequence::operator=( const CbcConsequence & rhs) { if (this != &rhs) { } return *this; } Cbc-2.8.12/src/CbcBranchBase.cpp0000644000076600007660000002210711510742604014646 0ustar coincoin/* $Id: CbcBranchBase.cpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "OsiChooseVariable.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchBase.hpp" // Default Constructor CbcObject::CbcObject() : OsiObject(), model_(NULL), id_(-1), position_(-1), preferredWay_(0) { } // Constructor from model CbcObject::CbcObject(CbcModel * model) : OsiObject(), model_(model), id_(-1), position_(-1), preferredWay_(0) { } // Destructor CbcObject::~CbcObject () { } // Copy constructor CbcObject::CbcObject ( const CbcObject & rhs) : OsiObject(rhs) { model_ = rhs.model_; id_ = rhs.id_; position_ = rhs.position_; preferredWay_ = rhs.preferredWay_; } // Assignment operator CbcObject & CbcObject::operator=( const CbcObject & rhs) { if (this != &rhs) { OsiObject::operator=(rhs); model_ = rhs.model_; id_ = rhs.id_; position_ = rhs.position_; preferredWay_ = rhs.preferredWay_; } return *this; } /* Returns floor and ceiling i.e. closest valid points */ void CbcObject::floorCeiling(double & floorValue, double & ceilingValue, double value, double tolerance) const { if (fabs(floor(value + 0.5) - value) > tolerance) { floorValue = floor(value); } else { floorValue = floor(value + 0.5); } ceilingValue = floorValue + 1.0; } /* For the variable(s) referenced by the object, look at the current solution and set bounds to match the solution. Returns measure of how much it had to move solution to make feasible */ double CbcObject::feasibleRegion(OsiSolverInterface * /*solver*/) const { //assert (solver==model_->solver()); CbcObject * fudge = const_cast(this); fudge->feasibleRegion(); return 0.0; } /* For the variable(s) referenced by the object, look at the current solution and set bounds to match the solution. Returns measure of how much it had to move solution to make feasible */ double CbcObject::feasibleRegion(OsiSolverInterface * /*solver*/, const OsiBranchingInformation * /*info*/) const { //assert (solver==model_->solver()); CbcObject * fudge = const_cast(this); fudge->feasibleRegion(); return 0.0; } /* Create a branching object and indicate which way to branch first. The branching object has to know how to create branches (fix variables, etc.) */ OsiBranchingObject * CbcObject::createOsiBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const { //assert (solver==model_->solver()); CbcObject * fudge = const_cast(this); return fudge->createBranch(solver, info, way); } /* Create an OsiSolverBranch object This returns NULL if branch not represented by bound changes */ OsiSolverBranch * CbcObject::solverBranch() const { return NULL; } /* Pass in information on branch just done and create CbcObjectUpdateData instance. If object does not need data then backward pointer will be NULL. Assumes can get information from solver */ CbcObjectUpdateData CbcObject::createUpdateInformation(const OsiSolverInterface * /*solver*/, const CbcNode * /*node*/, const CbcBranchingObject * /*branchingObject*/) { return CbcObjectUpdateData(); } // Default Constructor CbcBranchingObject::CbcBranchingObject() : OsiBranchingObject() { model_ = NULL; originalCbcObject_ = NULL; variable_ = -1; way_ = 0; } // Useful constructor CbcBranchingObject::CbcBranchingObject (CbcModel * model, int variable, int way , double value) : OsiBranchingObject(model->solver(), value) { model_ = model; originalCbcObject_ = NULL; variable_ = variable; way_ = way; } // Copy constructor CbcBranchingObject::CbcBranchingObject ( const CbcBranchingObject & rhs) : OsiBranchingObject(rhs) { model_ = rhs.model_; originalCbcObject_ = rhs.originalCbcObject_; variable_ = rhs.variable_; way_ = rhs.way_; value_ = rhs.value_; } // Assignment operator CbcBranchingObject & CbcBranchingObject::operator=( const CbcBranchingObject & rhs) { if (this != &rhs) { OsiBranchingObject::operator=(rhs); model_ = rhs.model_; originalCbcObject_ = rhs.originalCbcObject_; variable_ = rhs.variable_; way_ = rhs.way_; } return *this; } // Destructor CbcBranchingObject::~CbcBranchingObject () { } // Default Constructor CbcBranchDecision::CbcBranchDecision () : object_(NULL), model_(NULL), chooseMethod_(NULL) { } // Copy Constructor CbcBranchDecision::CbcBranchDecision (const CbcBranchDecision &rhs) : object_(NULL), model_(rhs.model_), chooseMethod_(NULL) { if (rhs.chooseMethod_) chooseMethod_ = rhs.chooseMethod_->clone(); } CbcBranchDecision::~CbcBranchDecision() { delete object_; delete chooseMethod_; } /* Compare N branching objects. Return index of best and sets way of branching in chosen object. This routine is used only after strong branching. This is reccommended version as it can be more sophisticated */ int CbcBranchDecision::bestBranch (CbcBranchingObject ** objects, int numberObjects, int /*numberUnsatisfied*/, double * changeUp, int * numberInfeasibilitiesUp, double * changeDown, int * numberInfeasibilitiesDown, double /*objectiveValue*/) { int bestWay = 0; int whichObject = -1; if (numberObjects) { initialize(objects[0]->model()); CbcBranchingObject * bestObject = NULL; for (int i = 0 ; i < numberObjects ; i++) { int betterWay = betterBranch(objects[i], bestObject, changeUp[i], numberInfeasibilitiesUp [i], changeDown[i], numberInfeasibilitiesDown[i] ); if (betterWay) { bestObject = objects[i]; bestWay = betterWay; whichObject = i; } } // set way in best if (whichObject >= 0) objects[whichObject]->way(bestWay); } return whichObject; } // Set (clone) chooseMethod void CbcBranchDecision::setChooseMethod(const OsiChooseVariable & method) { delete chooseMethod_; chooseMethod_ = method.clone(); } // Default constructor CbcConsequence::CbcConsequence() { } // Destructor CbcConsequence::~CbcConsequence () { } // Copy constructor CbcConsequence::CbcConsequence ( const CbcConsequence & /*rhs*/) { } // Assignment operator CbcConsequence & CbcConsequence::operator=( const CbcConsequence & rhs) { if (this != &rhs) { } return *this; } // Default constructor CbcObjectUpdateData::CbcObjectUpdateData() : object_(NULL), way_(0), objectNumber_(-1), change_(0.0), status_(0), intDecrease_(0), branchingValue_(0.0), originalObjective_(COIN_DBL_MAX), cutoff_(COIN_DBL_MAX) { } // Useful constructor CbcObjectUpdateData::CbcObjectUpdateData (CbcObject * object, int way, double change, int status, int intDecrease, double branchingValue) : object_(object), way_(way), objectNumber_(-1), change_(change), status_(status), intDecrease_(intDecrease), branchingValue_(branchingValue), originalObjective_(COIN_DBL_MAX), cutoff_(COIN_DBL_MAX) { } // Destructor CbcObjectUpdateData::~CbcObjectUpdateData () { } // Copy constructor CbcObjectUpdateData::CbcObjectUpdateData ( const CbcObjectUpdateData & rhs) : object_(rhs.object_), way_(rhs.way_), objectNumber_(rhs.objectNumber_), change_(rhs.change_), status_(rhs.status_), intDecrease_(rhs.intDecrease_), branchingValue_(rhs.branchingValue_), originalObjective_(rhs.originalObjective_), cutoff_(rhs.cutoff_) { } // Assignment operator CbcObjectUpdateData & CbcObjectUpdateData::operator=( const CbcObjectUpdateData & rhs) { if (this != &rhs) { object_ = rhs.object_; way_ = rhs.way_; objectNumber_ = rhs.objectNumber_; change_ = rhs.change_; status_ = rhs.status_; intDecrease_ = rhs.intDecrease_; branchingValue_ = rhs.branchingValue_; originalObjective_ = rhs.originalObjective_; cutoff_ = rhs.cutoff_; } return *this; } Cbc-2.8.12/src/CbcCompareDepth.hpp0000644000076600007660000000256312131315050015231 0ustar coincoin// $Id: CbcCompareDepth.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/24/09 carved out of CbcCompareActual #ifndef CbcCompareDepth_H #define CbcCompareDepth_H //############################################################################# /* These are alternative strategies for node traversal. They can take data etc for fine tuning At present the node list is stored as a heap and the "test" comparison function returns true if node y is better than node x. */ #include "CbcNode.hpp" #include "CbcCompareBase.hpp" #include "CbcCompare.hpp" class CbcModel; // This is default before first solution class CbcCompareDepth : public CbcCompareBase { public: // Default Constructor CbcCompareDepth () ; ~CbcCompareDepth(); // Copy constructor CbcCompareDepth ( const CbcCompareDepth &rhs); // Assignment operator CbcCompareDepth & operator=( const CbcCompareDepth& rhs); /// Clone virtual CbcCompareBase * clone() const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp); // This returns true if the depth of node y is greater than depth of node x virtual bool test (CbcNode * x, CbcNode * y); }; #endif Cbc-2.8.12/src/CbcHeuristicDivePseudoCost.cpp0000644000076600007660000002004712145106127017436 0ustar coincoin/* $Id: CbcHeuristicDivePseudoCost.cpp 1922 2013-05-16 07:35:51Z forrest $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcHeuristicDivePseudoCost.hpp" #include "CbcStrategy.hpp" #include "CbcBranchDynamic.hpp" // Default Constructor CbcHeuristicDivePseudoCost::CbcHeuristicDivePseudoCost() : CbcHeuristicDive() { } // Constructor from model CbcHeuristicDivePseudoCost::CbcHeuristicDivePseudoCost(CbcModel & model) : CbcHeuristicDive(model) { } // Destructor CbcHeuristicDivePseudoCost::~CbcHeuristicDivePseudoCost () { } // Clone CbcHeuristicDivePseudoCost * CbcHeuristicDivePseudoCost::clone() const { return new CbcHeuristicDivePseudoCost(*this); } // Create C++ lines to get to current state void CbcHeuristicDivePseudoCost::generateCpp( FILE * fp) { CbcHeuristicDivePseudoCost other; fprintf(fp, "0#include \"CbcHeuristicDivePseudoCost.hpp\"\n"); fprintf(fp, "3 CbcHeuristicDivePseudoCost heuristicDivePseudoCost(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicDivePseudoCost"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicDivePseudoCost);\n"); } // Copy constructor CbcHeuristicDivePseudoCost::CbcHeuristicDivePseudoCost(const CbcHeuristicDivePseudoCost & rhs) : CbcHeuristicDive(rhs) { } // Assignment operator CbcHeuristicDivePseudoCost & CbcHeuristicDivePseudoCost::operator=( const CbcHeuristicDivePseudoCost & rhs) { if (this != &rhs) { CbcHeuristicDive::operator=(rhs); } return *this; } bool CbcHeuristicDivePseudoCost::selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound) { int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); // get the LP relaxation solution at the root node double * rootNodeLPSol = model_->continuousSolution(); // get pseudo costs double * pseudoCostDown = downArray_; double * pseudoCostUp = upArray_; bestColumn = -1; bestRound = -1; // -1 rounds down, +1 rounds up double bestScore = -1.0; bool allTriviallyRoundableSoFar = true; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double rootValue = rootNodeLPSol[iColumn]; double value = newSolution[iColumn]; double fraction = value - floor(value); int round = 0; if (fabs(floor(value + 0.5) - value) > integerTolerance) { if (allTriviallyRoundableSoFar || (downLocks_[i] > 0 && upLocks_[i] > 0)) { if (allTriviallyRoundableSoFar && downLocks_[i] > 0 && upLocks_[i] > 0) { allTriviallyRoundableSoFar = false; bestScore = -1.0; } double pCostDown = pseudoCostDown[i]; double pCostUp = pseudoCostUp[i]; assert(pCostDown >= 0.0 && pCostUp >= 0.0); if (allTriviallyRoundableSoFar && downLocks_[i] == 0 && upLocks_[i] > 0) round = 1; else if (allTriviallyRoundableSoFar && downLocks_[i] > 0 && upLocks_[i] == 0) round = -1; else if (value - rootValue < -0.4) round = -1; else if (value - rootValue > 0.4) round = 1; else if (fraction < 0.3) round = -1; else if (fraction > 0.7) round = 1; else if (pCostDown < pCostUp) round = -1; else round = 1; // calculate score double score; if (round == 1) score = fraction * (pCostDown + 1.0) / (pCostUp + 1.0); else score = (1.0 - fraction) * (pCostUp + 1.0) / (pCostDown + 1.0); // if variable is binary, increase its chance of being selected if (solver->isBinary(iColumn)) score *= 1000.0; if (score > bestScore) { bestColumn = iColumn; bestScore = score; bestRound = round; } } } } return allTriviallyRoundableSoFar; } void CbcHeuristicDivePseudoCost::initializeData() { int numberIntegers = model_->numberIntegers(); if (!downArray_) { downArray_ = new double [numberIntegers]; upArray_ = new double [numberIntegers]; } // get pseudo costs model_->fillPseudoCosts(downArray_, upArray_); // allow for -999 -> force to run int diveOptions = (when_>0) ? when_ / 100 : 0; if (diveOptions) { // pseudo shadow prices int k = diveOptions % 100; if (diveOptions >= 100) k += 32; model_->pseudoShadow(k - 1); int numberInts = CoinMin(model_->numberObjects(), numberIntegers); OsiObject ** objects = model_->objects(); for (int i = 0; i < numberInts; i++) { CbcSimpleIntegerDynamicPseudoCost * obj1 = dynamic_cast (objects[i]) ; if (obj1) { //int iColumn = obj1->columnNumber(); double downPseudoCost = 1.0e-2 * obj1->downDynamicPseudoCost(); double downShadow = obj1->downShadowPrice(); double upPseudoCost = 1.0e-2 * obj1->upDynamicPseudoCost(); double upShadow = obj1->upShadowPrice(); downPseudoCost = CoinMax(downPseudoCost, downShadow); downPseudoCost = CoinMax(downPseudoCost, 0.001 * upShadow); downArray_[i] = downPseudoCost; upPseudoCost = CoinMax(upPseudoCost, upShadow); upPseudoCost = CoinMax(upPseudoCost, 0.001 * downShadow); upArray_[i] = upPseudoCost; } } } } // Fix other variables at bounds int CbcHeuristicDivePseudoCost::fixOtherVariables(OsiSolverInterface * solver, const double * solution, PseudoReducedCost * candidate, const double * random) { const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double* reducedCost = solver->getReducedCost(); // fix other integer variables that are at their bounds int cnt = 0; int numberFree = 0; int numberFixedAlready = 0; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { numberFree++; double value = solution[iColumn]; if (value - lower[iColumn] <= integerTolerance) { candidate[cnt].var = iColumn; candidate[cnt++].pseudoRedCost = CoinMax(1.0e-2 * reducedCost[iColumn], downArray_[i]) * random[i]; } else if (upper[iColumn] - value <= integerTolerance) { candidate[cnt].var = iColumn; candidate[cnt++].pseudoRedCost = CoinMax(-1.0e-2 * reducedCost[iColumn], downArray_[i]) * random[i]; } } else { numberFixedAlready++; } } #ifdef CLP_INVESTIGATE printf("cutoff %g obj %g - %d free, %d fixed\n", model_->getCutoff(), solver->getObjValue(), numberFree, numberFixedAlready); #endif return cnt; //return CbcHeuristicDive::fixOtherVariables(solver, solution, // candidate, random); } Cbc-2.8.12/src/CbcSubProblem.hpp0000644000076600007660000000432012131315050014721 0ustar coincoin// $Id: CbcSubProblem.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #ifndef CbcSubProblem_H #define CbcSubProblem_H #ifdef COIN_HAS_CLP #include "ClpSimplex.hpp" #include "ClpNode.hpp" /** Defines a general subproblem Basis will be made more compact later */ class CoinWarmStartDiff; class CbcSubProblem { public: /// Default constructor CbcSubProblem (); /// Constructor from model CbcSubProblem (const OsiSolverInterface * solver, const double * lowerBefore, const double * upperBefore, const unsigned char * status, int depth); /// Copy constructor CbcSubProblem ( const CbcSubProblem &); /// Assignment operator CbcSubProblem & operator= (const CbcSubProblem& rhs); /// Destructor virtual ~CbcSubProblem (); /// Take over void takeOver ( CbcSubProblem &, bool cleanup); /// Apply subproblem (1=bounds, 2=basis, 3=both) void apply(OsiSolverInterface * model, int what = 3) const; public: /// Value of objective double objectiveValue_; /// Sum of infeasibilities double sumInfeasibilities_; /// Branch value double branchValue_; /// Dj on branching variable at end double djValue_; /** Which variable (top bit if upper bound changing) next bit if changing on down branch only */ int * variables_; /// New bound double * newBounds_; /// Status mutable CoinWarmStartBasis * status_; /// Depth int depth_; /// Number of Extra bound changes int numberChangedBounds_; /// Number of infeasibilities int numberInfeasibilities_; /** Status 1 bit going up on first, 2 bit set first branch infeasible on second, 4 bit redundant branch, bits after 256 give reason for stopping (just last node) 0 - solution 1 - infeasible 2 - maximum depth >2 - error or max time or something */ int problemStatus_; /// Variable branched on int branchVariable_; }; #endif //COIN_HAS_CLP #endif Cbc-2.8.12/src/CbcBranchCut.hpp0000644000076600007660000001351011510742604014532 0ustar coincoin/* $Id: CbcBranchCut.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcBranchCut_H #define CbcBranchCut_H #include "CbcBranchBase.hpp" #include "OsiRowCut.hpp" #include "CoinPackedMatrix.hpp" /** Define a cut branching class. At present empty - all stuff in descendants */ class CbcBranchCut : public CbcObject { public: // Default Constructor CbcBranchCut (); /** In to maintain normal methods */ CbcBranchCut (CbcModel * model); // Copy constructor CbcBranchCut ( const CbcBranchCut &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcBranchCut & operator=( const CbcBranchCut& rhs); // Destructor ~CbcBranchCut (); /// Infeasibility virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /** Set bounds to contain the current solution. More precisely, for the variable associated with this object, take the value given in the current solution, force it within the current bounds if required, then set the bounds to fix the variable at the integer nearest the solution value. At present this will do nothing */ virtual void feasibleRegion(); /** \brief Return true if branch created by object should fix variables */ virtual bool boundBranch() const ; /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /** \brief Given a valid solution (with reduced costs, etc.), return a branching object which would give a new feasible point in the good direction. The preferred branching object will force the variable to be +/-1 from its current value, depending on the reduced cost and objective sense. If movement in the direction which improves the objective is impossible due to bounds on the variable, the branching object will move in the other direction. If no movement is possible, the method returns NULL. Only the bounds on this variable are considered when determining if the new point is feasible. At present this does nothing */ virtual CbcBranchingObject * preferredNewFeasible() const; /** \brief Given a valid solution (with reduced costs, etc.), return a branching object which would give a new feasible point in a bad direction. As for preferredNewFeasible(), but the preferred branching object will force movement in a direction that degrades the objective. At present this does nothing */ virtual CbcBranchingObject * notPreferredNewFeasible() const ; using CbcObject::resetBounds ; /** Reset original upper and lower bound values from the solver. Handy for updating bounds held in this object after bounds held in the solver have been tightened. */ virtual void resetBounds(); protected: /// data }; /** Cut branching object This object can specify a two-way branch in terms of two cuts */ class CbcCutBranchingObject : public CbcBranchingObject { public: /// Default constructor CbcCutBranchingObject (); /** Create a cut branching object Cut down will applied on way=-1, up on way==1 Assumed down will be first so way_ set to -1 */ CbcCutBranchingObject (CbcModel * model, OsiRowCut & down, OsiRowCut &up, bool canFix); /// Copy constructor CbcCutBranchingObject ( const CbcCutBranchingObject &); /// Assignment operator CbcCutBranchingObject & operator= (const CbcCutBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; /// Destructor virtual ~CbcCutBranchingObject (); using CbcBranchingObject::branch ; /** \brief Sets the bounds for variables or adds a cut depending on the current arm of the branch and advances the object state to the next arm. Returns change in guessed objective on next branch */ virtual double branch(); using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /** \brief Return true if branch should fix variables */ virtual bool boundBranch() const; /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return CutBranchingObj; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const; /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); protected: /// Cut for the down arm (way_ = -1) OsiRowCut down_; /// Cut for the up arm (way_ = 1) OsiRowCut up_; /// True if one way can fix variables bool canFix_; }; #endif Cbc-2.8.12/src/CbcHeuristicDive.hpp0000644000076600007660000001252012131315050015417 0ustar coincoin/* $Id: CbcHeuristicDive.hpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcHeuristicDive_H #define CbcHeuristicDive_H #include "CbcHeuristic.hpp" class CbcSubProblem; class OsiRowCut; struct PseudoReducedCost { int var; double pseudoRedCost; }; /** Dive class */ class CbcHeuristicDive : public CbcHeuristic { public: // Default Constructor CbcHeuristicDive (); // Constructor with model - assumed before cuts CbcHeuristicDive (CbcModel & model); // Copy constructor CbcHeuristicDive ( const CbcHeuristicDive &); // Destructor ~CbcHeuristicDive (); /// Clone virtual CbcHeuristicDive * clone() const = 0; /// Assignment operator CbcHeuristicDive & operator=(const CbcHeuristicDive& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * ) {} /// Create C++ lines to get to current state - does work for base class void generateCpp( FILE * fp, const char * heuristic); /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); // REMLOVE using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution with better objective value than one passed in Sets solution values if good, sets objective value (only if good) This is called after cuts have been added - so can not add cuts This does Fractional Diving */ virtual int solution(double & objectiveValue, double * newSolution); /// inner part of dive int solution(double & objectiveValue, int & numberNodes, int & numberCuts, OsiRowCut ** cuts, CbcSubProblem ** & nodes, double * newSolution); /** returns 0 if no solution, 1 if valid solution with better objective value than one passed in also returns list of nodes This does Fractional Diving */ int fathom(CbcModel * model, int & numberNodes,CbcSubProblem ** & nodes); /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) virtual void validate(); /// Select candidate binary variables for fixing void selectBinaryVariables(); /// Set percentage of integer variables to fix at bounds void setPercentageToFix(double value) { percentageToFix_ = value; } /// Set maximum number of iterations void setMaxIterations(int value) { maxIterations_ = value; } /// Set maximum number of simplex iterations void setMaxSimplexIterations(int value) { maxSimplexIterations_ = value; } /// Get maximum number of simplex iterations inline int maxSimplexIterations() const { return maxSimplexIterations_; } /// Set maximum number of simplex iterations at root node void setMaxSimplexIterationsAtRoot(int value) { maxSimplexIterationsAtRoot_ = value; } /// Set maximum time allowed void setMaxTime(double value) { maxTime_ = value; } /// Tests if the heuristic can run virtual bool canHeuristicRun(); /** Selects the next variable to branch on Returns true if all the fractional variables can be trivially rounded. Returns false, if there is at least one fractional variable that is not trivially roundable. In this case, the bestColumn returned will not be trivially roundable. */ virtual bool selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound) = 0; /** Initializes any data which is going to be used repeatedly in selectVariableToBranch */ virtual void initializeData() {} /// Perform reduced cost fixing on integer variables int reducedCostFix (OsiSolverInterface* solver); /// Fix other variables at bounds virtual int fixOtherVariables(OsiSolverInterface * solver, const double * solution, PseudoReducedCost * candidate, const double * random); protected: // Data // Original matrix by column CoinPackedMatrix matrix_; // Original matrix by CoinPackedMatrix matrixByRow_; // Down locks unsigned short * downLocks_; // Up locks unsigned short * upLocks_; /// Extra down array (number Integers long) double * downArray_; /// Extra up array (number Integers long) double * upArray_; // Indexes of binary variables with 0 objective coefficient // and in variable bound constraints std::vector binVarIndex_; // Indexes of variable bound rows for each binary variable std::vector vbRowIndex_; // Percentage of integer variables to fix at bounds double percentageToFix_; // Maximum number of major iterations int maxIterations_; // Maximum number of simplex iterations int maxSimplexIterations_; // Maximum number of simplex iterations at root node int maxSimplexIterationsAtRoot_; // Maximum time allowed double maxTime_; }; #endif Cbc-2.8.12/src/CbcSimpleInteger.hpp0000644000076600007660000002275312131315050015430 0ustar coincoin// $Id: CbcSimpleInteger.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/9/2009-- carved out of CbcBranchActual #ifndef CbcSimpleInteger_H #define CbcSimpleInteger_H #include "CbcBranchingObject.hpp" /** Simple branching object for an integer variable This object can specify a two-way branch on an integer variable. For each arm of the branch, the upper and lower bounds on the variable can be independently specified. Variable_ holds the index of the integer variable in the integerVariable_ array of the model. */ class CbcIntegerBranchingObject : public CbcBranchingObject { public: /// Default constructor CbcIntegerBranchingObject (); /** Create a standard floor/ceiling branch object Specifies a simple two-way branch. Let \p value = x*. One arm of the branch will be lb <= x <= floor(x*), the other ceil(x*) <= x <= ub. Specify way = -1 to set the object state to perform the down arm first, way = 1 for the up arm. */ CbcIntegerBranchingObject (CbcModel *model, int variable, int way , double value) ; /** Create a degenerate branch object Specifies a `one-way branch'. Calling branch() for this object will always result in lowerValue <= x <= upperValue. Used to fix a variable when lowerValue = upperValue. */ CbcIntegerBranchingObject (CbcModel *model, int variable, int way, double lowerValue, double upperValue) ; /// Copy constructor CbcIntegerBranchingObject ( const CbcIntegerBranchingObject &); /// Assignment operator CbcIntegerBranchingObject & operator= (const CbcIntegerBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; /// Destructor virtual ~CbcIntegerBranchingObject (); /// Does part of constructor void fillPart ( int variable, int way , double value) ; using CbcBranchingObject::branch ; /** \brief Sets the bounds for the variable according to the current arm of the branch and advances the object state to the next arm. Returns change in guessed objective on next branch */ virtual double branch(); /** Update bounds in solver as in 'branch' and update given bounds. branchState is -1 for 'down' +1 for 'up' */ virtual void fix(OsiSolverInterface * solver, double * lower, double * upper, int branchState) const ; /** Change (tighten) bounds in object to reflect bounds in solver. Return true if now fixed */ virtual bool tighten(OsiSolverInterface * ) ; #ifdef JJF_ZERO // No need to override. Default works fine. /** Reset every information so that the branching object appears to point to the previous child. This method does not need to modify anything in any solver. */ virtual void previousBranch(); #endif using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /// Lower and upper bounds for down branch inline const double * downBounds() const { return down_; } /// Lower and upper bounds for up branch inline const double * upBounds() const { return up_; } /// Set lower and upper bounds for down branch inline void setDownBounds(const double bounds[2]) { memcpy(down_, bounds, 2*sizeof(double)); } /// Set lower and upper bounds for up branch inline void setUpBounds(const double bounds[2]) { memcpy(up_, bounds, 2*sizeof(double)); } #ifdef FUNNY_BRANCHING /** Which variable (top bit if upper bound changing, next bit if on down branch */ inline const int * variables() const { return variables_; } // New bound inline const double * newBounds() const { return newBounds_; } /// Number of bound changes inline int numberExtraChangedBounds() const { return numberExtraChangedBounds_; } /// Just apply extra bounds to one variable - COIN_DBL_MAX ignore int applyExtraBounds(int iColumn, double lower, double upper, int way) ; /// Deactivate bounds for branching void deactivate(); /// Are active bounds for branching inline bool active() const { return (down_[1] != -COIN_DBL_MAX); } #endif /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return SimpleIntegerBranchObj; } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); protected: /// Lower [0] and upper [1] bounds for the down arm (way_ = -1) double down_[2]; /// Lower [0] and upper [1] bounds for the up arm (way_ = 1) double up_[2]; #ifdef FUNNY_BRANCHING /** Which variable (top bit if upper bound changing) next bit if changing on down branch only */ int * variables_; // New bound double * newBounds_; /// Number of Extra bound changes int numberExtraChangedBounds_; #endif }; /// Define a single integer class class CbcSimpleInteger : public CbcObject { public: // Default Constructor CbcSimpleInteger (); // Useful constructor - passed model and index CbcSimpleInteger (CbcModel * model, int iColumn, double breakEven = 0.5); // Useful constructor - passed model and Osi object CbcSimpleInteger (CbcModel * model, const OsiSimpleInteger * object); // Copy constructor CbcSimpleInteger ( const CbcSimpleInteger &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcSimpleInteger & operator=( const CbcSimpleInteger& rhs); // Destructor virtual ~CbcSimpleInteger (); /// Construct an OsiSimpleInteger object OsiSimpleInteger * osiObject() const; /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /** Set bounds to fix the variable at the current (integer) value. Given an integer value, set the lower and upper bounds to fix the variable. Returns amount it had to move variable. */ virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; /** Create a branching object and indicate which way to branch first. The branching object has to know how to create branches (fix variables, etc.) */ virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Fills in a created branching object void fillCreateBranch(CbcIntegerBranchingObject * branching, const OsiBranchingInformation * info, int way) ; using CbcObject::solverBranch ; /** Create an OsiSolverBranch object This returns NULL if branch not represented by bound changes */ virtual OsiSolverBranch * solverBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info) const; /** Set bounds to fix the variable at the current (integer) value. Given an integer value, set the lower and upper bounds to fix the variable. The algorithm takes a bit of care in order to compensate for minor numerical inaccuracy. */ virtual void feasibleRegion(); /** Column number if single column object -1 otherwise, so returns >= 0 Used by heuristics */ virtual int columnNumber() const; /// Set column number inline void setColumnNumber(int value) { columnNumber_ = value; } /** Reset variable bounds to their original values. Bounds may be tightened, so it may be good to be able to set this info in object. */ virtual void resetBounds(const OsiSolverInterface * solver) ; /** Change column numbers after preprocessing */ virtual void resetSequenceEtc(int numberColumns, const int * originalColumns) ; /// Original bounds inline double originalLowerBound() const { return originalLower_; } inline void setOriginalLowerBound(double value) { originalLower_ = value; } inline double originalUpperBound() const { return originalUpper_; } inline void setOriginalUpperBound(double value) { originalUpper_ = value; } /// Breakeven e.g 0.7 -> >= 0.7 go up first inline double breakEven() const { return breakEven_; } /// Set breakeven e.g 0.7 -> >= 0.7 go up first inline void setBreakEven(double value) { breakEven_ = value; } protected: /// data /// Original lower bound double originalLower_; /// Original upper bound double originalUpper_; /// Breakeven i.e. >= this preferred is up double breakEven_; /// Column number in model int columnNumber_; /// If -1 down always chosen first, +1 up always, 0 normal int preferredWay_; }; #endif Cbc-2.8.12/src/CbcFixVariable.cpp0000644000076600007660000001362712131315050015050 0ustar coincoin// $Id: CbcFixVariable.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcFixVariable.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" //############################################################################## // Default Constructor CbcFixVariable::CbcFixVariable () : CbcConsequence(), numberStates_(0), states_(NULL), startLower_(NULL), startUpper_(NULL), newBound_(NULL), variable_(NULL) { } // One useful Constructor CbcFixVariable::CbcFixVariable (int numberStates, const int * states, const int * numberNewLower, const int ** newLowerValue, const int ** lowerColumn, const int * numberNewUpper, const int ** newUpperValue, const int ** upperColumn) : CbcConsequence(), states_(NULL), startLower_(NULL), startUpper_(NULL), newBound_(NULL), variable_(NULL) { // How much space numberStates_ = numberStates; if (numberStates_) { states_ = new int[numberStates_]; memcpy(states_, states, numberStates_*sizeof(int)); int i; int n = 0; startLower_ = new int[numberStates_+1]; startUpper_ = new int[numberStates_+1]; startLower_[0] = 0; //count for (i = 0; i < numberStates_; i++) { n += numberNewLower[i]; startUpper_[i] = n; n += numberNewUpper[i]; startLower_[i+1] = n; } newBound_ = new double [n]; variable_ = new int [n]; n = 0; for (i = 0; i < numberStates_; i++) { int j; int k; const int * bound; const int * variable; k = numberNewLower[i]; bound = newLowerValue[i]; variable = lowerColumn[i]; for (j = 0; j < k; j++) { newBound_[n] = bound[j]; variable_[n++] = variable[j]; } k = numberNewUpper[i]; bound = newUpperValue[i]; variable = upperColumn[i]; for (j = 0; j < k; j++) { newBound_[n] = bound[j]; variable_[n++] = variable[j]; } } } } // Copy constructor CbcFixVariable::CbcFixVariable ( const CbcFixVariable & rhs) : CbcConsequence(rhs) { numberStates_ = rhs.numberStates_; states_ = NULL; startLower_ = NULL; startUpper_ = NULL; newBound_ = NULL; variable_ = NULL; if (numberStates_) { states_ = CoinCopyOfArray(rhs.states_, numberStates_); startLower_ = CoinCopyOfArray(rhs.startLower_, numberStates_ + 1); startUpper_ = CoinCopyOfArray(rhs.startUpper_, numberStates_ + 1); int n = startLower_[numberStates_]; newBound_ = CoinCopyOfArray(rhs.newBound_, n); variable_ = CoinCopyOfArray(rhs.variable_, n); } } // Clone CbcConsequence * CbcFixVariable::clone() const { return new CbcFixVariable(*this); } // Assignment operator CbcFixVariable & CbcFixVariable::operator=( const CbcFixVariable & rhs) { if (this != &rhs) { CbcConsequence::operator=(rhs); delete [] states_; delete [] startLower_; delete [] startUpper_; delete [] newBound_; delete [] variable_; states_ = NULL; startLower_ = NULL; startUpper_ = NULL; newBound_ = NULL; variable_ = NULL; numberStates_ = rhs.numberStates_; if (numberStates_) { states_ = CoinCopyOfArray(rhs.states_, numberStates_); startLower_ = CoinCopyOfArray(rhs.startLower_, numberStates_ + 1); startUpper_ = CoinCopyOfArray(rhs.startUpper_, numberStates_ + 1); int n = startLower_[numberStates_]; newBound_ = CoinCopyOfArray(rhs.newBound_, n); variable_ = CoinCopyOfArray(rhs.variable_, n); } } return *this; } // Destructor CbcFixVariable::~CbcFixVariable () { delete [] states_; delete [] startLower_; delete [] startUpper_; delete [] newBound_; delete [] variable_; } // Set up a startLower for a single member void CbcFixVariable::applyToSolver(OsiSolverInterface * solver, int state) const { assert (state == -9999 || state == 9999); // Find state int find; for (find = 0; find < numberStates_; find++) if (states_[find] == state) break; if (find == numberStates_) return; int i; // Set new lower bounds for (i = startLower_[find]; i < startUpper_[find]; i++) { int iColumn = variable_[i]; double value = newBound_[i]; double oldValue = solver->getColLower()[iColumn]; //printf("for %d old lower bound %g, new %g",iColumn,oldValue,value); solver->setColLower(iColumn, CoinMax(value, oldValue)); //printf(" => %g\n",solver->getColLower()[iColumn]); } // Set new upper bounds for (i = startUpper_[find]; i < startLower_[find+1]; i++) { int iColumn = variable_[i]; double value = newBound_[i]; double oldValue = solver->getColUpper()[iColumn]; //printf("for %d old upper bound %g, new %g",iColumn,oldValue,value); solver->setColUpper(iColumn, CoinMin(value, oldValue)); //printf(" => %g\n",solver->getColUpper()[iColumn]); } } Cbc-2.8.12/src/CbcObjectUpdateData.hpp0000644000076600007660000000304612131315050016016 0ustar coincoin// $Id: CbcObjectUpdateData.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/12/2009 carved from CbcBranchBase #ifndef CbcObjectUpdateData_H #define CbcObjectUpdateData_H #include "CbcObject.hpp" /* This stores data so an object can be updated */ class CbcObjectUpdateData { public: /// Default Constructor CbcObjectUpdateData (); /// Useful constructor CbcObjectUpdateData (CbcObject * object, int way, double change, int status, int intDecrease_, double branchingValue); /// Copy constructor CbcObjectUpdateData ( const CbcObjectUpdateData &); /// Assignment operator CbcObjectUpdateData & operator=( const CbcObjectUpdateData& rhs); /// Destructor virtual ~CbcObjectUpdateData (); public: /// data /// Object CbcObject * object_; /// Branch as defined by instance of CbcObject int way_; /// Object number int objectNumber_; /// Change in objective double change_; /// Status 0 Optimal, 1 infeasible, 2 unknown int status_; /// Decrease in number unsatisfied int intDecrease_; /// Branching value double branchingValue_; /// Objective value before branching double originalObjective_; /// Current cutoff double cutoff_; }; #endif Cbc-2.8.12/src/CbcSimpleIntegerDynamicPseudoCost.hpp0000644000076600007660000003725512131315050020751 0ustar coincoin// $Id: CbcSimpleIntegerDynamicPseudoCost.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/17/2009 - carved out of CbcBranchDynamic #ifndef CbcSimpleIntegerDynamicPseudoCost_H #define CbcSimpleIntegerDynamicPseudoCost_H #include "CbcSimpleInteger.hpp" #define TYPERATIO 0.9 #define MINIMUM_MOVEMENT 0.1 #define TYPE2 0 // was 1 - but that looks flakey #define INFEAS 1 #define MOD_SHADOW 1 // weight at 1.0 is max min #define WEIGHT_AFTER 0.8 #define WEIGHT_BEFORE 0.1 //Stolen from Constraint Integer Programming book (with epsilon change) #define WEIGHT_PRODUCT /** Define a single integer class but with dynamic pseudo costs. Based on work by Achterberg, Koch and Martin. It is wild overkill but to keep design all twiddly things are in each. This could be used for fine tuning. */ class CbcSimpleIntegerDynamicPseudoCost : public CbcSimpleInteger { public: // Default Constructor CbcSimpleIntegerDynamicPseudoCost (); // Useful constructor - passed model index CbcSimpleIntegerDynamicPseudoCost (CbcModel * model, int iColumn, double breakEven = 0.5); // Useful constructor - passed model index and pseudo costs CbcSimpleIntegerDynamicPseudoCost (CbcModel * model, int iColumn, double downDynamicPseudoCost, double upDynamicPseudoCost); // Useful constructor - passed model index and pseudo costs CbcSimpleIntegerDynamicPseudoCost (CbcModel * model, int dummy, int iColumn, double downDynamicPseudoCost, double upDynamicPseudoCost); // Copy constructor CbcSimpleIntegerDynamicPseudoCost ( const CbcSimpleIntegerDynamicPseudoCost &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcSimpleIntegerDynamicPseudoCost & operator=( const CbcSimpleIntegerDynamicPseudoCost& rhs); // Destructor virtual ~CbcSimpleIntegerDynamicPseudoCost (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Fills in a created branching object void fillCreateBranch(CbcIntegerBranchingObject * branching, const OsiBranchingInformation * info, int way) ; /** Pass in information on branch just done and create CbcObjectUpdateData instance. If object does not need data then backward pointer will be NULL. Assumes can get information from solver */ virtual CbcObjectUpdateData createUpdateInformation(const OsiSolverInterface * solver, const CbcNode * node, const CbcBranchingObject * branchingObject); /// Update object by CbcObjectUpdateData virtual void updateInformation(const CbcObjectUpdateData & data) ; /// Copy some information i.e. just variable stuff void copySome(const CbcSimpleIntegerDynamicPseudoCost * otherObject); /// Updates stuff like pseudocosts before threads virtual void updateBefore(const OsiObject * rhs) ; /// Updates stuff like pseudocosts after threads finished virtual void updateAfter(const OsiObject * rhs, const OsiObject * baseObject) ; /// Updates stuff like pseudocosts after mini branch and bound void updateAfterMini(int numberDown, int numberDownInfeasible, double sumDown, int numberUp, int numberUpInfeasible, double sumUp); using CbcSimpleInteger::solverBranch ; /** Create an OsiSolverBranch object This returns NULL if branch not represented by bound changes */ virtual OsiSolverBranch * solverBranch() const; /// Down pseudo cost inline double downDynamicPseudoCost() const { return downDynamicPseudoCost_; } /// Set down pseudo cost void setDownDynamicPseudoCost(double value) ; /// Modify down pseudo cost in a slightly different way void updateDownDynamicPseudoCost(double value); /// Up pseudo cost inline double upDynamicPseudoCost() const { return upDynamicPseudoCost_; } /// Set up pseudo cost void setUpDynamicPseudoCost(double value); /// Modify up pseudo cost in a slightly different way void updateUpDynamicPseudoCost(double value); /// Down pseudo shadow price cost inline double downShadowPrice() const { return downShadowPrice_; } /// Set down pseudo shadow price cost inline void setDownShadowPrice(double value) { downShadowPrice_ = value; } /// Up pseudo shadow price cost inline double upShadowPrice() const { return upShadowPrice_; } /// Set up pseudo shadow price cost inline void setUpShadowPrice(double value) { upShadowPrice_ = value; } /// Up down separator inline double upDownSeparator() const { return upDownSeparator_; } /// Set up down separator inline void setUpDownSeparator(double value) { upDownSeparator_ = value; } /// Down sum cost inline double sumDownCost() const { return sumDownCost_; } /// Set down sum cost inline void setSumDownCost(double value) { sumDownCost_ = value; } /// Add to down sum cost and set last and square inline void addToSumDownCost(double value) { sumDownCost_ += value; lastDownCost_ = value; } /// Up sum cost inline double sumUpCost() const { return sumUpCost_; } /// Set up sum cost inline void setSumUpCost(double value) { sumUpCost_ = value; } /// Add to up sum cost and set last and square inline void addToSumUpCost(double value) { sumUpCost_ += value; lastUpCost_ = value; } /// Down sum change inline double sumDownChange() const { return sumDownChange_; } /// Set down sum change inline void setSumDownChange(double value) { sumDownChange_ = value; } /// Add to down sum change inline void addToSumDownChange(double value) { sumDownChange_ += value; } /// Up sum change inline double sumUpChange() const { return sumUpChange_; } /// Set up sum change inline void setSumUpChange(double value) { sumUpChange_ = value; } /// Add to up sum change and set last and square inline void addToSumUpChange(double value) { sumUpChange_ += value; } /// Sum down decrease number infeasibilities from strong or actual inline double sumDownDecrease() const { return sumDownDecrease_; } /// Set sum down decrease number infeasibilities from strong or actual inline void setSumDownDecrease(double value) { sumDownDecrease_ = value; } /// Add to sum down decrease number infeasibilities from strong or actual inline void addToSumDownDecrease(double value) { sumDownDecrease_ += value;/*lastDownDecrease_ = (int) value;*/ } /// Sum up decrease number infeasibilities from strong or actual inline double sumUpDecrease() const { return sumUpDecrease_; } /// Set sum up decrease number infeasibilities from strong or actual inline void setSumUpDecrease(double value) { sumUpDecrease_ = value; } /// Add to sum up decrease number infeasibilities from strong or actual inline void addToSumUpDecrease(double value) { sumUpDecrease_ += value;/*lastUpDecrease_ = (int) value;*/ } /// Down number times inline int numberTimesDown() const { return numberTimesDown_; } /// Set down number times inline void setNumberTimesDown(int value) { numberTimesDown_ = value; } /// Increment down number times inline void incrementNumberTimesDown() { numberTimesDown_++; } /// Up number times inline int numberTimesUp() const { return numberTimesUp_; } /// Set up number times inline void setNumberTimesUp(int value) { numberTimesUp_ = value; } /// Increment up number times inline void incrementNumberTimesUp() { numberTimesUp_++; } /// Down number times infeasible inline int numberTimesDownInfeasible() const { return numberTimesDownInfeasible_; } /// Set down number times infeasible inline void setNumberTimesDownInfeasible(int value) { numberTimesDownInfeasible_ = value; } /// Increment down number times infeasible inline void incrementNumberTimesDownInfeasible() { numberTimesDownInfeasible_++; } /// Up number times infeasible inline int numberTimesUpInfeasible() const { return numberTimesUpInfeasible_; } /// Set up number times infeasible inline void setNumberTimesUpInfeasible(int value) { numberTimesUpInfeasible_ = value; } /// Increment up number times infeasible inline void incrementNumberTimesUpInfeasible() { numberTimesUpInfeasible_++; } /// Number of times before trusted inline int numberBeforeTrust() const { return numberBeforeTrust_; } /// Set number of times before trusted inline void setNumberBeforeTrust(int value) { numberBeforeTrust_ = value; } /// Increment number of times before trusted inline void incrementNumberBeforeTrust() { numberBeforeTrust_++; } /// Return "up" estimate virtual double upEstimate() const; /// Return "down" estimate (default 1.0e-5) virtual double downEstimate() const; /// method - see below for details inline int method() const { return method_; } /// Set method inline void setMethod(int value) { method_ = value; } /// Pass in information on a down branch void setDownInformation(double changeObjectiveDown, int changeInfeasibilityDown); /// Pass in information on a up branch void setUpInformation(double changeObjectiveUp, int changeInfeasibilityUp); /// Pass in probing information void setProbingInformation(int fixedDown, int fixedUp); /// Print - 0 -summary, 1 just before strong void print(int type = 0, double value = 0.0) const; /// Same - returns true if contents match(ish) bool same(const CbcSimpleIntegerDynamicPseudoCost * obj) const; protected: /// data /// Down pseudo cost double downDynamicPseudoCost_; /// Up pseudo cost double upDynamicPseudoCost_; /** Up/down separator If >0.0 then do first branch up if value-floor(value) >= this value */ double upDownSeparator_; /// Sum down cost from strong or actual double sumDownCost_; /// Sum up cost from strong or actual double sumUpCost_; /// Sum of all changes to x when going down double sumDownChange_; /// Sum of all changes to x when going up double sumUpChange_; /// Current pseudo-shadow price estimate down mutable double downShadowPrice_; /// Current pseudo-shadow price estimate up mutable double upShadowPrice_; /// Sum down decrease number infeasibilities from strong or actual double sumDownDecrease_; /// Sum up decrease number infeasibilities from strong or actual double sumUpDecrease_; /// Last down cost from strong (i.e. as computed by last strong) double lastDownCost_; /// Last up cost from strong (i.e. as computed by last strong) double lastUpCost_; /// Last down decrease number infeasibilities from strong (i.e. as computed by last strong) mutable int lastDownDecrease_; /// Last up decrease number infeasibilities from strong (i.e. as computed by last strong) mutable int lastUpDecrease_; /// Number of times we have gone down int numberTimesDown_; /// Number of times we have gone up int numberTimesUp_; /// Number of times we have been infeasible going down int numberTimesDownInfeasible_; /// Number of times we have been infeasible going up int numberTimesUpInfeasible_; /// Number of branches before we trust int numberBeforeTrust_; /// Number of local probing fixings going down int numberTimesDownLocalFixed_; /// Number of local probing fixings going up int numberTimesUpLocalFixed_; /// Number of total probing fixings going down double numberTimesDownTotalFixed_; /// Number of total probing fixings going up double numberTimesUpTotalFixed_; /// Number of times probing done int numberTimesProbingTotal_; /// Number of times infeasible when tested /** Method - 0 - pseudo costs 1 - probing */ int method_; }; /** Simple branching object for an integer variable with pseudo costs This object can specify a two-way branch on an integer variable. For each arm of the branch, the upper and lower bounds on the variable can be independently specified. Variable_ holds the index of the integer variable in the integerVariable_ array of the model. */ class CbcIntegerPseudoCostBranchingObject : public CbcIntegerBranchingObject { public: /// Default constructor CbcIntegerPseudoCostBranchingObject (); /** Create a standard floor/ceiling branch object Specifies a simple two-way branch. Let \p value = x*. One arm of the branch will be is lb <= x <= floor(x*), the other ceil(x*) <= x <= ub. Specify way = -1 to set the object state to perform the down arm first, way = 1 for the up arm. */ CbcIntegerPseudoCostBranchingObject (CbcModel *model, int variable, int way , double value) ; /** Create a degenerate branch object Specifies a `one-way branch'. Calling branch() for this object will always result in lowerValue <= x <= upperValue. Used to fix a variable when lowerValue = upperValue. */ CbcIntegerPseudoCostBranchingObject (CbcModel *model, int variable, int way, double lowerValue, double upperValue) ; /// Copy constructor CbcIntegerPseudoCostBranchingObject ( const CbcIntegerPseudoCostBranchingObject &); /// Assignment operator CbcIntegerPseudoCostBranchingObject & operator= (const CbcIntegerPseudoCostBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; /// Destructor virtual ~CbcIntegerPseudoCostBranchingObject (); using CbcBranchingObject::branch ; /** \brief Sets the bounds for the variable according to the current arm of the branch and advances the object state to the next arm. This version also changes guessed objective value */ virtual double branch(); /// Change in guessed inline double changeInGuessed() const { return changeInGuessed_; } /// Set change in guessed inline void setChangeInGuessed(double value) { changeInGuessed_ = value; } /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return SimpleIntegerDynamicPseudoCostBranchObj; } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); protected: /// Change in guessed objective value for next branch double changeInGuessed_; }; #endif Cbc-2.8.12/src/CbcHeuristicRENS.hpp0000644000076600007660000000346012131315050015302 0ustar coincoin// $Id: CbcHeuristicRENS.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // edwin 12/5/09 carved out of CbcHeuristicRINS #ifndef CbcHeuristicRENS_H #define CbcHeuristicRENS_H #include "CbcHeuristic.hpp" /** LocalSearch class */ class CbcHeuristicRENS : public CbcHeuristic { public: // Default Constructor CbcHeuristicRENS (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicRENS (CbcModel & model); // Copy constructor CbcHeuristicRENS ( const CbcHeuristicRENS &); // Destructor ~CbcHeuristicRENS (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicRENS & operator=(const CbcHeuristicRENS& rhs); /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) This does Relaxation Extension Neighborhood Search Does not run if when_<2 and a solution exists */ virtual int solution(double & objectiveValue, double * newSolution); /// Set type inline void setRensType(int value) { rensType_ = value;} protected: // Data /// Number of tries int numberTries_; /** Type 0 - fix at LB 1 - fix on dj 2 - fix at UB as well 3 - fix on 0.01*average dj add 16 to allow two tries */ int rensType_; }; #endif Cbc-2.8.12/src/CbcNWay.hpp0000644000076600007660000001222712131315050013532 0ustar coincoin// $Id: CbcNWay.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/9/2009-- carved out of CbcBranchActual /** Define an n-way class for variables. Only valid value is one at UB others at LB Normally 0-1 */ #ifndef CbcNWay_H #define CbcNWay_H class CbcNWay : public CbcObject { public: // Default Constructor CbcNWay (); /** Useful constructor (which are matrix indices) */ CbcNWay (CbcModel * model, int numberMembers, const int * which, int identifier); // Copy constructor CbcNWay ( const CbcNWay &); /// Clone virtual CbcObject * clone() const; /// Assignment operator CbcNWay & operator=( const CbcNWay& rhs); /// Destructor virtual ~CbcNWay (); /// Set up a consequence for a single member void setConsequence(int iColumn, const CbcConsequence & consequence); /// Applies a consequence for a single member void applyConsequence(int iSequence, int state) const; /// Infeasibility - large is 0.5 (and 0.5 will give this) virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /// This looks at solution and sets bounds to contain solution virtual void feasibleRegion(); /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Number of members inline int numberMembers() const { return numberMembers_; } /// Members (indices in range 0 ... numberColumns-1) inline const int * members() const { return members_; } /// Redoes data when sequence numbers change virtual void redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns); protected: /// data /// Number of members int numberMembers_; /// Members (indices in range 0 ... numberColumns-1) int * members_; /// Consequences (normally NULL) CbcConsequence ** consequence_; }; /** N way branching Object class. Variable is number of set. */ class CbcNWayBranchingObject : public CbcBranchingObject { public: // Default Constructor CbcNWayBranchingObject (); /** Useful constructor - order had matrix indices way_ -1 corresponds to setting first, +1 to second, +3 etc. this is so -1 and +1 have similarity to normal */ CbcNWayBranchingObject (CbcModel * model, const CbcNWay * nway, int numberBranches, const int * order); // Copy constructor CbcNWayBranchingObject ( const CbcNWayBranchingObject &); // Assignment operator CbcNWayBranchingObject & operator=( const CbcNWayBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; // Destructor virtual ~CbcNWayBranchingObject (); using CbcBranchingObject::branch ; /// Does next branch and updates state virtual double branch(); #ifdef JJF_ZERO // FIXME: what do we need to do here? /** Reset every information so that the branching object appears to point to the previous child. This method does not need to modify anything in any solver. */ virtual void previousBranch(); #endif using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /** The number of branch arms created for this branching object */ virtual int numberBranches() const { return numberInSet_; } /// Is this a two way object (-1 down, +1 up) virtual bool twoWay() const { return false; } /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return NWayBranchObj; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const; /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); private: /// order of branching - points back to CbcNWay int * order_; /// Points back to object const CbcNWay * object_; /// Number in set int numberInSet_; }; #endif Cbc-2.8.12/src/Cbc_C_Interface.h0000644000076600007660000003064512376140747014645 0ustar coincoin/* $Id: Cbc_C_Interface.h 2059 2014-08-23 16:31:35Z tkr $ */ /* Copyright (C) 2004 International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). */ #ifndef CbcModelC_H #define CbcModelC_H /* include all defines and ugly stuff */ #include "Coin_C_defines.h" #include /* * Original verison contributed by Bob Entriken, * significantly updated by Miles Lubin. */ #ifdef __cplusplus extern "C" { #endif /**@name Constructors and destructor This is a "C" interface to Cbc. The user does not need to know structure of Cbc_Model. */ /*@{*/ /** Default Cbc_Model constructor */ COINLIBAPI Cbc_Model * COINLINKAGE Cbc_newModel(void) ; /** Cbc_Model Destructor */ COINLIBAPI void COINLINKAGE Cbc_deleteModel(Cbc_Model * model) ; /** Current version of Cbc */ COINLIBAPI const char* COINLINKAGE Cbc_getVersion(void) ; /*@}*/ /**@name Getting and setting model data Note that problem access and modification methods, such as getColLower and setColLower, are *not valid* after calling Cbc_solve(). Therefore it is not recommended to reuse a Cbc_Model object for multiple solves. A workaround is to call Cbc_clone() before solving. * */ /*@{*/ /** Loads a problem (the constraints on the rows are given by lower and upper bounds). If a pointer is NULL then the following values are the default:
  • colub: all columns have upper bound infinity
  • collb: all columns have lower bound 0
  • rowub: all rows have upper bound infinity
  • rowlb: all rows have lower bound -infinity
  • obj: all variables have 0 objective coefficient
The constraint matrix is given in standard compressed sparse column (without gaps).
  • start[i] stores the starting index of the ith column
  • index[k] stores the row index of the kth nonzero element
  • value[k] stores the coefficient of the kth nonzero element
*/ COINLIBAPI void COINLINKAGE Cbc_loadProblem (Cbc_Model * model, const int numcols, const int numrows, const CoinBigIndex * start, const int* index, const double* value, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub) ; /** Read an mps file from the given filename */ COINLIBAPI int COINLINKAGE Cbc_readMps(Cbc_Model * model, const char *filename) ; /** Write an mps file from the given filename */ COINLIBAPI void COINLINKAGE Cbc_writeMps(Cbc_Model * model, const char *filename) ; /** Provide an initial feasible solution to accelerate branch-and-bound Note that feasibility of the solution is *not* verified. */ COINLIBAPI void COINLINKAGE Cbc_setInitialSolution(Cbc_Model *model, const double * sol) ; /** Fills in array with problem name */ COINLIBAPI void COINLINKAGE Cbc_problemName(Cbc_Model * model, int maxNumberCharacters, char * array) ; /** Sets problem name. \p array must be a null-terminated string. */ COINLIBAPI int COINLINKAGE Cbc_setProblemName(Cbc_Model * model, const char * array) ; /** Number of nonzero elements in constraint matrix */ COINLIBAPI int COINLINKAGE Cbc_getNumElements(Cbc_Model * model) ; /** "Column start" vector of constraint matrix. Same format as Cbc_loadProblem() */ COINLIBAPI const CoinBigIndex * COINLINKAGE Cbc_getVectorStarts(Cbc_Model * model) ; /** "Row index" vector of constraint matrix */ COINLIBAPI const int * COINLINKAGE Cbc_getIndices(Cbc_Model * model) ; /** Coefficient vector of constraint matrix */ COINLIBAPI const double * COINLINKAGE Cbc_getElements(Cbc_Model * model) ; /** Maximum lenght of a row or column name */ COINLIBAPI size_t COINLINKAGE Cbc_maxNameLength(Cbc_Model * model) ; /** Fill in first maxLength bytes of name array with a row name */ COINLIBAPI void COINLINKAGE Cbc_getRowName(Cbc_Model * model, int iRow, char * name, size_t maxLength) ; /** Fill in first maxLength bytes of name array with a column name */ COINLIBAPI void COINLINKAGE Cbc_getColName(Cbc_Model * model, int iColumn, char * name, size_t maxLength) ; /** Set the name of a column */ COINLIBAPI void COINLINKAGE Cbc_setColName(Cbc_Model * model, int iColumn, const char * name) ; /** Set the name of a row */ COINLIBAPI void COINLINKAGE Cbc_setRowName(Cbc_Model * model, int iRow, const char * name) ; /** Number of constraints in the model */ COINLIBAPI int COINLINKAGE Cbc_getNumRows(Cbc_Model * model) ; /** Number of variables in the model */ COINLIBAPI int COINLINKAGE Cbc_getNumCols(Cbc_Model * model) ; /** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore) */ COINLIBAPI void COINLINKAGE Cbc_setObjSense(Cbc_Model * model, double sense) ; /** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore) */ COINLIBAPI double COINLINKAGE Cbc_getObjSense(Cbc_Model * model) ; /** Constraint lower bounds */ COINLIBAPI const double* COINLINKAGE Cbc_getRowLower(Cbc_Model * model) ; /** Set the lower bound of a single constraint */ COINLIBAPI void COINLINKAGE Cbc_setRowLower(Cbc_Model * model, int index, double value) ; /** Constraint upper bounds */ COINLIBAPI const double* COINLINKAGE Cbc_getRowUpper(Cbc_Model * model) ; /** Set the upper bound of a single constraint */ COINLIBAPI void COINLINKAGE Cbc_setRowUpper(Cbc_Model * model, int index, double value) ; /** Objective vector */ COINLIBAPI const double * COINLINKAGE Cbc_getObjCoefficients(Cbc_Model * model) ; /** Set the objective coefficient of a single variable */ COINLIBAPI void COINLINKAGE Cbc_setObjCoeff(Cbc_Model * model, int index, double value) ; /** Variable lower bounds */ COINLIBAPI const double * COINLINKAGE Cbc_getColLower(Cbc_Model * model) ; /** Set the lower bound of a single variable */ COINLIBAPI void COINLINKAGE Cbc_setColLower(Cbc_Model * model, int index, double value) ; /** Variable upper bounds */ COINLIBAPI const double * COINLINKAGE Cbc_getColUpper(Cbc_Model * model) ; /** Set the upper bound of a single variable */ COINLIBAPI void COINLINKAGE Cbc_setColUpper(Cbc_Model * model, int index, double value) ; /** Determine whether the ith variable is integer restricted */ COINLIBAPI int COINLINKAGE Cbc_isInteger(Cbc_Model * model, int i) ; /** Set this variable to be continuous */ COINLIBAPI void COINLINKAGE Cbc_setContinuous(Cbc_Model * model, int iColumn) ; /** Set this variable to be integer */ COINLIBAPI void COINLINKAGE Cbc_setInteger(Cbc_Model * model, int iColumn) ; /** Add SOS constraints to the model using row-order matrix * Unable to confirm that this function is working. */ COINLIBAPI void COINLINKAGE Cbc_addSOS(Cbc_Model * model, int numRows, const int * rowStarts, const int * colIndices, const double * weights, const int type) ; /** Print the model */ COINLIBAPI void COINLINKAGE Cbc_printModel(Cbc_Model * model, const char * argPrefix) ; /** Return a copy of this model */ COINLIBAPI Cbc_Model * COINLINKAGE Cbc_clone(Cbc_Model * model) ; /*@}*/ /**@name Solver parameters */ /*@{*/ /** Set parameter "name" to value "value". Note that this * translates directly to using "-name value" as a * command-line argument to Cbc.*/ COINLIBAPI void COINLINKAGE Cbc_setParameter(Cbc_Model * model, const char * name, const char * value) ; /*@}*/ /**@name Message handling. Call backs are handled by ONE function */ /*@{*/ /** Pass in Callback function. Message numbers up to 1000000 are Clp, Coin ones have 1000000 added */ COINLIBAPI void COINLINKAGE Cbc_registerCallBack(Cbc_Model * model, cbc_callback userCallBack) ; /** Unset Callback function */ COINLIBAPI void COINLINKAGE Cbc_clearCallBack(Cbc_Model * model) ; /*@}*/ /**@name Solving the model */ /*@{*/ /* Solve the model with Cbc (using CbcMain1). */ COINLIBAPI int COINLINKAGE Cbc_solve(Cbc_Model * model) ; /*@}*/ /**@name Accessing the solution and solution status */ /*@{*/ /** Sum of primal infeasibilities */ COINLIBAPI double COINLINKAGE Cbc_sumPrimalInfeasibilities(Cbc_Model * model) ; /** Number of primal infeasibilities */ COINLIBAPI int COINLINKAGE Cbc_numberPrimalInfeasibilities(Cbc_Model * model) ; /** Just check solution (for external use) - sets sum of infeasibilities etc */ COINLIBAPI void COINLINKAGE Cbc_checkSolution(Cbc_Model * model) ; /** Number of iterations */ COINLIBAPI int COINLINKAGE Cbc_getIterationCount(Cbc_Model * model) ; /** Are there a numerical difficulties? */ COINLIBAPI int COINLINKAGE Cbc_isAbandoned(Cbc_Model * model) ; /** Is optimality proven? */ COINLIBAPI int COINLINKAGE Cbc_isProvenOptimal(Cbc_Model * model) ; /** Is infeasiblity proven (or none better than cutoff)? */ COINLIBAPI int COINLINKAGE Cbc_isProvenInfeasible(Cbc_Model * model) ; /** Was continuous solution unbounded? */ COINLIBAPI int COINLINKAGE Cbc_isContinuousUnbounded(Cbc_Model * model) ; /** Node limit reached? */ COINLIBAPI int COINLINKAGE Cbc_isNodeLimitReached(Cbc_Model * model) ; /** Time limit reached? */ COINLIBAPI int COINLINKAGE Cbc_isSecondsLimitReached(Cbc_Model * model) ; /** Solution limit reached? */ COINLIBAPI int COINLINKAGE Cbc_isSolutionLimitReached(Cbc_Model * model) ; /** Are there numerical difficulties (for initialSolve) ? */ COINLIBAPI int COINLINKAGE Cbc_isInitialSolveAbandoned(Cbc_Model * model) ; /** Is optimality proven (for initialSolve) ? */ COINLIBAPI int COINLINKAGE Cbc_isInitialSolveProvenOptimal(Cbc_Model * model) ; /** Is primal infeasiblity proven (for initialSolve) ? */ COINLIBAPI int COINLINKAGE Cbc_isInitialSolveProvenPrimalInfeasible(Cbc_Model * model) ; /** "row" solution * This is the vector A*x, where A is the constraint matrix * and x is the current solution. */ COINLIBAPI const double * COINLINKAGE Cbc_getRowActivity(Cbc_Model * model) ; /** Best feasible solution vector */ COINLIBAPI const double * COINLINKAGE Cbc_getColSolution(Cbc_Model * model) ; /** Objective value of best feasible solution */ COINLIBAPI double COINLINKAGE Cbc_getObjValue(Cbc_Model * model) ; /** Best known bound on the optimal objective value */ COINLIBAPI double COINLINKAGE Cbc_getBestPossibleObjValue(Cbc_Model * model) ; /** Number of nodes explored in B&B tree */ COINLIBAPI int COINLINKAGE Cbc_getNodeCount(Cbc_Model * model) ; /** Print the solution */ COINLIBAPI void COINLINKAGE Cbc_printSolution(Cbc_Model * model) ; /** Final status of problem Some of these can be found out by is...... functions -1 before branchAndBound 0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found (or check value of best solution) 1 stopped - on maxnodes, maxsols, maxtime 2 difficulties so run was abandoned (5 event user programmed event occurred) */ COINLIBAPI int COINLINKAGE Cbc_status(Cbc_Model * model) ; /** Secondary status of problem -1 unset (status_ will also be -1) 0 search completed with solution 1 linear relaxation not feasible (or worse than cutoff) 2 stopped on gap 3 stopped on nodes 4 stopped on time 5 stopped on user event 6 stopped on solutions 7 linear relaxation unbounded 8 stopped on iteration limit */ COINLIBAPI int COINLINKAGE Cbc_secondaryStatus(Cbc_Model * model) ; /*@}*/ #ifdef __cplusplus } #endif #endif Cbc-2.8.12/src/CbcCbcParam.cpp0000644000076600007660000000053312131315050014314 0ustar coincoin/* $Id: CbcCbcParam.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2007, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CbcConfig.h" #ifndef COIN_HAS_CBC #define COIN_HAS_CBC #endif #include "CbcOrClpParam.cpp" Cbc-2.8.12/src/CbcSOS.hpp0000644000076600007660000002230112131315050013312 0ustar coincoin// $Id: CbcSOS.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/9/2009-- carved out of CbcBranchActual #ifndef CbcSOS_H #define CbcSOS_H /** \brief Branching object for Special Ordered Sets of type 1 and 2. SOS1 are an ordered set of variables where at most one variable can be non-zero. SOS1 are commonly defined with binary variables (interpreted as selection between alternatives) but this is not necessary. An SOS1 with all binary variables is a special case of a clique (setting any one variable to 1 forces all others to 0). In theory, the implementation makes no assumptions about integrality in Type 1 sets. In practice, there are places where the code seems to have been written with a binary SOS mindset. Current development of SOS branching objects is proceeding in OsiSOS. SOS2 are an ordered set of variables in which at most two consecutive variables can be non-zero and must sum to 1 (interpreted as interpolation between two discrete values). By definition the variables are non-integer. */ class CbcSOS : public CbcObject { public: // Default Constructor CbcSOS (); /** \brief Constructor with SOS type and member information Type specifies SOS 1 or 2. Identifier is an arbitrary value. Which should be an array of variable indices with numberMembers entries. Weights can be used to assign arbitrary weights to variables, in the order they are specified in which. If no weights are provided, a default array of 0, 1, 2, ... is generated. */ CbcSOS (CbcModel * model, int numberMembers, const int * which, const double * weights, int identifier, int type = 1); // Copy constructor CbcSOS ( const CbcSOS &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcSOS & operator=( const CbcSOS& rhs); // Destructor virtual ~CbcSOS (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /// This looks at solution and sets bounds to contain solution virtual void feasibleRegion(); /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /** Pass in information on branch just done and create CbcObjectUpdateData instance. If object does not need data then backward pointer will be NULL. Assumes can get information from solver */ virtual CbcObjectUpdateData createUpdateInformation(const OsiSolverInterface * solver, const CbcNode * node, const CbcBranchingObject * branchingObject); /// Update object by CbcObjectUpdateData virtual void updateInformation(const CbcObjectUpdateData & data) ; using CbcObject::solverBranch ; /** Create an OsiSolverBranch object This returns NULL if branch not represented by bound changes */ virtual OsiSolverBranch * solverBranch() const; /// Redoes data when sequence numbers change virtual void redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns); /// Construct an OsiSOS object OsiSOS * osiObject(const OsiSolverInterface * solver) const; /// Number of members inline int numberMembers() const { return numberMembers_; } /// Members (indices in range 0 ... numberColumns-1) inline const int * members() const { return members_; } /// SOS type inline int sosType() const { return sosType_; } /// Down number times inline int numberTimesDown() const { return numberTimesDown_; } /// Up number times inline int numberTimesUp() const { return numberTimesUp_; } /** Array of weights */ inline const double * weights() const { return weights_; } /// Set number of members inline void setNumberMembers(int n) { numberMembers_ = n; } /// Members (indices in range 0 ... numberColumns-1) inline int * mutableMembers() const { return members_; } /** Array of weights */ inline double * mutableWeights() const { return weights_; } /** \brief Return true if object can take part in normal heuristics */ virtual bool canDoHeuristics() const { return (sosType_ == 1 && integerValued_); } /// Set whether set is integer valued or not inline void setIntegerValued(bool yesNo) { integerValued_ = yesNo; } private: /// data /// Members (indices in range 0 ... numberColumns-1) int * members_; /** \brief Weights for individual members Arbitrary weights for members. Can be used to attach meaning to variable values independent of objective coefficients. For example, if the SOS set comprises binary variables used to choose a facility of a given size, the weight could be the corresponding facilty size. Fractional values of the SOS variables can then be used to estimate ideal facility size. Weights cannot be completely arbitrary. From the code, they must be differ by at least 1.0e-7 */ double * weights_; /// Current pseudo-shadow price estimate down mutable double shadowEstimateDown_; /// Current pseudo-shadow price estimate up mutable double shadowEstimateUp_; /// Down pseudo ratio double downDynamicPseudoRatio_; /// Up pseudo ratio double upDynamicPseudoRatio_; /// Number of times we have gone down int numberTimesDown_; /// Number of times we have gone up int numberTimesUp_; /// Number of members int numberMembers_; /// SOS type int sosType_; /// Whether integer valued bool integerValued_; }; /** Branching object for Special ordered sets Variable_ is the set id number (redundant, as the object also holds a pointer to the set. */ class CbcSOSBranchingObject : public CbcBranchingObject { public: // Default Constructor CbcSOSBranchingObject (); // Useful constructor CbcSOSBranchingObject (CbcModel * model, const CbcSOS * clique, int way, double separator); // Copy constructor CbcSOSBranchingObject ( const CbcSOSBranchingObject &); // Assignment operator CbcSOSBranchingObject & operator=( const CbcSOSBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; // Destructor virtual ~CbcSOSBranchingObject (); using CbcBranchingObject::branch ; /// Does next branch and updates state virtual double branch(); /** Update bounds in solver as in 'branch' and update given bounds. branchState is -1 for 'down' +1 for 'up' */ virtual void fix(OsiSolverInterface * solver, double * lower, double * upper, int branchState) const ; /** Reset every information so that the branching object appears to point to the previous child. This method does not need to modify anything in any solver. */ virtual void previousBranch() { CbcBranchingObject::previousBranch(); computeNonzeroRange(); } using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return SoSBranchObj; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const; /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); /** Fill out the \c firstNonzero_ and \c lastNonzero_ data members */ void computeNonzeroRange(); private: /// data const CbcSOS * set_; /// separator double separator_; /** The following two members describe the range in the members_ of the original object that whose upper bound is not fixed to 0. This is not necessary for Cbc to function correctly, this is there for heuristics so that separate branching decisions on the same object can be pooled into one branching object. */ int firstNonzero_; int lastNonzero_; }; #endif Cbc-2.8.12/src/CbcHeuristicDINS.hpp0000644000076600007660000000511712131315050015271 0ustar coincoin// $Id: CbcHeuristicDINS.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // edwin 12/5/09 carved out of CbcHeuristicRINS #ifndef CbcHeuristicDINS_H #define CbcHeuristicDINS_H #include "CbcHeuristic.hpp" class CbcHeuristicDINS : public CbcHeuristic { public: // Default Constructor CbcHeuristicDINS (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicDINS (CbcModel & model); // Copy constructor CbcHeuristicDINS ( const CbcHeuristicDINS &); // Destructor ~CbcHeuristicDINS (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicDINS & operator=(const CbcHeuristicDINS& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) This does Relaxation Induced Neighborhood Search */ virtual int solution(double & objectiveValue, double * newSolution); /// This version fixes stuff and does IP int solutionFix(double & objectiveValue, double * newSolution, const int * keep); /// Sets how often to do it inline void setHowOften(int value) { howOften_ = value; } /// Sets maximum number of solutions kept inline void setMaximumKeep(int value) { maximumKeepSolutions_ = value; } /// Sets tightness of extra constraint inline void setConstraint(int value) { localSpace_ = value; } protected: // Data /// Number of solutions so we can do something at solution int numberSolutions_; /// How often to do (code can change) int howOften_; /// Number of successes int numberSuccesses_; /// Number of tries int numberTries_; /// Maximum number of solutions to keep int maximumKeepSolutions_; /// Number of solutions kept int numberKeptSolutions_; /// Number of integer variables int numberIntegers_; /// Local parameter int localSpace_; /// Values of integer variables int ** values_; }; #endif Cbc-2.8.12/src/CbcNode.cpp0000644000076600007660000063107112371443325013555 0ustar coincoin/* $Id: CbcNode.cpp 2055 2014-08-09 16:05:41Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" //#define DEBUG_SOLUTION #ifdef DEBUG_SOLUTION #define COIN_DETAIL #endif #include //#define CBC_DEBUG 1 //#define CHECK_CUT_COUNTS //#define CHECK_NODE //#define CBC_CHECK_BASIS #include #include #define CUTS #include "OsiSolverInterface.hpp" #include "OsiChooseVariable.hpp" #include "OsiAuxInfo.hpp" #include "OsiSolverBranch.hpp" #include "CoinWarmStartBasis.hpp" #include "CoinTime.hpp" #include "CbcModel.hpp" #include "CbcNode.hpp" #include "CbcStatistics.hpp" #include "CbcStrategy.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchDynamic.hpp" #include "OsiRowCut.hpp" #include "OsiRowCutDebugger.hpp" #include "OsiCuts.hpp" #include "CbcCountRowCut.hpp" #include "CbcFeasibilityBase.hpp" #include "CbcMessage.hpp" #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #include "ClpSimplexOther.hpp" #endif using namespace std; #include "CglCutGenerator.hpp" CbcNode::CbcNode() : nodeInfo_(NULL), objectiveValue_(1.0e100), guessedObjectiveValue_(1.0e100), sumInfeasibilities_(0.0), branch_(NULL), depth_(-1), numberUnsatisfied_(0), nodeNumber_(-1), state_(0) { #ifdef CHECK_NODE printf("CbcNode %x Constructor\n", this); #endif } // Print void CbcNode::print() const { printf("number %d obj %g depth %d sumun %g nunsat %d state %d\n", nodeNumber_, objectiveValue_, depth_, sumInfeasibilities_, numberUnsatisfied_, state_); } CbcNode::CbcNode(CbcModel * model, CbcNode * lastNode) : nodeInfo_(NULL), objectiveValue_(1.0e100), guessedObjectiveValue_(1.0e100), sumInfeasibilities_(0.0), branch_(NULL), depth_(-1), numberUnsatisfied_(0), nodeNumber_(-1), state_(0) { #ifdef CHECK_NODE printf("CbcNode %x Constructor from model\n", this); #endif model->setObjectiveValue(this, lastNode); if (lastNode) { if (lastNode->nodeInfo_) { lastNode->nodeInfo_->increment(); } } nodeNumber_ = model->getNodeCount(); } #define CBC_NEW_CREATEINFO #ifdef CBC_NEW_CREATEINFO /* New createInfo, with basis manipulation hidden inside mergeBasis. Allows solvers to override and carry over all information from one basis to another. */ void CbcNode::createInfo (CbcModel *model, CbcNode *lastNode, const CoinWarmStartBasis *lastws, const double *lastLower, const double *lastUpper, int numberOldActiveCuts, int numberNewCuts) { OsiSolverInterface *solver = model->solver(); CbcStrategy *strategy = model->strategy(); /* The root --- no parent. Create full basis and bounds information. */ if (!lastNode) { if (!strategy) nodeInfo_ = new CbcFullNodeInfo(model, solver->getNumRows()); else nodeInfo_ = strategy->fullNodeInfo(model, solver->getNumRows()); } else { /* Not the root. Create an edit from the parent's basis & bound information. This is not quite as straightforward as it seems. We need to reintroduce cuts we may have dropped out of the basis, in the correct position, because this whole process is strictly positional. Start by grabbing the current basis. */ bool mustDeleteBasis; const CoinWarmStartBasis *ws = dynamic_cast(solver->getPointerToWarmStart(mustDeleteBasis)); assert(ws != NULL); // make sure not volume //int numberArtificials = lastws->getNumArtificial(); int numberColumns = solver->getNumCols(); int numberRowsAtContinuous = model->numberRowsAtContinuous(); int currentNumberCuts = model->currentNumberCuts(); # ifdef CBC_CHECK_BASIS std::cout << "Before expansion: orig " << numberRowsAtContinuous << ", old " << numberOldActiveCuts << ", new " << numberNewCuts << ", current " << currentNumberCuts << "." << std::endl ; ws->print(); # endif /* Clone the basis and resize it to hold the structural constraints, plus all the cuts: old cuts, both active and inactive (currentNumberCuts), and new cuts (numberNewCuts). This will become the expanded basis. */ CoinWarmStartBasis *expanded = dynamic_cast(ws->clone()) ; int iCompact = numberRowsAtContinuous + numberOldActiveCuts + numberNewCuts ; // int nPartial = numberRowsAtContinuous+currentNumberCuts; int iFull = numberRowsAtContinuous + currentNumberCuts + numberNewCuts; // int maxBasisLength = ((iFull+15)>>4)+((numberColumns+15)>>4); // printf("l %d full %d\n",maxBasisLength,iFull); expanded->resize(iFull, numberColumns); # ifdef CBC_CHECK_BASIS std::cout << "\tFull basis " << iFull << " rows, " << numberColumns << " columns; compact " << iCompact << " rows." << std::endl ; # endif /* Now flesh out the expanded basis. The clone already has the correct status information for the variables and for the structural (numberRowsAtContinuous) constraints. Any indices beyond nPartial must be cuts created while processing this node --- they can be copied en bloc into the correct position in the expanded basis. The space reserved for xferRows is a gross overestimate. */ CoinWarmStartBasis::XferVec xferRows ; xferRows.reserve(iFull - numberRowsAtContinuous + 1) ; if (numberNewCuts) { xferRows.push_back( CoinWarmStartBasis::XferEntry(iCompact - numberNewCuts, iFull - numberNewCuts, numberNewCuts)) ; } /* From nPartial down, record the entries we want to copy from the current basis (the entries for the active cuts; non-zero in the list returned by addedCuts). Fill the expanded basis with entries showing a status of basic for the deactivated (loose) cuts. */ CbcCountRowCut **cut = model->addedCuts(); iFull -= (numberNewCuts + 1) ; iCompact -= (numberNewCuts + 1) ; int runLen = 0 ; CoinWarmStartBasis::XferEntry entry(-1, -1, -1) ; while (iFull >= numberRowsAtContinuous) { for ( ; iFull >= numberRowsAtContinuous && cut[iFull-numberRowsAtContinuous] ; iFull--) runLen++ ; if (runLen) { iCompact -= runLen ; entry.first = iCompact + 1 ; entry.second = iFull + 1 ; entry.third = runLen ; runLen = 0 ; xferRows.push_back(entry) ; } for ( ; iFull >= numberRowsAtContinuous && !cut[iFull-numberRowsAtContinuous] ; iFull--) expanded->setArtifStatus(iFull, CoinWarmStartBasis::basic); } /* Finally, call mergeBasis to copy over entries from the current basis to the expanded basis. Since we cloned the expanded basis from the active basis and haven't changed the number of variables, only row status entries need to be copied. */ expanded->mergeBasis(ws, &xferRows, 0) ; #ifdef CBC_CHECK_BASIS std::cout << "Expanded basis:" << std::endl ; expanded->print() ; std::cout << "Diffing against:" << std::endl ; lastws->print() ; #endif assert (expanded->getNumArtificial() >= lastws->getNumArtificial()); #ifdef CLP_INVESTIGATE if (!expanded->fullBasis()) { int iFull = numberRowsAtContinuous + currentNumberCuts + numberNewCuts; printf("cont %d old %d new %d current %d full inc %d full %d\n", numberRowsAtContinuous, numberOldActiveCuts, numberNewCuts, currentNumberCuts, iFull, iFull - numberNewCuts); } #endif /* Now that we have two bases in proper positional correspondence, creating the actual diff is dead easy. Note that we're going to compare the expanded basis here to the stripped basis (lastws) produced by addCuts. It doesn't affect the correctness (the diff process has no knowledge of the meaning of an entry) but it does mean that we'll always generate a whack of diff entries because the expanded basis is considerably larger than the stripped basis. */ CoinWarmStartDiff *basisDiff = expanded->generateDiff(lastws) ; /* Diff the bound vectors. It's assumed the number of structural variables is not changing. For branching objects that change bounds on integer variables, we should see at least one bound change as a consequence of applying the branch that generated this subproblem from its parent. This need not hold for other types of branching objects (hyperplane branches, for example). */ const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double *boundChanges = new double [2*numberColumns] ; int *variables = new int [2*numberColumns] ; int numberChangedBounds = 0; int i; for (i = 0; i < numberColumns; i++) { if (lower[i] != lastLower[i]) { variables[numberChangedBounds] = i; boundChanges[numberChangedBounds++] = lower[i]; } if (upper[i] != lastUpper[i]) { variables[numberChangedBounds] = i | 0x80000000; boundChanges[numberChangedBounds++] = upper[i]; } #ifdef CBC_DEBUG if (lower[i] != lastLower[i]) { std::cout << "lower on " << i << " changed from " << lastLower[i] << " to " << lower[i] << std::endl ; } if (upper[i] != lastUpper[i]) { std::cout << "upper on " << i << " changed from " << lastUpper[i] << " to " << upper[i] << std::endl ; } #endif } #ifdef CBC_DEBUG std::cout << numberChangedBounds << " changed bounds." << std::endl ; #endif //if (lastNode->branchingObject()->boundBranch()) //assert (numberChangedBounds); /* Hand the lot over to the CbcPartialNodeInfo constructor, then clean up and return. */ if (!strategy) nodeInfo_ = new CbcPartialNodeInfo(lastNode->nodeInfo_, this, numberChangedBounds, variables, boundChanges, basisDiff) ; else nodeInfo_ = strategy->partialNodeInfo(model, lastNode->nodeInfo_, this, numberChangedBounds, variables, boundChanges, basisDiff) ; delete basisDiff ; delete [] boundChanges; delete [] variables; delete expanded ; if (mustDeleteBasis) delete ws; } // Set node number nodeInfo_->setNodeNumber(model->getNodeCount2()); state_ |= 2; // say active } #else // CBC_NEW_CREATEINFO /* Original createInfo, with bare manipulation of basis vectors. Fails if solver maintains additional information in basis. */ void CbcNode::createInfo (CbcModel *model, CbcNode *lastNode, const CoinWarmStartBasis *lastws, const double *lastLower, const double *lastUpper, int numberOldActiveCuts, int numberNewCuts) { OsiSolverInterface * solver = model->solver(); CbcStrategy * strategy = model->strategy(); /* The root --- no parent. Create full basis and bounds information. */ if (!lastNode) { if (!strategy) nodeInfo_ = new CbcFullNodeInfo(model, solver->getNumRows()); else nodeInfo_ = strategy->fullNodeInfo(model, solver->getNumRows()); } /* Not the root. Create an edit from the parent's basis & bound information. This is not quite as straightforward as it seems. We need to reintroduce cuts we may have dropped out of the basis, in the correct position, because this whole process is strictly positional. Start by grabbing the current basis. */ else { bool mustDeleteBasis; const CoinWarmStartBasis* ws = dynamic_cast(solver->getPointerToWarmStart(mustDeleteBasis)); assert(ws != NULL); // make sure not volume //int numberArtificials = lastws->getNumArtificial(); int numberColumns = solver->getNumCols(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); int i; /* Create a clone and resize it to hold all the structural constraints, plus all the cuts: old cuts, both active and inactive (currentNumberCuts), and new cuts (numberNewCuts). TODO: You'd think that the set of constraints (logicals) in the expanded basis should match the set represented in lastws. At least, that's what I thought. But at the point I first looked hard at this bit of code, it turned out that lastws was the stripped basis produced at the end of addCuts(), rather than the raw basis handed back by addCuts1(). The expanded basis here is equivalent to the raw basis of addCuts1(). I said ``whoa, that's not good, I must have introduced a bug'' and went back to John's code to see where I'd gone wrong. And discovered the same `error' in his code. After a bit of thought, my conclusion is that correctness is not affected by whether lastws is the stripped or raw basis. The diffs have no semantics --- just a set of changes that need to be made to convert lastws into expanded. I think the only effect is that we store a lot more diffs (everything in expanded that's not covered by the stripped basis). But I need to give this more thought. There may well be some subtle error cases. In the mean time, I've twiddled addCuts() to set lastws to the raw basis. Makes me (Lou) less nervous to compare apples to apples. */ CoinWarmStartBasis *expanded = dynamic_cast(ws->clone()) ; int numberRowsAtContinuous = model->numberRowsAtContinuous(); int iFull = numberRowsAtContinuous + model->currentNumberCuts() + numberNewCuts; //int numberArtificialsNow = iFull; //int maxBasisLength = ((iFull+15)>>4)+((numberColumns+15)>>4); //printf("l %d full %d\n",maxBasisLength,iFull); if (expanded) expanded->resize(iFull, numberColumns); #ifdef CBC_CHECK_BASIS printf("Before expansion: orig %d, old %d, new %d, current %d\n", numberRowsAtContinuous, numberOldActiveCuts, numberNewCuts, model->currentNumberCuts()) ; ws->print(); #endif /* Now fill in the expanded basis. Any indices beyond nPartial must be cuts created while processing this node --- they can be copied directly into the expanded basis. From nPartial down, pull the status of active cuts from ws, interleaving with a B entry for the deactivated (loose) cuts. */ int numberDropped = model->currentNumberCuts() - numberOldActiveCuts; int iCompact = iFull - numberDropped; CbcCountRowCut ** cut = model->addedCuts(); int nPartial = model->currentNumberCuts() + numberRowsAtContinuous; iFull--; for (; iFull >= nPartial; iFull--) { CoinWarmStartBasis::Status status = ws->getArtifStatus(--iCompact); //assert (status != CoinWarmStartBasis::basic); // may be permanent cut expanded->setArtifStatus(iFull, status); } for (; iFull >= numberRowsAtContinuous; iFull--) { if (cut[iFull-numberRowsAtContinuous]) { CoinWarmStartBasis::Status status = ws->getArtifStatus(--iCompact); // If no cut generator being used then we may have basic variables //if (model->getMaximumCutPasses()&& // status == CoinWarmStartBasis::basic) //printf("cut basic\n"); expanded->setArtifStatus(iFull, status); } else { expanded->setArtifStatus(iFull, CoinWarmStartBasis::basic); } } #ifdef CBC_CHECK_BASIS printf("Expanded basis\n"); expanded->print() ; printf("Diffing against\n") ; lastws->print() ; #endif /* Now that we have two bases in proper positional correspondence, creating the actual diff is dead easy. */ CoinWarmStartDiff *basisDiff = expanded->generateDiff(lastws) ; /* Diff the bound vectors. It's assumed the number of structural variables is not changing. Assuming that branching objects all involve integer variables, we should see at least one bound change as a consequence of processing this subproblem. Different types of branching objects could break this assertion. Not true at all - we have not applied current branch - JJF. */ double *boundChanges = new double [2*numberColumns] ; int *variables = new int [2*numberColumns] ; int numberChangedBounds = 0; for (i = 0; i < numberColumns; i++) { if (lower[i] != lastLower[i]) { variables[numberChangedBounds] = i; boundChanges[numberChangedBounds++] = lower[i]; } if (upper[i] != lastUpper[i]) { variables[numberChangedBounds] = i | 0x80000000; boundChanges[numberChangedBounds++] = upper[i]; } #ifdef CBC_DEBUG if (lower[i] != lastLower[i]) printf("lower on %d changed from %g to %g\n", i, lastLower[i], lower[i]); if (upper[i] != lastUpper[i]) printf("upper on %d changed from %g to %g\n", i, lastUpper[i], upper[i]); #endif } #ifdef CBC_DEBUG printf("%d changed bounds\n", numberChangedBounds) ; #endif //if (lastNode->branchingObject()->boundBranch()) //assert (numberChangedBounds); /* Hand the lot over to the CbcPartialNodeInfo constructor, then clean up and return. */ if (!strategy) nodeInfo_ = new CbcPartialNodeInfo(lastNode->nodeInfo_, this, numberChangedBounds, variables, boundChanges, basisDiff) ; else nodeInfo_ = strategy->partialNodeInfo(model, lastNode->nodeInfo_, this, numberChangedBounds, variables, boundChanges, basisDiff) ; delete basisDiff ; delete [] boundChanges; delete [] variables; delete expanded ; if (mustDeleteBasis) delete ws; } // Set node number nodeInfo_->setNodeNumber(model->getNodeCount2()); state_ |= 2; // say active } #endif // CBC_NEW_CREATEINFO /* The routine scans through the object list of the model looking for objects that indicate infeasibility. It tests each object using strong branching and selects the one with the least objective degradation. A corresponding branching object is left attached to lastNode. If strong branching is disabled, a candidate object is chosen essentially at random (whatever object ends up in pos'n 0 of the candidate array). If a branching candidate is found to be monotone, bounds are set to fix the variable and the routine immediately returns (the caller is expected to reoptimize). If a branching candidate is found to result in infeasibility in both directions, the routine immediately returns an indication of infeasibility. Returns: 0 both branch directions are feasible -1 branching variable is monotone -2 infeasible Original comments: Here could go cuts etc etc For now just fix on objective from strong branching. */ int CbcNode::chooseBranch (CbcModel *model, CbcNode *lastNode, int numberPassesLeft) { if (lastNode) depth_ = lastNode->depth_ + 1; else depth_ = 0; delete branch_; branch_ = NULL; OsiSolverInterface * solver = model->solver(); # ifdef COIN_HAS_CLP OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver); int saveClpOptions = 0; if (osiclp) { // for faster hot start saveClpOptions = osiclp->specialOptions(); osiclp->setSpecialOptions(saveClpOptions | 8192); } # else OsiSolverInterface *osiclp = NULL ; # endif double saveObjectiveValue = solver->getObjValue(); double objectiveValue = CoinMax(solver->getObjSense() * saveObjectiveValue, objectiveValue_); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); // See what user thinks int anyAction = model->problemFeasibility()->feasible(model, 0); if (anyAction) { // will return -2 if infeasible , 0 if treat as integer return anyAction - 1; } double integerTolerance = model->getDblParam(CbcModel::CbcIntegerTolerance); // point to useful information OsiBranchingInformation usefulInfo = model->usefulInformation(); // and modify usefulInfo.depth_ = depth_; int i; bool beforeSolution = model->getSolutionCount() == 0; int numberStrong = model->numberStrong(); // switch off strong if hotstart const double * hotstartSolution = model->hotstartSolution(); const int * hotstartPriorities = model->hotstartPriorities(); int numberObjects = model->numberObjects(); int numberColumns = model->getNumCols(); double * saveUpper = new double[numberColumns]; double * saveLower = new double[numberColumns]; for (i = 0; i < numberColumns; i++) { saveLower[i] = lower[i]; saveUpper[i] = upper[i]; } // Save solution in case heuristics need good solution later double * saveSolution = new double[numberColumns]; memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double)); model->reserveCurrentSolution(saveSolution); if (hotstartSolution) { numberStrong = 0; if ((model->moreSpecialOptions()&1024) != 0) { int nBad = 0; int nUnsat = 0; int nDiff = 0; for (int i = 0; i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); const CbcSimpleInteger * thisOne = dynamic_cast (object); if (thisOne) { int iColumn = thisOne->columnNumber(); double targetValue = hotstartSolution[iColumn]; double value = saveSolution[iColumn]; if (fabs(value - floor(value + 0.5)) > 1.0e-6) { nUnsat++; #ifdef CLP_INVESTIGATE printf("H %d is %g target %g\n", iColumn, value, targetValue); #endif } else if (fabs(targetValue - value) > 1.0e-6) { nDiff++; } if (targetValue < saveLower[iColumn] || targetValue > saveUpper[iColumn]) { #ifdef CLP_INVESTIGATE printf("%d has target %g and current bounds %g and %g\n", iColumn, targetValue, saveLower[iColumn], saveUpper[iColumn]); #endif nBad++; } } } #ifdef CLP_INVESTIGATE printf("Hot %d unsatisfied, %d outside limits, %d different\n", nUnsat, nBad, nDiff); #endif if (nBad) { // switch off as not possible hotstartSolution = NULL; model->setHotstartSolution(NULL, NULL); usefulInfo.hotstartSolution_ = NULL; } } } int numberStrongDone = 0; int numberUnfinished = 0; int numberStrongInfeasible = 0; int numberStrongIterations = 0; int saveNumberStrong = numberStrong; bool checkFeasibility = numberObjects > model->numberIntegers(); int maximumStrong = CoinMax(CoinMin(numberStrong, numberObjects), 1); /* Get a branching decision object. Use the default decision criteria unless the user has loaded a decision method into the model. */ CbcBranchDecision *decision = model->branchingMethod(); CbcDynamicPseudoCostBranchingObject * dynamicBranchingObject = dynamic_cast(decision); if (!decision || dynamicBranchingObject) decision = new CbcBranchDefaultDecision(); decision->initialize(model); CbcStrongInfo * choice = new CbcStrongInfo[maximumStrong]; // May go round twice if strong branching fixes all local candidates bool finished = false; double estimatedDegradation = 0.0; while (!finished) { finished = true; // Some objects may compute an estimate of best solution from here estimatedDegradation = 0.0; //int numberIntegerInfeasibilities=0; // without odd ones numberStrongDone = 0; numberUnfinished = 0; numberStrongInfeasible = 0; numberStrongIterations = 0; // We may go round this loop twice (only if we think we have solution) for (int iPass = 0; iPass < 2; iPass++) { // compute current state //int numberObjectInfeasibilities; // just odd ones //model->feasibleSolution( // numberIntegerInfeasibilities, // numberObjectInfeasibilities); // Some objects may compute an estimate of best solution from here estimatedDegradation = 0.0; numberUnsatisfied_ = 0; // initialize sum of "infeasibilities" sumInfeasibilities_ = 0.0; int bestPriority = COIN_INT_MAX; /* Scan for branching objects that indicate infeasibility. Choose the best maximumStrong candidates, using priority as the first criteria, then integer infeasibility. The algorithm is to fill the choice array with a set of good candidates (by infeasibility) with priority bestPriority. Finding a candidate with priority better (less) than bestPriority flushes the choice array. (This serves as initialization when the first candidate is found.) A new candidate is added to choices only if its infeasibility exceeds the current max infeasibility (mostAway). When a candidate is added, it replaces the candidate with the smallest infeasibility (tracked by iSmallest). */ int iSmallest = 0; double mostAway = 1.0e-100; for (i = 0 ; i < maximumStrong ; i++) choice[i].possibleBranch = NULL ; numberStrong = 0; bool canDoOneHot = false; for (i = 0; i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); int preferredWay; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); int priorityLevel = object->priority(); if (hotstartSolution) { // we are doing hot start const CbcSimpleInteger * thisOne = dynamic_cast (object); if (thisOne) { int iColumn = thisOne->columnNumber(); bool canDoThisHot = true; double targetValue = hotstartSolution[iColumn]; if (saveUpper[iColumn] > saveLower[iColumn]) { double value = saveSolution[iColumn]; if (hotstartPriorities) priorityLevel = hotstartPriorities[iColumn]; //double originalLower = thisOne->originalLower(); //double originalUpper = thisOne->originalUpper(); // switch off if not possible if (targetValue >= saveLower[iColumn] && targetValue <= saveUpper[iColumn]) { /* priority outranks rest always if negative otherwise can be downgraded if at correct level. Infeasibility may be increased to choose 1.0 values first. choose one near wanted value */ if (fabs(value - targetValue) > integerTolerance) { //if (infeasibility>0.01) //infeasibility = fabs(1.0e6-fabs(value-targetValue)); //else infeasibility = fabs(value - targetValue); //if (targetValue==1.0) //infeasibility += 1.0; if (value > targetValue) { preferredWay = -1; } else { preferredWay = 1; } priorityLevel = CoinAbs(priorityLevel); } else if (priorityLevel < 0) { priorityLevel = CoinAbs(priorityLevel); if (targetValue == saveLower[iColumn]) { infeasibility = integerTolerance + 1.0e-12; preferredWay = -1; } else if (targetValue == saveUpper[iColumn]) { infeasibility = integerTolerance + 1.0e-12; preferredWay = 1; } else { // can't priorityLevel += 10000000; canDoThisHot = false; } } else { priorityLevel += 10000000; canDoThisHot = false; } } else { // switch off if not possible canDoThisHot = false; } if (canDoThisHot) canDoOneHot = true; } else if (targetValue < saveLower[iColumn] || targetValue > saveUpper[iColumn]) { } } else { priorityLevel += 10000000; } } if (infeasibility) { // Increase estimated degradation to solution estimatedDegradation += CoinMin(object->upEstimate(), object->downEstimate()); numberUnsatisfied_++; sumInfeasibilities_ += infeasibility; // Better priority? Flush choices. if (priorityLevel < bestPriority) { int j; iSmallest = 0; for (j = 0; j < maximumStrong; j++) { choice[j].upMovement = 0.0; delete choice[j].possibleBranch; choice[j].possibleBranch = NULL; } bestPriority = priorityLevel; mostAway = 1.0e-100; numberStrong = 0; } else if (priorityLevel > bestPriority) { continue; } // Check for suitability based on infeasibility. if (infeasibility > mostAway) { //add to list choice[iSmallest].upMovement = infeasibility; delete choice[iSmallest].possibleBranch; CbcObject * obj = dynamic_cast (object) ; assert (obj); choice[iSmallest].possibleBranch = obj->createCbcBranch(solver, &usefulInfo, preferredWay); numberStrong = CoinMax(numberStrong, iSmallest + 1); // Save which object it was choice[iSmallest].objectNumber = i; int j; iSmallest = -1; mostAway = 1.0e50; for (j = 0; j < maximumStrong; j++) { if (choice[j].upMovement < mostAway) { mostAway = choice[j].upMovement; iSmallest = j; } } } } } if (!canDoOneHot && hotstartSolution) { // switch off as not possible hotstartSolution = NULL; model->setHotstartSolution(NULL, NULL); usefulInfo.hotstartSolution_ = NULL; } if (numberUnsatisfied_) { // some infeasibilities - go to next steps #ifdef CLP_INVESTIGATE if (hotstartSolution) { int k = choice[0].objectNumber; OsiObject * object = model->modifiableObject(k); const CbcSimpleInteger * thisOne = dynamic_cast (object); assert (thisOne); int iColumn = thisOne->columnNumber(); double targetValue = hotstartSolution[iColumn]; double value = saveSolution[iColumn]; printf("Branch on %d has target %g (value %g) and current bounds %g and %g\n", iColumn, targetValue, value, saveLower[iColumn], saveUpper[iColumn]); } #endif break; } else if (!iPass) { // looks like a solution - get paranoid bool roundAgain = false; // get basis CoinWarmStartBasis * ws = dynamic_cast(solver->getWarmStart()); if (!ws) break; for (i = 0; i < numberColumns; i++) { double value = saveSolution[i]; if (value < lower[i]) { saveSolution[i] = lower[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound); } else if (value > upper[i]) { saveSolution[i] = upper[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound); } } if (roundAgain && saveNumberStrong) { // restore basis solver->setWarmStart(ws); delete ws; solver->resolve(); memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double)); model->reserveCurrentSolution(saveSolution); if (!solver->isProvenOptimal()) { // infeasible anyAction = -2; break; } } else { delete ws; break; } } } /* Some solvers can do the strong branching calculations faster if they do them all at once. At present only Clp does for ordinary integers but I think this coding would be easy to modify */ bool allNormal = true; // to say if we can do fast strong branching // Say which one will be best int bestChoice = 0; double worstInfeasibility = 0.0; for (i = 0; i < numberStrong; i++) { choice[i].numIntInfeasUp = numberUnsatisfied_; choice[i].numIntInfeasDown = numberUnsatisfied_; choice[i].fix = 0; // say not fixed if (!dynamic_cast (model->object(choice[i].objectNumber))) allNormal = false; // Something odd so lets skip clever fast branching if ( !model->object(choice[i].objectNumber)->boundBranch()) numberStrong = 0; // switch off if ( choice[i].possibleBranch->numberBranches() > 2) numberStrong = 0; // switch off // Do best choice in case switched off if (choice[i].upMovement > worstInfeasibility) { worstInfeasibility = choice[i].upMovement; bestChoice = i; } } // If we have hit max time don't do strong branching bool hitMaxTime = (model->getCurrentSeconds() > model->getDblParam(CbcModel::CbcMaximumSeconds)); // also give up if we are looping round too much if (hitMaxTime || numberPassesLeft <= 0) numberStrong = 0; /* Is strong branching enabled? If so, set up and do it. Otherwise, we'll fall through to simple branching. Setup for strong branching involves saving the current basis (for restoration afterwards) and setting up for hot starts. */ if (numberStrong && saveNumberStrong) { bool solveAll = false; // set true to say look at all even if some fixed (experiment) solveAll = true; // worth trying if too many times // Save basis CoinWarmStart * ws = solver->getWarmStart(); // save limit int saveLimit; solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit); if (beforeSolution && saveLimit < 100) solver->setIntParam(OsiMaxNumIterationHotStart, 100); // go to end # ifdef COIN_HAS_CLP /* If we are doing all strong branching in one go then we create new arrays to store information. If clp NULL then doing old way. Going down - outputSolution[2*i] is final solution. outputStuff[2*i] is status (0 - finished, 1 infeas, other unknown outputStuff[2*i+numberStrong] is number iterations On entry newUpper[i] is new upper bound, on exit obj change Going up - outputSolution[2*i+1] is final solution. outputStuff[2*i+1] is status (0 - finished, 1 infeas, other unknown outputStuff[2*i+1+numberStrong] is number iterations On entry newLower[i] is new lower bound, on exit obj change */ ClpSimplex * clp = NULL; double * newLower = NULL; double * newUpper = NULL; double ** outputSolution = NULL; int * outputStuff = NULL; // Go back to normal way if user wants it if (osiclp && (osiclp->specialOptions()&16) != 0 && osiclp->specialOptions() > 0) allNormal = false; if (osiclp && !allNormal) { // say do fast int easy = 1; osiclp->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ; } if (osiclp && allNormal) { clp = osiclp->getModelPtr(); // Clp - do a different way newLower = new double[numberStrong]; newUpper = new double[numberStrong]; outputSolution = new double * [2*numberStrong]; outputStuff = new int [4*numberStrong]; int * which = new int[numberStrong]; int startFinishOptions; int specialOptions = osiclp->specialOptions(); int clpOptions = clp->specialOptions(); int returnCode = 0; #define CRUNCH #ifdef CRUNCH // Crunch down problem int numberRows = clp->numberRows(); // Use dual region double * rhs = clp->dualRowSolution(); int * whichRow = new int[3*numberRows]; int * whichColumn = new int[2*numberColumns]; int nBound; ClpSimplex * small = static_cast (clp)->crunch(rhs, whichRow, whichColumn, nBound, true); if (!small) { anyAction = -2; //printf("XXXX Inf by inspection\n"); delete [] whichColumn; whichColumn = NULL; delete [] whichRow; whichRow = NULL; break; } else { clp = small; } #else int saveLogLevel = clp->logLevel(); int saveMaxIts = clp->maximumIterations(); #endif clp->setLogLevel(0); if ((specialOptions&1) == 0) { startFinishOptions = 0; clp->setSpecialOptions(clpOptions | (64 | 1024)); } else { startFinishOptions = 1 + 2 + 4; //startFinishOptions=1+4; // for moment re-factorize if ((specialOptions&4) == 0) clp->setSpecialOptions(clpOptions | (64 | 128 | 512 | 1024 | 4096)); else clp->setSpecialOptions(clpOptions | (64 | 128 | 512 | 1024 | 2048 | 4096)); } // User may want to clean up before strong branching if ((clp->specialOptions()&32) != 0) { clp->primal(1); if (clp->numberIterations()) model->messageHandler()->message(CBC_ITERATE_STRONG, *model->messagesPointer()) << clp->numberIterations() << CoinMessageEol; } clp->setMaximumIterations(saveLimit); #ifdef CRUNCH int * backColumn = whichColumn + numberColumns; #endif for (i = 0; i < numberStrong; i++) { int iObject = choice[i].objectNumber; const OsiObject * object = model->object(iObject); const CbcSimpleInteger * simple = static_cast (object); int iSequence = simple->columnNumber(); newLower[i] = ceil(saveSolution[iSequence]); newUpper[i] = floor(saveSolution[iSequence]); #ifdef CRUNCH iSequence = backColumn[iSequence]; assert (iSequence >= 0); #endif which[i] = iSequence; outputSolution[2*i] = new double [numberColumns]; outputSolution[2*i+1] = new double [numberColumns]; } //clp->writeMps("bad"); returnCode = clp->strongBranching(numberStrong, which, newLower, newUpper, outputSolution, outputStuff, outputStuff + 2 * numberStrong, !solveAll, false, startFinishOptions); #ifndef CRUNCH clp->setSpecialOptions(clpOptions); // restore clp->setMaximumIterations(saveMaxIts); clp->setLogLevel(saveLogLevel); #endif if (returnCode == -2) { // bad factorization!!! // Doing normal way // Mark hot start solver->markHotStart(); clp = NULL; } else { #ifdef CRUNCH // extract solution //bool checkSol=true; for (i = 0; i < numberStrong; i++) { int iObject = choice[i].objectNumber; const OsiObject * object = model->object(iObject); const CbcSimpleInteger * simple = static_cast (object); int iSequence = simple->columnNumber(); which[i] = iSequence; double * sol = outputSolution[2*i]; double * sol2 = outputSolution[2*i+1]; //bool x=true; //bool x2=true; for (int iColumn = numberColumns - 1; iColumn >= 0; iColumn--) { int jColumn = backColumn[iColumn]; if (jColumn >= 0) { sol[iColumn] = sol[jColumn]; sol2[iColumn] = sol2[jColumn]; } else { sol[iColumn] = saveSolution[iColumn]; sol2[iColumn] = saveSolution[iColumn]; } } } #endif } #ifdef CRUNCH delete [] whichColumn; delete [] whichRow; delete small; #endif delete [] which; } else { // Doing normal way // Mark hot start solver->markHotStart(); } # else /* COIN_HAS_CLP */ OsiSolverInterface *clp = NULL ; double **outputSolution = NULL ; int *outputStuff = NULL ; double * newLower = NULL ; double * newUpper = NULL ; solver->markHotStart(); # endif /* COIN_HAS_CLP */ /* Open a loop to do the strong branching LPs. For each candidate variable, solve an LP with the variable forced down, then up. If a direction turns out to be infeasible or monotonic (i.e., over the dual objective cutoff), force the objective change to be big (1.0e100). If we determine the problem is infeasible, or find a monotone variable, escape the loop. TODO: The `restore bounds' part might be better encapsulated as an unbranch() method. Branching objects more exotic than simple integers or cliques might not restrict themselves to variable bounds. TODO: Virtuous solvers invalidate the current solution (or give bogus results :-) when the bounds are changed out from under them. So we need to do all the work associated with finding a new solution before restoring the bounds. */ for (i = 0 ; i < numberStrong ; i++) { double objectiveChange ; double newObjectiveValue = 1.0e100; // status is 0 finished, 1 infeasible and other int iStatus; /* Try the down direction first. (Specify the initial branching alternative as down with a call to way(-1). Each subsequent call to branch() performs the specified branch and advances the branch object state to the next branch alternative.) */ if (!clp) { choice[i].possibleBranch->way(-1) ; choice[i].possibleBranch->branch() ; bool feasible = true; if (checkFeasibility) { // check branching did not make infeasible int iColumn; int numberColumns = solver->getNumCols(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLower[iColumn] > columnUpper[iColumn] + 1.0e-5) feasible = false; } } if (feasible) { solver->solveFromHotStart() ; numberStrongDone++; numberStrongIterations += solver->getIterationCount(); /* We now have an estimate of objective degradation that we can use for strong branching. If we're over the cutoff, the variable is monotone up. If we actually made it to optimality, check for a solution, and if we have a good one, call setBestSolution to process it. Note that this may reduce the cutoff, so we check again to see if we can declare this variable monotone. */ if (solver->isProvenOptimal()) iStatus = 0; // optimal else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) iStatus = 2; // unknown else iStatus = 1; // infeasible newObjectiveValue = solver->getObjSense() * solver->getObjValue(); choice[i].numItersDown = solver->getIterationCount(); } else { iStatus = 1; // infeasible newObjectiveValue = 1.0e100; choice[i].numItersDown = 0; } } else { iStatus = outputStuff[2*i]; choice[i].numItersDown = outputStuff[2*numberStrong+2*i]; numberStrongDone++; numberStrongIterations += choice[i].numItersDown; newObjectiveValue = objectiveValue + newUpper[i]; solver->setColSolution(outputSolution[2*i]); } objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0); if (!iStatus) { choice[i].finishedDown = true ; if (newObjectiveValue >= model->getCutoff()) { objectiveChange = 1.0e100; // say infeasible numberStrongInfeasible++; } else { // See if integer solution if (model->feasibleSolution(choice[i].numIntInfeasDown, choice[i].numObjInfeasDown) && model->problemFeasibility()->feasible(model, -1) >= 0) { model->setBestSolution(CBC_STRONGSOL, newObjectiveValue, solver->getColSolution()) ; // only needed for odd solvers newObjectiveValue = solver->getObjSense() * solver->getObjValue(); objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0) ; model->setLastHeuristic(NULL); model->incrementUsed(solver->getColSolution()); if (newObjectiveValue >= model->getCutoff()) { // *new* cutoff objectiveChange = 1.0e100 ; numberStrongInfeasible++; } } } } else if (iStatus == 1) { objectiveChange = 1.0e100 ; numberStrongInfeasible++; } else { // Can't say much as we did not finish choice[i].finishedDown = false ; numberUnfinished++; } choice[i].downMovement = objectiveChange ; // restore bounds if (!clp) { for (int j = 0; j < numberColumns; j++) { if (saveLower[j] != lower[j]) solver->setColLower(j, saveLower[j]); if (saveUpper[j] != upper[j]) solver->setColUpper(j, saveUpper[j]); } } //printf("Down on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n", // choice[i].objectNumber,iStatus,newObjectiveValue,choice[i].numItersDown, // choice[i].downMovement,choice[i].finishedDown,choice[i].numIntInfeasDown, // choice[i].numObjInfeasDown); // repeat the whole exercise, forcing the variable up if (!clp) { bool feasible = true; // If odd branching then maybe just one possibility if (choice[i].possibleBranch->numberBranchesLeft() > 0) { choice[i].possibleBranch->branch(); if (checkFeasibility) { // check branching did not make infeasible int iColumn; int numberColumns = solver->getNumCols(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLower[iColumn] > columnUpper[iColumn] + 1.0e-5) feasible = false; } } } else { // second branch infeasible feasible = false; } if (feasible) { solver->solveFromHotStart() ; numberStrongDone++; numberStrongIterations += solver->getIterationCount(); /* We now have an estimate of objective degradation that we can use for strong branching. If we're over the cutoff, the variable is monotone up. If we actually made it to optimality, check for a solution, and if we have a good one, call setBestSolution to process it. Note that this may reduce the cutoff, so we check again to see if we can declare this variable monotone. */ if (solver->isProvenOptimal()) iStatus = 0; // optimal else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) iStatus = 2; // unknown else iStatus = 1; // infeasible newObjectiveValue = solver->getObjSense() * solver->getObjValue(); choice[i].numItersUp = solver->getIterationCount(); } else { iStatus = 1; // infeasible newObjectiveValue = 1.0e100; choice[i].numItersDown = 0; } } else { iStatus = outputStuff[2*i+1]; choice[i].numItersUp = outputStuff[2*numberStrong+2*i+1]; numberStrongDone++; numberStrongIterations += choice[i].numItersUp; newObjectiveValue = objectiveValue + newLower[i]; solver->setColSolution(outputSolution[2*i+1]); } objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0); if (!iStatus) { choice[i].finishedUp = true ; if (newObjectiveValue >= model->getCutoff()) { objectiveChange = 1.0e100; // say infeasible numberStrongInfeasible++; } else { // See if integer solution if (model->feasibleSolution(choice[i].numIntInfeasUp, choice[i].numObjInfeasUp) && model->problemFeasibility()->feasible(model, -1) >= 0) { model->setBestSolution(CBC_STRONGSOL, newObjectiveValue, solver->getColSolution()) ; // only needed for odd solvers newObjectiveValue = solver->getObjSense() * solver->getObjValue(); objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0) ; model->setLastHeuristic(NULL); model->incrementUsed(solver->getColSolution()); if (newObjectiveValue >= model->getCutoff()) { // *new* cutoff objectiveChange = 1.0e100 ; numberStrongInfeasible++; } } } } else if (iStatus == 1) { objectiveChange = 1.0e100 ; numberStrongInfeasible++; } else { // Can't say much as we did not finish choice[i].finishedUp = false ; numberUnfinished++; } choice[i].upMovement = objectiveChange ; // restore bounds if (!clp) { for (int j = 0; j < numberColumns; j++) { if (saveLower[j] != lower[j]) solver->setColLower(j, saveLower[j]); if (saveUpper[j] != upper[j]) solver->setColUpper(j, saveUpper[j]); } } //printf("Up on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n", // choice[i].objectNumber,iStatus,newObjectiveValue,choice[i].numItersUp, // choice[i].upMovement,choice[i].finishedUp,choice[i].numIntInfeasUp, // choice[i].numObjInfeasUp); /* End of evaluation for this candidate variable. Possibilities are: * Both sides below cutoff; this variable is a candidate for branching. * Both sides infeasible or above the objective cutoff: no further action here. Break from the evaluation loop and assume the node will be purged by the caller. * One side below cutoff: Install the branch (i.e., fix the variable). Break from the evaluation loop and assume the node will be reoptimised by the caller. */ // reset choice[i].possibleBranch->resetNumberBranchesLeft(); if (choice[i].upMovement < 1.0e100) { if (choice[i].downMovement < 1.0e100) { // feasible - no action } else { // up feasible, down infeasible anyAction = -1; //printf("Down infeasible for choice %d sequence %d\n",i, // model->object(choice[i].objectNumber)->columnNumber()); if (!solveAll) { choice[i].possibleBranch->way(1); choice[i].possibleBranch->branch(); break; } else { choice[i].fix = 1; } } } else { if (choice[i].downMovement < 1.0e100) { // down feasible, up infeasible anyAction = -1; //printf("Up infeasible for choice %d sequence %d\n",i, // model->object(choice[i].objectNumber)->columnNumber()); if (!solveAll) { choice[i].possibleBranch->way(-1); choice[i].possibleBranch->branch(); break; } else { choice[i].fix = -1; } } else { // neither side feasible anyAction = -2; //printf("Both infeasible for choice %d sequence %d\n",i, // model->object(choice[i].objectNumber)->columnNumber()); break; } } bool hitMaxTime = (model->getCurrentSeconds() > model->getDblParam(CbcModel::CbcMaximumSeconds)); if (hitMaxTime) { numberStrong = i + 1; break; } } if (!clp) { // Delete the snapshot solver->unmarkHotStart(); } else { delete [] newLower; delete [] newUpper; delete [] outputStuff; int i; for (i = 0; i < 2*numberStrong; i++) delete [] outputSolution[i]; delete [] outputSolution; } solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit); // restore basis solver->setWarmStart(ws); // Unless infeasible we will carry on // But we could fix anyway if (anyAction == -1 && solveAll) { // apply and take off for (i = 0 ; i < numberStrong ; i++) { if (choice[i].fix) { choice[i].possibleBranch->way(choice[i].fix) ; choice[i].possibleBranch->branch() ; } } bool feasible = true; if (checkFeasibility) { // check branching did not make infeasible int iColumn; int numberColumns = solver->getNumCols(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLower[iColumn] > columnUpper[iColumn] + 1.0e-5) feasible = false; } } if (feasible) { // can do quick optimality check int easy = 2; solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ; solver->resolve() ; solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; feasible = solver->isProvenOptimal(); } if (feasible) { memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double)); model->reserveCurrentSolution(saveSolution); memcpy(saveLower, solver->getColLower(), numberColumns*sizeof(double)); memcpy(saveUpper, solver->getColUpper(), numberColumns*sizeof(double)); // Clean up all candidates whih are fixed int numberLeft = 0; for (i = 0 ; i < numberStrong ; i++) { CbcStrongInfo thisChoice = choice[i]; choice[i].possibleBranch = NULL; const OsiObject * object = model->object(thisChoice.objectNumber); int preferredWay; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); if (!infeasibility) { // take out delete thisChoice.possibleBranch; } else { choice[numberLeft++] = thisChoice; } } numberStrong = numberLeft; for (; i < maximumStrong; i++) { delete choice[i].possibleBranch; choice[i].possibleBranch = NULL; } // If all fixed then round again if (!numberLeft) { finished = false; numberStrong = 0; saveNumberStrong = 0; maximumStrong = 1; } else { anyAction = 0; } // If these two uncommented then different action anyAction = -1; finished = true; //printf("some fixed but continuing %d left\n",numberLeft); } else { anyAction = -2; // say infeasible } } delete ws; //int numberNodes = model->getNodeCount(); // update number of strong iterations etc model->incrementStrongInfo(numberStrongDone, numberStrongIterations, anyAction == -2 ? 0 : numberStrongInfeasible, anyAction == -2); /* anyAction >= 0 indicates that strong branching didn't produce any monotone variables. Sift through the candidates for the best one. QUERY: Setting numberNodes looks to be a distributed noop. numberNodes is local to this code block. Perhaps should be numberNodes_ from model? Unclear what this calculation is doing. */ if (anyAction >= 0) { // get average cost per iteration and assume stopped ones // would stop after 50% more iterations at average cost??? !!! ??? double averageCostPerIteration = 0.0; double totalNumberIterations = 1.0; int smallestNumberInfeasibilities = COIN_INT_MAX; for (i = 0; i < numberStrong; i++) { totalNumberIterations += choice[i].numItersDown + choice[i].numItersUp ; averageCostPerIteration += choice[i].downMovement + choice[i].upMovement; smallestNumberInfeasibilities = CoinMin(CoinMin(choice[i].numIntInfeasDown , choice[i].numIntInfeasUp ), smallestNumberInfeasibilities); } //if (smallestNumberInfeasibilities>=numberIntegerInfeasibilities) //numberNodes=1000000; // switch off search for better solution averageCostPerIteration /= totalNumberIterations; // all feasible - choose best bet // New method does all at once so it can be more sophisticated // in deciding how to balance actions. // But it does need arrays double * changeUp = new double [numberStrong]; int * numberInfeasibilitiesUp = new int [numberStrong]; double * changeDown = new double [numberStrong]; int * numberInfeasibilitiesDown = new int [numberStrong]; CbcBranchingObject ** objects = new CbcBranchingObject * [ numberStrong]; for (i = 0 ; i < numberStrong ; i++) { int iColumn = choice[i].possibleBranch->variable() ; model->messageHandler()->message(CBC_STRONG, *model->messagesPointer()) << i << iColumn << choice[i].downMovement << choice[i].numIntInfeasDown << choice[i].upMovement << choice[i].numIntInfeasUp << choice[i].possibleBranch->value() << CoinMessageEol; changeUp[i] = choice[i].upMovement; numberInfeasibilitiesUp[i] = choice[i].numIntInfeasUp; changeDown[i] = choice[i].downMovement; numberInfeasibilitiesDown[i] = choice[i].numIntInfeasDown; objects[i] = choice[i].possibleBranch; } int whichObject = decision->bestBranch(objects, numberStrong, numberUnsatisfied_, changeUp, numberInfeasibilitiesUp, changeDown, numberInfeasibilitiesDown, objectiveValue_); // move branching object and make sure it will not be deleted if (whichObject >= 0) { branch_ = objects[whichObject]; if (model->messageHandler()->logLevel() > 3) printf("Choosing column %d\n", choice[whichObject].possibleBranch->variable()) ; choice[whichObject].possibleBranch = NULL; } delete [] changeUp; delete [] numberInfeasibilitiesUp; delete [] changeDown; delete [] numberInfeasibilitiesDown; delete [] objects; } # ifdef COIN_HAS_CLP if (osiclp && !allNormal) { // back to normal osiclp->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; } # endif } /* Simple branching. Probably just one, but we may have got here because of an odd branch e.g. a cut */ else { // not strong // C) create branching object branch_ = choice[bestChoice].possibleBranch; choice[bestChoice].possibleBranch = NULL; } } // Set guessed solution value guessedObjectiveValue_ = objectiveValue_ + estimatedDegradation; /* Cleanup, then we're outta here. */ if (!model->branchingMethod() || dynamicBranchingObject) delete decision; for (i = 0; i < maximumStrong; i++) delete choice[i].possibleBranch; delete [] choice; delete [] saveLower; delete [] saveUpper; // restore solution solver->setColSolution(saveSolution); delete [] saveSolution; # ifdef COIN_HAS_CLP if (osiclp) osiclp->setSpecialOptions(saveClpOptions); # endif return anyAction; } /* Version for dynamic pseudo costs. **** For now just return if anything odd later allow even if odd The routine scans through the object list of the model looking for objects that indicate infeasibility. It tests each object using strong branching and selects the one with the least objective degradation. A corresponding branching object is left attached to lastNode. This version gives preference in evaluation to variables which have not been evaluated many times. It also uses numberStrong to say give up if last few tries have not changed incumbent. See Achterberg, Koch and Martin. If strong branching is disabled, a candidate object is chosen essentially at random (whatever object ends up in pos'n 0 of the candidate array). If a branching candidate is found to be monotone, bounds are set to fix the variable and the routine immediately returns (the caller is expected to reoptimize). If a branching candidate is found to result in infeasibility in both directions, the routine immediately returns an indication of infeasibility. Returns: 0 both branch directions are feasible -1 branching variable is monotone -2 infeasible -3 Use another method For now just fix on objective from strong branching. */ int CbcNode::chooseDynamicBranch (CbcModel *model, CbcNode *lastNode, OsiSolverBranch * & /*branches*/, int numberPassesLeft) { if (lastNode) depth_ = lastNode->depth_ + 1; else depth_ = 0; // Go to other choose if hot start if (model->hotstartSolution() && (((model->moreSpecialOptions()&1024) == 0) || false)) return -3; delete branch_; branch_ = NULL; OsiSolverInterface * solver = model->solver(); // get information on solver type const OsiAuxInfo * auxInfo = solver->getAuxiliaryInfo(); const OsiBabSolver * auxiliaryInfo = dynamic_cast (auxInfo); if (!auxiliaryInfo) { // use one from CbcModel auxiliaryInfo = model->solverCharacteristics(); } int numberObjects = model->numberObjects(); // If very odd set of objects then use older chooseBranch bool useOldWay = false; // point to useful information OsiBranchingInformation usefulInfo = model->usefulInformation(); if (numberObjects > model->numberIntegers()) { for (int i = model->numberIntegers(); i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); CbcObject * obj = dynamic_cast (object) ; if (!obj || !obj->optionalObject()) { int preferredWay; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); if (infeasibility) { useOldWay = true; break; } } else { obj->initializeForBranching(model); } } } if ((model->specialOptions()&128) != 0) useOldWay = false; // allow // For now return if not simple if (useOldWay) return -3; // Modify useful info usefulInfo.depth_ = depth_; if ((model->specialOptions()&128) != 0) { // SOS - shadow prices int numberRows = solver->getNumRows(); const double * pi = usefulInfo.pi_; double sumPi = 0.0; for (int i = 0; i < numberRows; i++) sumPi += fabs(pi[i]); sumPi /= static_cast (numberRows); // and scale back sumPi *= 0.01; usefulInfo.defaultDual_ = sumPi; // switch on int numberColumns = solver->getNumCols(); int size = CoinMax(numberColumns, 2 * numberRows); usefulInfo.usefulRegion_ = new double [size]; CoinZeroN(usefulInfo.usefulRegion_, size); usefulInfo.indexRegion_ = new int [size]; // pi may change usefulInfo.pi_ = CoinCopyOfArray(usefulInfo.pi_, numberRows); } assert (auxiliaryInfo); double cutoff = model->getCutoff(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); // See if user thinks infeasible int anyAction = model->problemFeasibility()->feasible(model, 0); if (anyAction) { // will return -2 if infeasible , 0 if treat as integer return anyAction - 1; } int i; int saveStateOfSearch = model->stateOfSearch() % 10; int numberStrong = model->numberStrong(); /* Ranging is switched off. The idea is that you can find out the effect of one iteration on each unsatisfied variable cheaply. Then use this if you have not got much else to go on. */ //#define RANGING #ifdef RANGING // must have clp #ifndef COIN_HAS_CLP # warning("Ranging switched off as not Clp"); #undef RANGING #endif // Pass number int kPass = 0; int numberRows = solver->getNumRows(); #endif int numberColumns = model->getNumCols(); double * saveUpper = new double[numberColumns]; double * saveLower = new double[numberColumns]; for (i = 0; i < numberColumns; i++) { saveLower[i] = lower[i]; saveUpper[i] = upper[i]; } // Save solution in case heuristics need good solution later double * saveSolution = new double[numberColumns]; memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double)); model->reserveCurrentSolution(saveSolution); const double * hotstartSolution = model->hotstartSolution(); const int * hotstartPriorities = model->hotstartPriorities(); double integerTolerance = model->getDblParam(CbcModel::CbcIntegerTolerance); if (hotstartSolution) { if ((model->moreSpecialOptions()&1024) != 0) { int nBad = 0; int nUnsat = 0; int nDiff = 0; for (int i = 0; i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); const CbcSimpleInteger * thisOne = dynamic_cast (object); if (thisOne) { int iColumn = thisOne->columnNumber(); double targetValue = hotstartSolution[iColumn]; double value = saveSolution[iColumn]; if (fabs(value - floor(value + 0.5)) > 1.0e-6) { nUnsat++; #ifdef CLP_INVESTIGATE printf("H %d is %g target %g\n", iColumn, value, targetValue); #endif } else if (fabs(targetValue - value) > 1.0e-6) { nDiff++; } if (targetValue < saveLower[iColumn] || targetValue > saveUpper[iColumn]) { #ifdef CLP_INVESTIGATE printf("%d has target %g and current bounds %g and %g\n", iColumn, targetValue, saveLower[iColumn], saveUpper[iColumn]); #endif nBad++; } } } #ifdef CLP_INVESTIGATE printf("Hot %d unsatisfied, %d outside limits, %d different\n", nUnsat, nBad, nDiff); #endif if (nBad) { // switch off as not possible hotstartSolution = NULL; model->setHotstartSolution(NULL, NULL); usefulInfo.hotstartSolution_ = NULL; } } } /* Get a branching decision object. Use the default dynamic decision criteria unless the user has loaded a decision method into the model. */ CbcBranchDecision *decision = model->branchingMethod(); if (!decision) decision = new CbcBranchDynamicDecision(); int xMark = 0; // Get arrays to sort double * sort = new double[numberObjects]; int * whichObject = new int[numberObjects]; #ifdef RANGING int xPen = 0; int * objectMark = new int[2*numberObjects+1]; #endif // Arrays with movements double * upEstimate = new double[numberObjects]; double * downEstimate = new double[numberObjects]; double estimatedDegradation = 0.0; int numberNodes = model->getNodeCount(); int saveLogLevel = model->logLevel(); #ifdef JJF_ZERO if ((numberNodes % 500) == 0) { model->setLogLevel(6); // Get average up and down costs double averageUp = 0.0; double averageDown = 0.0; int numberUp = 0; int numberDown = 0; int i; for ( i = 0; i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; assert(dynamicObject); int numberUp2 = 0; int numberDown2 = 0; double up = 0.0; double down = 0.0; if (dynamicObject->numberTimesUp()) { numberUp++; averageUp += dynamicObject->upDynamicPseudoCost(); numberUp2 += dynamicObject->numberTimesUp(); up = dynamicObject->upDynamicPseudoCost(); } if (dynamicObject->numberTimesDown()) { numberDown++; averageDown += dynamicObject->downDynamicPseudoCost(); numberDown2 += dynamicObject->numberTimesDown(); down = dynamicObject->downDynamicPseudoCost(); } if (numberUp2 || numberDown2) printf("col %d - up %d times cost %g, - down %d times cost %g\n", dynamicObject->columnNumber(), numberUp2, up, numberDown2, down); } if (numberUp) averageUp /= static_cast (numberUp); else averageUp = 1.0; if (numberDown) averageDown /= static_cast (numberDown); else averageDown = 1.0; printf("total - up %d vars average %g, - down %d vars average %g\n", numberUp, averageUp, numberDown, averageDown); } #endif int numberBeforeTrust = model->numberBeforeTrust(); // May go round twice if strong branching fixes all local candidates bool finished = false; int numberToFix = 0; # ifdef COIN_HAS_CLP OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver); int saveClpOptions = 0; if (osiclp) { // for faster hot start saveClpOptions = osiclp->specialOptions(); osiclp->setSpecialOptions(saveClpOptions | 8192); } # else OsiSolverInterface *osiclp = NULL ; # endif //const CglTreeProbingInfo * probingInfo = NULL; //model->probingInfo(); // Old code left in with DEPRECATED_STRATEGY assert (model->searchStrategy() == -1 || model->searchStrategy() == 1 || model->searchStrategy() == 2); #ifdef DEPRECATED_STRATEGY int saveSearchStrategy2 = model->searchStrategy(); #endif // Get average up and down costs { double averageUp = 0.0; double averageDown = 0.0; int numberUp = 0; int numberDown = 0; int i; for ( i = 0; i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; if (dynamicObject) { if (dynamicObject->numberTimesUp()) { numberUp++; averageUp += dynamicObject->upDynamicPseudoCost(); } if (dynamicObject->numberTimesDown()) { numberDown++; averageDown += dynamicObject->downDynamicPseudoCost(); } } } if (numberUp) averageUp /= static_cast (numberUp); else averageUp = 1.0; if (numberDown) averageDown /= static_cast (numberDown); else averageDown = 1.0; for ( i = 0; i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; if (dynamicObject) { if (!dynamicObject->numberTimesUp()) dynamicObject->setUpDynamicPseudoCost(averageUp); if (!dynamicObject->numberTimesDown()) dynamicObject->setDownDynamicPseudoCost(averageDown); } } } /* 1 strong 2 no strong 3 strong just before solution 4 no strong just before solution 5 strong first time or before solution 6 strong first time */ int useShadow = model->moreSpecialOptions() & 7; if (useShadow > 2) { if (model->getSolutionCount()) { if (numberNodes || useShadow < 5) { useShadow = 0; // zap pseudo shadow prices model->pseudoShadow(-1); // and switch off model->setMoreSpecialOptions(model->moreSpecialOptions()&(~1023)); } else { useShadow = 1; } } else if (useShadow < 5) { useShadow -= 2; } else { useShadow = 1; } } if (useShadow) { // pseudo shadow prices model->pseudoShadow((model->moreSpecialOptions() >> 3)&63); } #ifdef DEPRECATED_STRATEGY { // in for tabbing } else if (saveSearchStrategy2 < 1999) { // pseudo shadow prices model->pseudoShadow(NULL, NULL); } else if (saveSearchStrategy2 < 2999) { // leave old ones } else if (saveSearchStrategy2 < 3999) { // pseudo shadow prices at root if (!numberNodes) model->pseudoShadow(NULL, NULL); } else { abort(); } if (saveSearchStrategy2 >= 0) saveSearchStrategy2 = saveSearchStrategy2 % 1000; if (saveSearchStrategy2 == 999) saveSearchStrategy2 = -1; int saveSearchStrategy = saveSearchStrategy2 < 99 ? saveSearchStrategy2 : saveSearchStrategy2 - 100; #endif //DEPRECATED_STRATEGY int numberNotTrusted = 0; int numberStrongDone = 0; int numberUnfinished = 0; int numberStrongInfeasible = 0; int numberStrongIterations = 0; int strongType=0; #define DO_ALL_AT_ROOT #ifdef DO_ALL_AT_ROOT int saveSatisfiedVariables=0; int saveNumberToDo=0; #endif // so we can save lots of stuff CbcStrongInfo choice; CbcDynamicPseudoCostBranchingObject * choiceObject = NULL; if (model->allDynamic()) { CbcSimpleIntegerDynamicPseudoCost * object = NULL; choiceObject = new CbcDynamicPseudoCostBranchingObject(model, 0, -1, 0.5, object); } choice.possibleBranch = choiceObject; numberPassesLeft = CoinMax(numberPassesLeft, 2); //#define DEBUG_SOLUTION #ifdef DEBUG_SOLUTION bool onOptimalPath=false; if ((model->specialOptions()&1) != 0) { const OsiRowCutDebugger *debugger = model->continuousSolver()->getRowCutDebugger() ; if (debugger) { const OsiRowCutDebugger *debugger2 = model->solver()->getRowCutDebugger() ; printf("On optimal in CbcNode %s\n",debugger2 ? "" : "but bad cuts"); onOptimalPath=true; } } #endif while (!finished) { numberPassesLeft--; finished = true; decision->initialize(model); // Some objects may compute an estimate of best solution from here estimatedDegradation = 0.0; numberToFix = 0; int numberToDo = 0; int iBestNot = -1; int iBestGot = -1; double best = 0.0; numberNotTrusted = 0; numberStrongDone = 0; numberUnfinished = 0; numberStrongInfeasible = 0; numberStrongIterations = 0; #ifdef RANGING int * which = objectMark + numberObjects + 1; int neededPenalties; int optionalPenalties; #endif // We may go round this loop three times (only if we think we have solution) for (int iPass = 0; iPass < 3; iPass++) { // Some objects may compute an estimate of best solution from here estimatedDegradation = 0.0; numberUnsatisfied_ = 0; // initialize sum of "infeasibilities" sumInfeasibilities_ = 0.0; int bestPriority = COIN_INT_MAX; #ifdef JJF_ZERO int number01 = 0; const cliqueEntry * entry = NULL; const int * toZero = NULL; const int * toOne = NULL; const int * backward = NULL; int numberUnsatisProbed = 0; int numberUnsatisNotProbed = 0; // 0-1 if (probingInfo) { number01 = probingInfo->numberIntegers(); entry = probingInfo->fixEntries(); toZero = probingInfo->toZero(); toOne = probingInfo->toOne(); backward = probingInfo->backward(); if (!toZero[number01] || number01 < numberObjects || true) { // no info probingInfo = NULL; } } #endif /* Scan for branching objects that indicate infeasibility. Choose candidates using priority as the first criteria, then integer infeasibility. The algorithm is to fill the array with a set of good candidates (by infeasibility) with priority bestPriority. Finding a candidate with priority better (less) than bestPriority flushes the choice array. (This serves as initialization when the first candidate is found.) */ numberToDo = 0; #ifdef RANGING neededPenalties = 0; optionalPenalties = numberObjects; #endif iBestNot = -1; double bestNot = 0.0; iBestGot = -1; best = 0.0; /* Problem type as set by user or found by analysis. This will be extended 0 - not known 1 - Set partitioning <= 2 - Set partitioning == 3 - Set covering 4 - all +- 1 or all +1 and odd */ int problemType = model->problemType(); bool canDoOneHot = false; for (i = 0; i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; int preferredWay; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); int priorityLevel = object->priority(); if (hotstartSolution) { // we are doing hot start const CbcSimpleInteger * thisOne = dynamic_cast (object); if (thisOne) { int iColumn = thisOne->columnNumber(); bool canDoThisHot = true; double targetValue = hotstartSolution[iColumn]; if (saveUpper[iColumn] > saveLower[iColumn]) { double value = saveSolution[iColumn]; if (hotstartPriorities) priorityLevel = hotstartPriorities[iColumn]; //double originalLower = thisOne->originalLower(); //double originalUpper = thisOne->originalUpper(); // switch off if not possible if (targetValue >= saveLower[iColumn] && targetValue <= saveUpper[iColumn]) { /* priority outranks rest always if negative otherwise can be downgraded if at correct level. Infeasibility may be increased to choose 1.0 values first. choose one near wanted value */ if (fabs(value - targetValue) > integerTolerance) { //if (infeasibility>0.01) //infeasibility = fabs(1.0e6-fabs(value-targetValue)); //else infeasibility = fabs(value - targetValue); //if (targetValue==1.0) //infeasibility += 1.0; if (value > targetValue) { preferredWay = -1; } else { preferredWay = 1; } priorityLevel = CoinAbs(priorityLevel); } else if (priorityLevel < 0) { priorityLevel = CoinAbs(priorityLevel); if (targetValue == saveLower[iColumn]) { infeasibility = integerTolerance + 1.0e-12; preferredWay = -1; } else if (targetValue == saveUpper[iColumn]) { infeasibility = integerTolerance + 1.0e-12; preferredWay = 1; } else { // can't priorityLevel += 10000000; canDoThisHot = false; } } else { priorityLevel += 10000000; canDoThisHot = false; } } else { // switch off if not possible canDoThisHot = false; } if (canDoThisHot) canDoOneHot = true; } else if (targetValue < saveLower[iColumn] || targetValue > saveUpper[iColumn]) { } } else { priorityLevel += 10000000; } } #define ZERO_ONE 0 #define ZERO_FAKE 1.0e20; #if ZERO_ONE==1 // branch on 0-1 first (temp) if (fabs(saveSolution[dynamicObject->columnNumber()]) < 1.0) priorityLevel--; #endif #if ZERO_ONE==2 if (fabs(saveSolution[dynamicObject->columnNumber()]) < 1.0) infeasibility *= ZERO_FAKE; #endif if (infeasibility) { int iColumn = numberColumns + i; bool gotDown = false; int numberThisDown = 0; bool gotUp = false; int numberThisUp = 0; double downGuess = object->downEstimate(); double upGuess = object->upEstimate(); if (dynamicObject) { // Use this object's numberBeforeTrust int numberBeforeTrustThis = dynamicObject->numberBeforeTrust(); iColumn = dynamicObject->columnNumber(); gotDown = false; numberThisDown = dynamicObject->numberTimesDown(); if (numberThisDown >= numberBeforeTrustThis) gotDown = true; gotUp = false; numberThisUp = dynamicObject->numberTimesUp(); if (numberThisUp >= numberBeforeTrustThis) gotUp = true; if (!depth_ && false) { // try closest to 0.5 double part = saveSolution[iColumn] - floor(saveSolution[iColumn]); infeasibility = fabs(0.5 - part); } if (problemType > 0 && problemType < 4 && false) { // try closest to 0.5 double part = saveSolution[iColumn] - floor(saveSolution[iColumn]); infeasibility = 0.5 - fabs(0.5 - part); } #ifdef JJF_ZERO if (probingInfo) { int iSeq = backward[iColumn]; assert (iSeq >= 0); infeasibility = 1.0 + (toZero[iSeq+1] - toZero[iSeq]) + 5.0 * CoinMin(toOne[iSeq] - toZero[iSeq], toZero[iSeq+1] - toOne[iSeq]); if (toZero[iSeq+1] > toZero[iSeq]) { numberUnsatisProbed++; } else { numberUnsatisNotProbed++; } } #endif } else { // see if SOS CbcSOS * sosObject = dynamic_cast (object) ; if (sosObject) { gotDown = false; numberThisDown = sosObject->numberTimesDown(); if (numberThisDown >= numberBeforeTrust) gotDown = true; gotUp = false; numberThisUp = sosObject->numberTimesUp(); if (numberThisUp >= numberBeforeTrust) gotUp = true; } else { gotDown = true; numberThisDown = 999999; downGuess = 1.0e20; gotUp = true; numberThisUp = 999999; upGuess = 1.0e20; numberPassesLeft = 0; } } // Increase estimated degradation to solution estimatedDegradation += CoinMin(downGuess, upGuess); downEstimate[i] = downGuess; upEstimate[i] = upGuess; numberUnsatisfied_++; sumInfeasibilities_ += infeasibility; // Better priority? Flush choices. if (priorityLevel < bestPriority) { numberToDo = 0; bestPriority = priorityLevel; iBestGot = -1; best = 0.0; numberNotTrusted = 0; #ifdef RANGING neededPenalties = 0; optionalPenalties = numberObjects; #endif } else if (priorityLevel > bestPriority) { continue; } if (!gotUp || !gotDown) numberNotTrusted++; // Check for suitability based on infeasibility. if ((gotDown && gotUp) && numberStrong > 0) { sort[numberToDo] = -infeasibility; if (infeasibility > best) { best = infeasibility; iBestGot = numberToDo; } #ifdef RANGING if (dynamicObject) { objectMark[--optionalPenalties] = numberToDo; which[optionalPenalties] = iColumn; } #endif } else { #ifdef RANGING if (dynamicObject) { objectMark[neededPenalties] = numberToDo; which[neededPenalties++] = iColumn; } #endif sort[numberToDo] = -10.0 * infeasibility; if (!(numberThisUp + numberThisDown)) sort[numberToDo] *= 100.0; // make even more likely if (iColumn < numberColumns) { double part = saveSolution[iColumn] - floor(saveSolution[iColumn]); if (1.0 - fabs(part - 0.5) > bestNot) { iBestNot = numberToDo; bestNot = 1.0 - fabs(part - 0.5); } } else { // SOS if (-sort[numberToDo] > bestNot) { iBestNot = numberToDo; bestNot = -sort[numberToDo]; } } } if (model->messageHandler()->logLevel() > 3) { printf("%d (%d) down %d %g up %d %g - infeas %g - sort %g solution %g\n", i, iColumn, numberThisDown, object->downEstimate(), numberThisUp, object->upEstimate(), infeasibility, sort[numberToDo], saveSolution[iColumn]); } whichObject[numberToDo++] = i; } else { // for debug downEstimate[i] = -1.0; upEstimate[i] = -1.0; } } if (numberUnsatisfied_) { //if (probingInfo&&false) //printf("nunsat %d, %d probed, %d other 0-1\n",numberUnsatisfied_, // numberUnsatisProbed,numberUnsatisNotProbed); // some infeasibilities - go to next steps if (!canDoOneHot && hotstartSolution) { // switch off as not possible hotstartSolution = NULL; model->setHotstartSolution(NULL, NULL); usefulInfo.hotstartSolution_ = NULL; } break; } else if (!iPass) { // may just need resolve model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); if (!solver->isProvenOptimal()) { // infeasible anyAction = -2; break; } // Double check looks OK - just look at rows with all integers if (model->allDynamic()) { double * solution = CoinCopyOfArray(saveSolution, numberColumns); for (int i = 0; i < numberColumns; i++) { if (model->isInteger(i)) solution[i] = floor(solution[i] + 0.5); } int numberRows = solver->getNumRows(); double * rowActivity = new double [numberRows]; CoinZeroN(rowActivity, numberRows); solver->getMatrixByCol()->times(solution, rowActivity); //const double * element = model->solver()->getMatrixByCol()->getElements(); const int * row = model->solver()->getMatrixByCol()->getIndices(); const CoinBigIndex * columnStart = model->solver()->getMatrixByCol()->getVectorStarts(); const int * columnLength = model->solver()->getMatrixByCol()->getVectorLengths(); int nFree = 0; int nFreeNon = 0; int nFixedNon = 0; double mostAway = 0.0; int whichAway = -1; const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); for (int i = 0; i < numberColumns; i++) { if (!model->isInteger(i)) { // mark rows as flexible CoinBigIndex start = columnStart[i]; CoinBigIndex end = start + columnLength[i]; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; rowActivity[iRow] = COIN_DBL_MAX; } } else if (columnLower[i] < columnUpper[i]) { if (fabs(solution[i] - saveSolution[i]) > integerTolerance) { nFreeNon++; if (fabs(solution[i] - saveSolution[i]) > mostAway) { mostAway = fabs(solution[i] - saveSolution[i]); whichAway = i; } } else { nFree++; } } else if (solution[i] != saveSolution[i]) { nFixedNon++; } } const double * lower = solver->getRowLower(); const double * upper = solver->getRowUpper(); bool satisfied = true; for (int i = 0; i < numberRows; i++) { double value = rowActivity[i]; if (value != COIN_DBL_MAX) { if (value > upper[i] + 1.0e-5 || value < lower[i] - 1.0e-5) { satisfied = false; } } } delete [] rowActivity; delete [] solution; if (!satisfied) { #ifdef CLP_INVESTIGATE printf("%d free ok %d free off target %d fixed off target\n", nFree, nFreeNon, nFixedNon); #endif if (nFreeNon) { // try branching on these delete branch_; for (int i = 0; i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); CbcSimpleIntegerDynamicPseudoCost * obj = dynamic_cast (object) ; assert (obj); int iColumn = obj->columnNumber(); if (iColumn == whichAway) { int preferredWay = (saveSolution[iColumn] > solution[iColumn]) ? -1 : +1; usefulInfo.integerTolerance_ = 0.0; branch_ = obj->createCbcBranch(solver, &usefulInfo, preferredWay); break; } } anyAction = 0; break; } } } } else if (iPass == 1) { // looks like a solution - get paranoid bool roundAgain = false; // get basis CoinWarmStartBasis * ws = dynamic_cast(solver->getWarmStart()); if (!ws) break; double tolerance; solver->getDblParam(OsiPrimalTolerance, tolerance); for (i = 0; i < numberColumns; i++) { double value = saveSolution[i]; if (value < lower[i] - tolerance) { saveSolution[i] = lower[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound); } else if (value > upper[i] + tolerance) { saveSolution[i] = upper[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound); } } if (roundAgain) { // restore basis solver->setWarmStart(ws); solver->setColSolution(saveSolution); delete ws; bool takeHint; OsiHintStrength strength; solver->getHintParam(OsiDoDualInResolve, takeHint, strength); solver->setHintParam(OsiDoDualInResolve, false, OsiHintDo) ; model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); solver->setHintParam(OsiDoDualInResolve, takeHint, strength) ; if (!solver->isProvenOptimal()) { // infeasible anyAction = -2; break; } } else { delete ws; break; } } } if (anyAction == -2) { break; } // skip if solution if (!numberUnsatisfied_) break; int skipAll = (numberNotTrusted == 0 || numberToDo == 1) ? 1 : 0; bool doneHotStart = false; //DEPRECATED_STRATEGYint searchStrategy = saveSearchStrategy>=0 ? (saveSearchStrategy%10) : -1; int searchStrategy = model->searchStrategy(); // But adjust depending on ratio of iterations if (searchStrategy > 0) { if (numberBeforeTrust >= /*5*/ 10 && numberBeforeTrust <= 10) { if (searchStrategy != 2) { assert (searchStrategy == 1); if (depth_ > 5) { int numberIterations = model->getIterationCount(); int numberStrongIterations = model->numberStrongIterations(); if (numberStrongIterations > numberIterations + 10000) { searchStrategy = 2; skipAll = 1; } else if (numberStrongIterations*4 + 1000 < numberIterations) { searchStrategy = 3; skipAll = 0; } } else { searchStrategy = 3; skipAll = 0; } } } } // worth trying if too many times // Save basis CoinWarmStart * ws = NULL; // save limit int saveLimit = 0; solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit); if (!numberPassesLeft) skipAll = 1; if (!skipAll) { ws = solver->getWarmStart(); int limit = 100; if (!saveStateOfSearch && saveLimit < limit && saveLimit == 100) solver->setIntParam(OsiMaxNumIterationHotStart, limit); } // Say which one will be best int whichChoice = 0; int bestChoice; if (iBestGot >= 0) bestChoice = iBestGot; else bestChoice = iBestNot; assert (bestChoice >= 0); // If we have hit max time don't do strong branching bool hitMaxTime = (model->getCurrentSeconds() > model->getDblParam(CbcModel::CbcMaximumSeconds)); // also give up if we are looping round too much if (hitMaxTime || numberPassesLeft <= 0 || useShadow == 2) { int iObject = whichObject[bestChoice]; OsiObject * object = model->modifiableObject(iObject); int preferredWay; object->infeasibility(&usefulInfo, preferredWay); CbcObject * obj = dynamic_cast (object) ; assert (obj); branch_ = obj->createCbcBranch(solver, &usefulInfo, preferredWay); { CbcBranchingObject * branchObj = dynamic_cast (branch_) ; assert (branchObj); branchObj->way(preferredWay); } delete ws; ws = NULL; break; } else { // say do fast int easy = 1; if (!skipAll) solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ; int iDo; #define RESET_BOUNDS #ifdef RANGING bool useRanging = model->allDynamic() && !skipAll; if (useRanging) { double currentObjective = solver->getObjValue() * solver->getObjSense(); double gap = cutoff - currentObjective; // relax a bit gap *= 1.0000001; gap = CoinMax(1.0e-5, gap); // off penalties if too much double needed = neededPenalties; needed *= numberRows; if (numberNodes) { if (needed > 1.0e6) { neededPenalties = 0; } else if (gap < 1.0e5) { // maybe allow some not needed int extra = static_cast ((1.0e6 - needed) / numberRows); int nStored = numberObjects - optionalPenalties; extra = CoinMin(extra, nStored); for (int i = 0; i < extra; i++) { objectMark[neededPenalties] = objectMark[optionalPenalties+i]; which[neededPenalties++] = which[optionalPenalties+i];; } } } if (osiclp && neededPenalties) { assert (!doneHotStart); xPen += neededPenalties; which--; which[0] = neededPenalties; osiclp->passInRanges(which); // Mark hot start and get ranges if (kPass) { // until can work out why solution can go funny int save = osiclp->specialOptions(); osiclp->setSpecialOptions(save | 256); solver->markHotStart(); #ifdef RESET_BOUNDS memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double)); memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double)); #endif osiclp->setSpecialOptions(save); } else { solver->markHotStart(); #ifdef RESET_BOUNDS memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double)); memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double)); #endif } doneHotStart = true; xMark++; kPass++; osiclp->passInRanges(NULL); const double * downCost = osiclp->upRange(); const double * upCost = osiclp->downRange(); bool problemFeasible = true; int numberFixed = 0; for (int i = 0; i < neededPenalties; i++) { int j = objectMark[i]; int iObject = whichObject[j]; OsiObject * object = model->modifiableObject(iObject); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; // Use this object's numberBeforeTrust int numberBeforeTrustThis = dynamicObject->numberBeforeTrust(); int iSequence = dynamicObject->columnNumber(); double value = saveSolution[iSequence]; value -= floor(value); double upPenalty = CoinMin(upCost[i], 1.0e110) * (1.0 - value); double downPenalty = CoinMin(downCost[i], 1.0e110) * value; int numberThisDown = dynamicObject->numberTimesDown(); int numberThisUp = dynamicObject->numberTimesUp(); if (!numberBeforeTrustThis) { // override downEstimate[iObject] = downPenalty; upEstimate[iObject] = upPenalty; double min1 = CoinMin(downEstimate[iObject], upEstimate[iObject]); double max1 = CoinMax(downEstimate[iObject], upEstimate[iObject]); min1 = 0.8 * min1 + 0.2 * max1; sort[j] = - min1; } else if (numberThisDown < numberBeforeTrustThis || numberThisUp < numberBeforeTrustThis) { double invTrust = 1.0 / static_cast (numberBeforeTrustThis); if (numberThisDown < numberBeforeTrustThis) { double fraction = numberThisDown * invTrust; downEstimate[iObject] = fraction * downEstimate[iObject] + (1.0 - fraction) * downPenalty; } if (numberThisUp < numberBeforeTrustThis) { double fraction = numberThisUp * invTrust; upEstimate[iObject] = fraction * upEstimate[iObject] + (1.0 - fraction) * upPenalty; } double min1 = CoinMin(downEstimate[iObject], upEstimate[iObject]); double max1 = CoinMax(downEstimate[iObject], upEstimate[iObject]); min1 = 0.8 * min1 + 0.2 * max1; min1 *= 10.0; if (!(numberThisDown + numberThisUp)) min1 *= 100.0; sort[j] = - min1; } // seems unreliable if (false&&CoinMax(downPenalty, upPenalty) > gap) { COIN_DETAIL_PRINT(printf("gap %g object %d has down range %g, up %g\n", gap, i, downPenalty, upPenalty)); //sort[j] -= 1.0e50; // make more likely to be chosen int number; if (downPenalty > gap) { number = dynamicObject->numberTimesDown(); if (upPenalty > gap) problemFeasible = false; CbcBranchingObject * branch = dynamicObject->createCbcBranch(solver, &usefulInfo, 1); //branch->fix(solver,saveLower,saveUpper,1); delete branch; } else { number = dynamicObject->numberTimesUp(); CbcBranchingObject * branch = dynamicObject->createCbcBranch(solver, &usefulInfo, 1); //branch->fix(solver,saveLower,saveUpper,-1); delete branch; } if (number >= numberBeforeTrustThis) dynamicObject->setNumberBeforeTrust(CoinMin(number + 1,5*numberBeforeTrust)); numberFixed++; } if (!numberNodes) COIN_DETAIL_PRINT(printf("%d pen down ps %g -> %g up ps %g -> %g\n", iObject, downPenalty, downPenalty, upPenalty, upPenalty)); } if (numberFixed && problemFeasible) { assert(doneHotStart); solver->unmarkHotStart(); model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); solver->markHotStart(); #ifdef RESET_BOUNDS memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double)); memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double)); #endif problemFeasible = solver->isProvenOptimal(); } if (!problemFeasible) { COIN_DETAIL_PRINT(fprintf(stdout, "both ways infeas on ranging - code needed\n")); anyAction = -2; if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } //printf("Both infeasible for choice %d sequence %d\n",i, // model->object(choice.objectNumber)->columnNumber()); // Delete the snapshot solver->unmarkHotStart(); // back to normal solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; // restore basis solver->setWarmStart(ws); doneHotStart = false; delete ws; ws = NULL; break; } } } #endif /* RANGING */ { int numberIterations = model->getIterationCount(); //numberIterations += (model->numberExtraIterations()>>2); const int * strongInfo = model->strongInfo(); //int numberDone = strongInfo[0]-strongInfo[3]; int numberFixed = strongInfo[1] - strongInfo[4]; int numberInfeasible = strongInfo[2] - strongInfo[5]; assert (!strongInfo[3]); assert (!strongInfo[4]); assert (!strongInfo[5]); int numberStrongIterations = model->numberStrongIterations(); int numberRows = solver->getNumRows(); if (numberStrongIterations > numberIterations + CoinMin(100, 10*numberRows) && depth_ >= 4 && numberNodes > 100) { if (20*numberInfeasible + 4*numberFixed < numberNodes) { // Say never do if (numberBeforeTrust == 5) skipAll = -1; } } } // make sure best will be first if (iBestGot >= 0) sort[iBestGot] = -COIN_DBL_MAX; // Actions 0 - exit for repeat, 1 resolve and try old choice,2 exit for continue if (anyAction) numberToDo = 0; // skip as we will be trying again // Sort CoinSort_2(sort, sort + numberToDo, whichObject); // Change in objective opposite infeasible double worstFeasible = 0.0; // Just first if strong off if (!numberStrong) numberToDo = CoinMin(numberToDo, 1); if (searchStrategy == 2) numberToDo = CoinMin(numberToDo, 20); iDo = 0; int saveLimit2; solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit2); int numberTest = numberNotTrusted > 0 ? numberStrong : (numberStrong + 1) / 2; if (searchStrategy == 3) { // Previously decided we need strong numberTest = numberStrong; } // Try nearly always off if (skipAll >= 0) { if (searchStrategy < 2) { //if ((numberNodes%20)!=0) { if ((model->specialOptions()&8) == 0) { numberTest = 0; } //} else { //numberTest=2*numberStrong; //skipAll=0; //} } } else { // Just take first numberTest = 1; } int testDepth = (skipAll >= 0) ? 8 : 4; if (depth_ < testDepth && numberStrong) { if (searchStrategy != 2) { int numberRows = solver->getNumRows(); // whether to do this or not is important - think if (numberRows < 300 || numberRows + numberColumns < 2500) { if (depth_ < 7) numberStrong = CoinMin(3 * numberStrong, numberToDo); if (!depth_) numberStrong = CoinMin(6 * numberStrong, numberToDo); } numberTest = numberStrong; skipAll = 0; } } // Do at least 5 strong if (numberColumns < 1000 && (depth_ < 15 || numberNodes < 1000000)) numberTest = CoinMax(numberTest, 5); if ((model->specialOptions()&8) == 0) { if (skipAll) { numberTest = 0; } } else { // do 5 as strong is fixing numberTest = CoinMax(numberTest, 5); } // see if switched off if (skipAll < 0) { numberTest = 0; } int realMaxHotIterations = 999999; if (skipAll < 0) numberToDo = 1; strongType=0; #ifdef DO_ALL_AT_ROOT if (model->strongStrategy()) { int iStrategy=model->strongStrategy(); int kDepth = iStrategy/100; if (kDepth) iStrategy -= 100*kDepth; else kDepth=5; double objValue = solver->getObjSense()*solver->getObjValue(); double bestPossible = model->getBestPossibleObjValue(); bestPossible += 1.0e-7*(1.0+fabs(bestPossible)); int jStrategy = iStrategy/10; if (jStrategy) { if ((jStrategy&1)!=0&&!depth_) strongType=2; else if ((jStrategy&2)!=0&&depth_<=kDepth) strongType=2; else if ((jStrategy&4)!=0&&objValueintegerVariable(); int numberIntegers = model->numberIntegers(); if (numberIntegers==numberObjects) { numberToDo=0; for (int i=0;isaveLower[iColumn]) { whichObject [numberToDo++]=i; } } saveSatisfiedVariables=numberToDo-saveNumberToDo; } else { strongType=1; } } if (strongType) { numberTest = numberToDo; numberStrong=numberToDo; skipAll=0; searchStrategy=0; solver->setIntParam(OsiMaxNumIterationHotStart, 100000); //printf("Strong branching type %d\n",strongType); } } #endif for ( iDo = 0; iDo < numberToDo; iDo++) { int iObject = whichObject[iDo]; OsiObject * object = model->modifiableObject(iObject); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; int iColumn = dynamicObject ? dynamicObject->columnNumber() : numberColumns + iObject; int preferredWay; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); double predictedChange=0.0; // may have become feasible if (!infeasibility) { if(strongType!=2||solver->getColLower()[iColumn]==solver->getColUpper()[iColumn]) continue; } #ifndef NDEBUG if (iColumn < numberColumns) { const double * solution = model->testSolution(); assert (saveSolution[iColumn] == solution[iColumn]); } #endif CbcSimpleInteger * obj = dynamic_cast (object) ; if (obj) { if (choiceObject) { obj->fillCreateBranch(choiceObject, &usefulInfo, preferredWay); choiceObject->setObject(dynamicObject); } else { choice.possibleBranch = obj->createCbcBranch(solver, &usefulInfo, preferredWay); } } else { CbcObject * obj = dynamic_cast (object) ; assert (obj); choice.possibleBranch = obj->createCbcBranch(solver, &usefulInfo, preferredWay); } // Save which object it was choice.objectNumber = iObject; choice.numIntInfeasUp = numberUnsatisfied_; choice.numIntInfeasDown = numberUnsatisfied_; if (strongType!=2) { choice.upMovement = upEstimate[iObject]; choice.downMovement = downEstimate[iObject]; } else { choice.upMovement = 0.1; choice.downMovement = 0.1; } assert (choice.upMovement >= 0.0); assert (choice.downMovement >= 0.0); choice.fix = 0; // say not fixed // see if can skip strong branching int canSkip = choice.possibleBranch->fillStrongInfo(choice); if ((numberTest <= 0 || skipAll)) { if (iDo > 20) { if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } break; // give up anyway } } if (model->messageHandler()->logLevel() > 3 && numberBeforeTrust && dynamicObject) dynamicObject->print(1, choice.possibleBranch->value()); if (strongType) canSkip=0; if (skipAll < 0) canSkip = 1; if (!canSkip) { if (!doneHotStart) { // Mark hot start doneHotStart = true; solver->markHotStart(); #ifdef RESET_BOUNDS memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double)); memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double)); #endif if (!solver->isProvenOptimal()) { skipAll=-2; canSkip = 1; } xMark++; } } if (!canSkip) { numberTest--; // just do a few if (searchStrategy == 2) solver->setIntParam(OsiMaxNumIterationHotStart, 10); double objectiveChange ; double newObjectiveValue = 1.0e100; int j; // status is 0 finished, 1 infeasible and other int iStatus; /* Try the down direction first. (Specify the initial branching alternative as down with a call to way(-1). Each subsequent call to branch() performs the specified branch and advances the branch object state to the next branch alternative.) */ choice.possibleBranch->way(-1) ; predictedChange = choice.possibleBranch->branch() ; solver->solveFromHotStart() ; bool needHotStartUpdate = false; numberStrongDone++; numberStrongIterations += solver->getIterationCount(); /* We now have an estimate of objective degradation that we can use for strong branching. If we're over the cutoff, the variable is monotone up. If we actually made it to optimality, check for a solution, and if we have a good one, call setBestSolution to process it. Note that this may reduce the cutoff, so we check again to see if we can declare this variable monotone. */ if (solver->isProvenOptimal()) iStatus = 0; // optimal else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) { iStatus = 2; // unknown } else { iStatus = 1; // infeasible #ifdef CONFLICT_CUTS # ifdef COIN_HAS_CLP if (osiclp&&(model->moreSpecialOptions()&4194304)!=0) { const CbcFullNodeInfo * topOfTree = model->topOfTree(); if (topOfTree) { OsiRowCut * cut = osiclp->smallModelCut(topOfTree->lower(), topOfTree->upper(), model->numberRowsAtContinuous(), model->whichGenerator()); if (cut) { printf("XXXXXX found conflict cut in strong branching\n"); //cut->print(); if ((model->specialOptions()&1) != 0) { const OsiRowCutDebugger *debugger = model->continuousSolver()->getRowCutDebugger() ; if (debugger) { if (debugger->invalidCut(*cut)) { model->continuousSolver()->applyRowCuts(1,cut); model->continuousSolver()->writeMps("bad"); } CoinAssert (!debugger->invalidCut(*cut)); } } model->makeGlobalCut(cut) ; } } } #endif #endif } // say infeasible if branch says so if (predictedChange==COIN_DBL_MAX) iStatus=1; if (iStatus != 2 && solver->getIterationCount() > realMaxHotIterations) numberUnfinished++; newObjectiveValue = solver->getObjSense() * solver->getObjValue(); choice.numItersDown = solver->getIterationCount(); objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0); // Update branching information if wanted CbcBranchingObject * cbcobj = dynamic_cast (choice.possibleBranch); if (cbcobj) { CbcObject * object = cbcobj->object(); assert (object) ; CbcObjectUpdateData update = object->createUpdateInformation(solver, this, cbcobj); update.objectNumber_ = choice.objectNumber; model->addUpdateInformation(update); } else { decision->updateInformation( solver, this); } if (!iStatus) { choice.finishedDown = true ; if (newObjectiveValue >= cutoff) { objectiveChange = 1.0e100; // say infeasible numberStrongInfeasible++; } else { #define CBCNODE_TIGHTEN_BOUNDS #ifdef CBCNODE_TIGHTEN_BOUNDS // Can we tighten bounds? if (iColumn < numberColumns && cutoff < 1.0e20 && objectiveChange > 1.0e-5) { double value = saveSolution[iColumn]; double down = value - floor(value-integerTolerance); double changePer = objectiveChange / (down + 1.0e-7); double distance = (cutoff - objectiveValue_) / changePer; distance += 1.0e-3; if (distance < 5.0) { double newLower = ceil(value - distance); if (newLower > saveLower[iColumn]) { //printf("Could increase lower bound on %d from %g to %g\n", // iColumn,saveLower[iColumn],newLower); saveLower[iColumn] = newLower; solver->setColLower(iColumn, newLower); } } } #endif // See if integer solution if (model->feasibleSolution(choice.numIntInfeasDown, choice.numObjInfeasDown) && model->problemFeasibility()->feasible(model, -1) >= 0) { if (auxiliaryInfo->solutionAddsCuts()) { needHotStartUpdate = true; solver->unmarkHotStart(); } model->setLogLevel(saveLogLevel); model->setBestSolution(CBC_STRONGSOL, newObjectiveValue, solver->getColSolution()) ; if (needHotStartUpdate) { model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); newObjectiveValue = solver->getObjSense() * solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjectiveValue); objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0); model->feasibleSolution(choice.numIntInfeasDown, choice.numObjInfeasDown); } model->setLastHeuristic(NULL); model->incrementUsed(solver->getColSolution()); cutoff = model->getCutoff(); if (newObjectiveValue >= cutoff) { // *new* cutoff objectiveChange = 1.0e100 ; numberStrongInfeasible++; } } } } else if (iStatus == 1) { objectiveChange = 1.0e100 ; numberStrongInfeasible++; } else { // Can't say much as we did not finish choice.finishedDown = false ; numberUnfinished++; } choice.downMovement = objectiveChange ; // restore bounds for ( j = 0; j < numberColumns; j++) { if (saveLower[j] != lower[j]) solver->setColLower(j, saveLower[j]); if (saveUpper[j] != upper[j]) solver->setColUpper(j, saveUpper[j]); } if (needHotStartUpdate) { needHotStartUpdate = false; model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); //we may again have an integer feasible solution int numberIntegerInfeasibilities; int numberObjectInfeasibilities; if (model->feasibleSolution( numberIntegerInfeasibilities, numberObjectInfeasibilities)) { #ifdef BONMIN //In this case node has become integer feasible, let us exit the loop std::cout << "Node has become integer feasible" << std::endl; numberUnsatisfied_ = 0; break; #endif double objValue = solver->getObjValue(); model->setLogLevel(saveLogLevel); model->setBestSolution(CBC_STRONGSOL, objValue, solver->getColSolution()) ; model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); cutoff = model->getCutoff(); } solver->markHotStart(); #ifdef RESET_BOUNDS memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double)); memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double)); #endif if (!solver->isProvenOptimal()) { skipAll=-2; canSkip = 1; } xMark++; } #if 0 //def DO_ALL_AT_ROOT if (strongType) printf("Down on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n", choice.objectNumber, iStatus, newObjectiveValue, choice.numItersDown, choice.downMovement, choice.finishedDown, choice.numIntInfeasDown, choice.numObjInfeasDown); #endif // repeat the whole exercise, forcing the variable up predictedChange=choice.possibleBranch->branch(); solver->solveFromHotStart() ; numberStrongDone++; numberStrongIterations += solver->getIterationCount(); /* We now have an estimate of objective degradation that we can use for strong branching. If we're over the cutoff, the variable is monotone up. If we actually made it to optimality, check for a solution, and if we have a good one, call setBestSolution to process it. Note that this may reduce the cutoff, so we check again to see if we can declare this variable monotone. */ if (solver->isProvenOptimal()) iStatus = 0; // optimal else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) { iStatus = 2; // unknown } else { iStatus = 1; // infeasible #ifdef CONFLICT_CUTS # ifdef COIN_HAS_CLP if (osiclp&&(model->moreSpecialOptions()&4194304)!=0) { const CbcFullNodeInfo * topOfTree = model->topOfTree(); if (topOfTree) { OsiRowCut * cut = osiclp->smallModelCut(topOfTree->lower(), topOfTree->upper(), model->numberRowsAtContinuous(), model->whichGenerator()); if (cut) { printf("XXXXXX found conflict cut in strong branching\n"); //cut->print(); if ((model->specialOptions()&1) != 0) { const OsiRowCutDebugger *debugger = model->continuousSolver()->getRowCutDebugger() ; if (debugger) { if (debugger->invalidCut(*cut)) { model->continuousSolver()->applyRowCuts(1,cut); model->continuousSolver()->writeMps("bad"); } CoinAssert (!debugger->invalidCut(*cut)); } } model->makeGlobalCut(cut) ; } } } #endif #endif } // say infeasible if branch says so if (predictedChange==COIN_DBL_MAX) iStatus=1; if (iStatus != 2 && solver->getIterationCount() > realMaxHotIterations) numberUnfinished++; newObjectiveValue = solver->getObjSense() * solver->getObjValue(); choice.numItersUp = solver->getIterationCount(); objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0); // Update branching information if wanted cbcobj = dynamic_cast (choice.possibleBranch); if (cbcobj) { CbcObject * object = cbcobj->object(); assert (object) ; CbcObjectUpdateData update = object->createUpdateInformation(solver, this, cbcobj); update.objectNumber_ = choice.objectNumber; model->addUpdateInformation(update); } else { decision->updateInformation( solver, this); } if (!iStatus) { choice.finishedUp = true ; if (newObjectiveValue >= cutoff) { objectiveChange = 1.0e100; // say infeasible numberStrongInfeasible++; } else { #ifdef CBCNODE_TIGHTEN_BOUNDS // Can we tighten bounds? if (iColumn < numberColumns && cutoff < 1.0e20 && objectiveChange > 1.0e-5) { double value = saveSolution[iColumn]; double up = ceil(value+integerTolerance) - value; double changePer = objectiveChange / (up + 1.0e-7); double distance = (cutoff - objectiveValue_) / changePer; distance += 1.0e-3; if (distance < 5.0) { double newUpper = floor(value + distance); if (newUpper < saveUpper[iColumn]) { //printf("Could decrease upper bound on %d from %g to %g\n", // iColumn,saveUpper[iColumn],newUpper); saveUpper[iColumn] = newUpper; solver->setColUpper(iColumn, newUpper); } } } #endif // See if integer solution if (model->feasibleSolution(choice.numIntInfeasUp, choice.numObjInfeasUp) && model->problemFeasibility()->feasible(model, -1) >= 0) { #ifdef BONMIN std::cout << "Node has become integer feasible" << std::endl; numberUnsatisfied_ = 0; break; #endif if (auxiliaryInfo->solutionAddsCuts()) { needHotStartUpdate = true; solver->unmarkHotStart(); } model->setLogLevel(saveLogLevel); model->setBestSolution(CBC_STRONGSOL, newObjectiveValue, solver->getColSolution()) ; if (choice.finishedDown) { double cutoff = model->getCutoff(); double downObj = objectiveValue_ + choice.downMovement ; if (downObj >= cutoff) { choice.downMovement = 1.0e100 ; numberStrongInfeasible++; } } if (needHotStartUpdate) { model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); newObjectiveValue = solver->getObjSense() * solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjectiveValue); objectiveChange = CoinMax(newObjectiveValue - objectiveValue_, 0.0); model->feasibleSolution(choice.numIntInfeasDown, choice.numObjInfeasDown); } model->setLastHeuristic(NULL); model->incrementUsed(solver->getColSolution()); cutoff = model->getCutoff(); if (newObjectiveValue >= cutoff) { // *new* cutoff objectiveChange = 1.0e100 ; numberStrongInfeasible++; } } } } else if (iStatus == 1) { objectiveChange = 1.0e100 ; numberStrongInfeasible++; } else { // Can't say much as we did not finish choice.finishedUp = false ; numberUnfinished++; } choice.upMovement = objectiveChange ; // restore bounds for ( j = 0; j < numberColumns; j++) { if (saveLower[j] != lower[j]) solver->setColLower(j, saveLower[j]); if (saveUpper[j] != upper[j]) solver->setColUpper(j, saveUpper[j]); } if (needHotStartUpdate) { needHotStartUpdate = false; model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); //we may again have an integer feasible solution int numberIntegerInfeasibilities; int numberObjectInfeasibilities; if (model->feasibleSolution( numberIntegerInfeasibilities, numberObjectInfeasibilities)) { double objValue = solver->getObjValue(); model->setLogLevel(saveLogLevel); model->setBestSolution(CBC_STRONGSOL, objValue, solver->getColSolution()) ; model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); cutoff = model->getCutoff(); } solver->markHotStart(); #ifdef RESET_BOUNDS memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double)); memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double)); #endif if (!solver->isProvenOptimal()) { skipAll=-2; canSkip = 1; } xMark++; } #if 0 //def DO_ALL_AT_ROOT if (strongType) printf("Up on %d, status is %d, obj %g its %d cost %g finished %d inf %d infobj %d\n", choice.objectNumber, iStatus, newObjectiveValue, choice.numItersUp, choice.upMovement, choice.finishedUp, choice.numIntInfeasUp, choice.numObjInfeasUp); #endif } solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit2); /* End of evaluation for this candidate variable. Possibilities are: * Both sides below cutoff; this variable is a candidate for branching. * Both sides infeasible or above the objective cutoff: no further action here. Break from the evaluation loop and assume the node will be purged by the caller. * One side below cutoff: Install the branch (i.e., fix the variable). Break from the evaluation loop and assume the node will be reoptimised by the caller. */ // reset choice.possibleBranch->resetNumberBranchesLeft(); if (choice.upMovement < 1.0e100) { if (choice.downMovement < 1.0e100) { // In case solution coming in was odd choice.upMovement = CoinMax(0.0, choice.upMovement); choice.downMovement = CoinMax(0.0, choice.downMovement); #if ZERO_ONE==2 // branch on 0-1 first (temp) if (fabs(choice.possibleBranch->value()) < 1.0) { choice.upMovement *= ZERO_FAKE; choice.downMovement *= ZERO_FAKE; } #endif // feasible - see which best if (!canSkip) { if (model->messageHandler()->logLevel() > 3) printf("sort %g downest %g upest %g ", sort[iDo], downEstimate[iObject], upEstimate[iObject]); model->messageHandler()->message(CBC_STRONG, *model->messagesPointer()) << iObject << iColumn << choice.downMovement << choice.numIntInfeasDown << choice.upMovement << choice.numIntInfeasUp << choice.possibleBranch->value() << CoinMessageEol; } int betterWay=0; // If was feasible (extra strong branching) skip if (infeasibility) { CbcBranchingObject * branchObj = dynamic_cast (branch_) ; if (branch_) assert (branchObj); betterWay = decision->betterBranch(choice.possibleBranch, branchObj, choice.upMovement, choice.numIntInfeasUp , choice.downMovement, choice.numIntInfeasDown ); } if (betterWay) { // C) create branching object if (choiceObject) { delete branch_; branch_ = choice.possibleBranch->clone(); } else { delete branch_; branch_ = choice.possibleBranch; choice.possibleBranch = NULL; } { CbcBranchingObject * branchObj = dynamic_cast (branch_) ; assert (branchObj); //branchObj->way(preferredWay); branchObj->way(betterWay); } bestChoice = choice.objectNumber; whichChoice = iDo; if (numberStrong <= 1) { delete ws; ws = NULL; break; } } else { if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } if (iDo >= 2*numberStrong) { delete ws; ws = NULL; break; } if (!dynamicObject || dynamicObject->numberTimesUp() > 1) { if (iDo - whichChoice >= numberStrong) { if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } break; // give up } } else { if (iDo - whichChoice >= 2*numberStrong) { delete ws; ws = NULL; if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } break; // give up } } } } else { // up feasible, down infeasible anyAction = -1; worstFeasible = CoinMax(worstFeasible, choice.upMovement); model->messageHandler()->message(CBC_STRONG, *model->messagesPointer()) << iObject << iColumn << choice.downMovement << choice.numIntInfeasDown << choice.upMovement << choice.numIntInfeasUp << choice.possibleBranch->value() << CoinMessageEol; //printf("Down infeasible for choice %d sequence %d\n",i, // model->object(choice.objectNumber)->columnNumber()); choice.fix = 1; numberToFix++; choice.possibleBranch->fix(solver, saveLower, saveUpper, 1); if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } else { //choiceObject = new CbcDynamicPseudoCostBranchingObject(*choiceObject); choice.possibleBranch = choiceObject; } assert(doneHotStart); solver->unmarkHotStart(); model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); bool goneInfeasible = (!solver->isProvenOptimal()||solver->isDualObjectiveLimitReached()); solver->markHotStart(); #ifdef RESET_BOUNDS memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double)); memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double)); #endif if (!solver->isProvenOptimal()) { skipAll=-2; canSkip = 1; } xMark++; // may be infeasible (if other way stopped on iterations) if (goneInfeasible) { // neither side feasible anyAction = -2; if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } //printf("Both infeasible for choice %d sequence %d\n",i, // model->object(choice.objectNumber)->columnNumber()); delete ws; ws = NULL; break; } } } else { if (choice.downMovement < 1.0e100) { // down feasible, up infeasible anyAction = -1; worstFeasible = CoinMax(worstFeasible, choice.downMovement); model->messageHandler()->message(CBC_STRONG, *model->messagesPointer()) << iObject << iColumn << choice.downMovement << choice.numIntInfeasDown << choice.upMovement << choice.numIntInfeasUp << choice.possibleBranch->value() << CoinMessageEol; choice.fix = -1; numberToFix++; choice.possibleBranch->fix(solver, saveLower, saveUpper, -1); if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } else { //choiceObject = new CbcDynamicPseudoCostBranchingObject(*choiceObject); choice.possibleBranch = choiceObject; } assert(doneHotStart); solver->unmarkHotStart(); model->resolve(NULL, 11, saveSolution, saveLower, saveUpper); double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); bool goneInfeasible = (!solver->isProvenOptimal()||solver->isDualObjectiveLimitReached()); solver->markHotStart(); #ifdef RESET_BOUNDS memcpy(saveLower,solver->getColLower(),solver->getNumCols()*sizeof(double)); memcpy(saveUpper,solver->getColUpper(),solver->getNumCols()*sizeof(double)); #endif if (!solver->isProvenOptimal()) { skipAll=-2; canSkip = 1; } xMark++; // may be infeasible (if other way stopped on iterations) if (goneInfeasible) { // neither side feasible anyAction = -2; if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } delete ws; ws = NULL; break; } } else { // neither side feasible anyAction = -2; if (!choiceObject) { delete choice.possibleBranch; choice.possibleBranch = NULL; } delete ws; ws = NULL; break; } } // Check max time hitMaxTime = (model->getCurrentSeconds() > model->getDblParam(CbcModel::CbcMaximumSeconds)); if (hitMaxTime) { // make sure rest are fast for ( int jDo = iDo + 1; jDo < numberToDo; jDo++) { int iObject = whichObject[iDo]; OsiObject * object = model->modifiableObject(iObject); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; if (dynamicObject) dynamicObject->setNumberBeforeTrust(0); } numberTest = 0; } if (!choiceObject) { delete choice.possibleBranch; } } if (model->messageHandler()->logLevel() > 3) { if (anyAction == -2) { printf("infeasible\n"); } else if (anyAction == -1) { printf("%d fixed AND choosing %d iDo %d iChosenWhen %d numberToDo %d\n", numberToFix, bestChoice, iDo, whichChoice, numberToDo); } else { int iObject = whichObject[whichChoice]; OsiObject * object = model->modifiableObject(iObject); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; if (dynamicObject) { int iColumn = dynamicObject->columnNumber(); printf("choosing %d (column %d) iChosenWhen %d numberToDo %d\n", bestChoice, iColumn, whichChoice, numberToDo); } } } if (doneHotStart) { // Delete the snapshot solver->unmarkHotStart(); // back to normal solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; // restore basis solver->setWarmStart(ws); } solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit); // Unless infeasible we will carry on // But we could fix anyway if (numberToFix && !hitMaxTime) { if (anyAction != -2) { // apply and take off bool feasible = true; // can do quick optimality check int easy = 2; solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ; model->resolve(NULL, 11, saveSolution, saveLower, saveUpper) ; double newObjValue = solver->getObjSense()*solver->getObjValue(); objectiveValue_ = CoinMax(objectiveValue_,newObjValue); solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; feasible = solver->isProvenOptimal(); if (feasible) { anyAction = 0; } else { anyAction = -2; finished = true; } } } // If fixed then round again // See if candidate still possible if (branch_) { const OsiObject * object = model->object(bestChoice); int preferredWay; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); if (!infeasibility) { // take out delete branch_; branch_ = NULL; } else { CbcBranchingObject * branchObj = dynamic_cast (branch_) ; assert (branchObj); branchObj->way(preferredWay); #ifdef CBCNODE_TIGHTEN_BOUNDS bool fixed = branchObj->tighten(solver); if (fixed) { //printf("Variable now fixed!\n"); // take out delete branch_; branch_ = NULL; } #endif } } if (!branch_ && anyAction != -2 && !hitMaxTime) { finished = false; } delete ws; } } // update number of strong iterations etc model->incrementStrongInfo(numberStrongDone, numberStrongIterations, anyAction == -2 ? 0 : numberToFix, anyAction == -2); if (model->searchStrategy() == -1) { #ifndef COIN_DEVELOP if (solver->messageHandler()->logLevel() > 1) #endif printf("%d strong, %d iters, %d inf, %d not finished, %d not trusted\n", numberStrongDone, numberStrongIterations, numberStrongInfeasible, numberUnfinished, numberNotTrusted); // decide what to do int strategy = 1; if (((numberUnfinished*4 > numberStrongDone && numberStrongInfeasible*40 < numberStrongDone) || numberStrongInfeasible < 0) && model->numberStrong() < 10 && model->numberBeforeTrust() <= 20 && model->numberObjects() > CoinMax(1000, solver->getNumRows())) { strategy = 2; #ifdef COIN_DEVELOP //if (model->logLevel()>1) printf("going to strategy 2\n"); #endif // Weaken model->setNumberStrong(2); model->setNumberBeforeTrust(1); model->synchronizeNumberBeforeTrust(); } if (numberNodes) strategy = 1; // should only happen after hot start model->setSearchStrategy(strategy); } else if (numberStrongDone) { //printf("%d strongB, %d iters, %d inf, %d not finished, %d not trusted\n", // numberStrongDone,numberStrongIterations,numberStrongInfeasible,numberUnfinished, // numberNotTrusted); } if (model->searchStrategy() == 1 && numberNodes > 500 && numberNodes < -510) { #ifndef COIN_DEVELOP if (solver->messageHandler()->logLevel() > 1) #endif printf("after %d nodes - %d strong, %d iters, %d inf, %d not finished, %d not trusted\n", numberNodes, numberStrongDone, numberStrongIterations, numberStrongInfeasible, numberUnfinished, numberNotTrusted); // decide what to do if (numberUnfinished*10 > numberStrongDone + 1 || !numberStrongInfeasible) { COIN_DETAIL_PRINT(printf("going to strategy 2\n")); // Weaken model->setNumberStrong(2); model->setNumberBeforeTrust(1); model->synchronizeNumberBeforeTrust(); model->setSearchStrategy(2); } } if (numberUnfinished*10 < numberStrongDone && model->numberStrongIterations()*20 < model->getIterationCount()&& !auxiliaryInfo->solutionAddsCuts()) { //printf("increasing trust\n"); model->synchronizeNumberBeforeTrust(2); } // Set guessed solution value guessedObjectiveValue_ = objectiveValue_ + estimatedDegradation; #ifdef DO_ALL_AT_ROOT if (strongType) { char general[200]; if (strongType==1) sprintf(general,"Strong branching on all %d unsatisfied, %d iterations (depth %d)\n", saveNumberToDo,numberStrongIterations,depth_); else sprintf(general,"Strong branching on all %d unfixed variables (%d unsatisfied), %d iterations (depth %d)\n", saveNumberToDo+saveSatisfiedVariables,saveNumberToDo,numberStrongIterations,depth_); model->messageHandler()->message(CBC_FPUMP2,model->messages()) << general << CoinMessageEol ; } #endif #ifdef DEBUG_SOLUTION if(onOptimalPath&&anyAction==-2) { printf("Gone off optimal path in CbcNode\n"); assert(!onOptimalPath||anyAction!=-2); } #endif /* Cleanup, then we're finished */ if (!model->branchingMethod()) delete decision; delete choiceObject; delete [] sort; delete [] whichObject; #ifdef RANGING delete [] objectMark; #endif delete [] saveLower; delete [] saveUpper; delete [] upEstimate; delete [] downEstimate; # ifdef COIN_HAS_CLP if (osiclp) { osiclp->setSpecialOptions(saveClpOptions); } # endif // restore solution solver->setColSolution(saveSolution); model->reserveCurrentSolution(saveSolution); delete [] saveSolution; model->setStateOfSearch(saveStateOfSearch); model->setLogLevel(saveLogLevel); // delete extra regions if (usefulInfo.usefulRegion_) { delete [] usefulInfo.usefulRegion_; delete [] usefulInfo.indexRegion_; delete [] usefulInfo.pi_; usefulInfo.usefulRegion_ = NULL; usefulInfo.indexRegion_ = NULL; usefulInfo.pi_ = NULL; } useShadow = model->moreSpecialOptions() & 7; if ((useShadow == 5 && model->getSolutionCount()) || useShadow == 6) { // zap pseudo shadow prices model->pseudoShadow(-1); // and switch off model->setMoreSpecialOptions(model->moreSpecialOptions()&(~1023)); } return anyAction; } int CbcNode::analyze (CbcModel *model, double * results) { int i; int numberIterationsAllowed = model->numberAnalyzeIterations(); OsiSolverInterface * solver = model->solver(); objectiveValue_ = solver->getObjSense() * solver->getObjValue(); double cutoff = model->getCutoff(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * dj = solver->getReducedCost(); int numberObjects = model->numberObjects(); int numberColumns = model->getNumCols(); // Initialize arrays int numberIntegers = model->numberIntegers(); int * back = new int[numberColumns]; const int * integerVariable = model->integerVariable(); for (i = 0; i < numberColumns; i++) back[i] = -1; // What results is double * newLower = results; double * objLower = newLower + numberIntegers; double * newUpper = objLower + numberIntegers; double * objUpper = newUpper + numberIntegers; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; back[iColumn] = i; newLower[i] = 0.0; objLower[i] = -COIN_DBL_MAX; newUpper[i] = 0.0; objUpper[i] = -COIN_DBL_MAX; } double * saveUpper = new double[numberColumns]; double * saveLower = new double[numberColumns]; // Save solution in case heuristics need good solution later double * saveSolution = new double[numberColumns]; memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double)); model->reserveCurrentSolution(saveSolution); for (i = 0; i < numberColumns; i++) { saveLower[i] = lower[i]; saveUpper[i] = upper[i]; } // Get arrays to sort double * sort = new double[numberObjects]; int * whichObject = new int[numberObjects]; int numberToFix = 0; int numberToDo = 0; double integerTolerance = model->getDblParam(CbcModel::CbcIntegerTolerance); // point to useful information OsiBranchingInformation usefulInfo = model->usefulInformation(); // and modify usefulInfo.depth_ = depth_; // compute current state int numberObjectInfeasibilities; // just odd ones int numberIntegerInfeasibilities; model->feasibleSolution( numberIntegerInfeasibilities, numberObjectInfeasibilities); # ifdef COIN_HAS_CLP OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver); int saveClpOptions = 0; bool fastIterations = (model->specialOptions() & 8) != 0; if (osiclp && fastIterations) { // for faster hot start saveClpOptions = osiclp->specialOptions(); osiclp->setSpecialOptions(saveClpOptions | 8192); } # else bool fastIterations = false ; # endif /* Scan for branching objects that indicate infeasibility. Choose candidates using priority as the first criteria, then integer infeasibility. The algorithm is to fill the array with a set of good candidates (by infeasibility) with priority bestPriority. Finding a candidate with priority better (less) than bestPriority flushes the choice array. (This serves as initialization when the first candidate is found.) */ numberToDo = 0; for (i = 0; i < numberObjects; i++) { OsiObject * object = model->modifiableObject(i); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; if (!dynamicObject) continue; int preferredWay; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); int iColumn = dynamicObject->columnNumber(); if (saveUpper[iColumn] == saveLower[iColumn]) continue; if (infeasibility) sort[numberToDo] = -1.0e10 - infeasibility; else sort[numberToDo] = -fabs(dj[iColumn]); whichObject[numberToDo++] = i; } // Save basis CoinWarmStart * ws = solver->getWarmStart(); int saveLimit; solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit); int targetIterations = CoinMax(500, numberIterationsAllowed / numberObjects); if (saveLimit < targetIterations) solver->setIntParam(OsiMaxNumIterationHotStart, targetIterations); // Mark hot start solver->markHotStart(); // Sort CoinSort_2(sort, sort + numberToDo, whichObject); double * currentSolution = model->currentSolution(); double objMin = 1.0e50; double objMax = -1.0e50; bool needResolve = false; /* Now calculate the cost forcing the variable up and down. */ int iDo; for (iDo = 0; iDo < numberToDo; iDo++) { CbcStrongInfo choice; int iObject = whichObject[iDo]; OsiObject * object = model->modifiableObject(iObject); CbcSimpleIntegerDynamicPseudoCost * dynamicObject = dynamic_cast (object) ; if (!dynamicObject) continue; int iColumn = dynamicObject->columnNumber(); int preferredWay; /* Update the information held in the object. */ object->infeasibility(&usefulInfo, preferredWay); double value = currentSolution[iColumn]; double nearest = floor(value + 0.5); double lowerValue = floor(value); bool satisfied = false; if (fabs(value - nearest) <= integerTolerance || value < saveLower[iColumn] || value > saveUpper[iColumn]) { satisfied = true; double newValue; if (nearest < saveUpper[iColumn]) { newValue = nearest + 1.0001 * integerTolerance; lowerValue = nearest; } else { newValue = nearest - 1.0001 * integerTolerance; lowerValue = nearest - 1; } currentSolution[iColumn] = newValue; } double upperValue = lowerValue + 1.0; //CbcSimpleInteger * obj = //dynamic_cast (object) ; //if (obj) { //choice.possibleBranch=obj->createCbcBranch(solver,&usefulInfo,preferredWay); //} else { CbcObject * obj = dynamic_cast (object) ; assert (obj); choice.possibleBranch = obj->createCbcBranch(solver, &usefulInfo, preferredWay); //} currentSolution[iColumn] = value; // Save which object it was choice.objectNumber = iObject; choice.numIntInfeasUp = numberUnsatisfied_; choice.numIntInfeasDown = numberUnsatisfied_; choice.downMovement = 0.0; choice.upMovement = 0.0; choice.numItersDown = 0; choice.numItersUp = 0; choice.fix = 0; // say not fixed double objectiveChange ; double newObjectiveValue = 1.0e100; int j; // status is 0 finished, 1 infeasible and other int iStatus; /* Try the down direction first. (Specify the initial branching alternative as down with a call to way(-1). Each subsequent call to branch() performs the specified branch and advances the branch object state to the next branch alternative.) */ choice.possibleBranch->way(-1) ; choice.possibleBranch->branch() ; if (fabs(value - lowerValue) > integerTolerance) { solver->solveFromHotStart() ; /* We now have an estimate of objective degradation that we can use for strong branching. If we're over the cutoff, the variable is monotone up. If we actually made it to optimality, check for a solution, and if we have a good one, call setBestSolution to process it. Note that this may reduce the cutoff, so we check again to see if we can declare this variable monotone. */ if (solver->isProvenOptimal()) iStatus = 0; // optimal else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) iStatus = 2; // unknown else iStatus = 1; // infeasible newObjectiveValue = solver->getObjSense() * solver->getObjValue(); choice.numItersDown = solver->getIterationCount(); numberIterationsAllowed -= choice.numItersDown; objectiveChange = newObjectiveValue - objectiveValue_; if (!iStatus) { choice.finishedDown = true ; if (newObjectiveValue >= cutoff) { objectiveChange = 1.0e100; // say infeasible } else { // See if integer solution if (model->feasibleSolution(choice.numIntInfeasDown, choice.numObjInfeasDown) && model->problemFeasibility()->feasible(model, -1) >= 0) { model->setBestSolution(CBC_STRONGSOL, newObjectiveValue, solver->getColSolution()) ; model->setLastHeuristic(NULL); model->incrementUsed(solver->getColSolution()); cutoff = model->getCutoff(); if (newObjectiveValue >= cutoff) // *new* cutoff objectiveChange = 1.0e100 ; } } } else if (iStatus == 1) { objectiveChange = 1.0e100 ; } else { // Can't say much as we did not finish choice.finishedDown = false ; } choice.downMovement = objectiveChange ; } // restore bounds for ( j = 0; j < numberColumns; j++) { if (saveLower[j] != lower[j]) solver->setColLower(j, saveLower[j]); if (saveUpper[j] != upper[j]) solver->setColUpper(j, saveUpper[j]); } // repeat the whole exercise, forcing the variable up choice.possibleBranch->branch(); if (fabs(value - upperValue) > integerTolerance) { solver->solveFromHotStart() ; /* We now have an estimate of objective degradation that we can use for strong branching. If we're over the cutoff, the variable is monotone up. If we actually made it to optimality, check for a solution, and if we have a good one, call setBestSolution to process it. Note that this may reduce the cutoff, so we check again to see if we can declare this variable monotone. */ if (solver->isProvenOptimal()) iStatus = 0; // optimal else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) iStatus = 2; // unknown else iStatus = 1; // infeasible newObjectiveValue = solver->getObjSense() * solver->getObjValue(); choice.numItersUp = solver->getIterationCount(); numberIterationsAllowed -= choice.numItersUp; objectiveChange = newObjectiveValue - objectiveValue_; if (!iStatus) { choice.finishedUp = true ; if (newObjectiveValue >= cutoff) { objectiveChange = 1.0e100; // say infeasible } else { // See if integer solution if (model->feasibleSolution(choice.numIntInfeasUp, choice.numObjInfeasUp) && model->problemFeasibility()->feasible(model, -1) >= 0) { model->setBestSolution(CBC_STRONGSOL, newObjectiveValue, solver->getColSolution()) ; model->setLastHeuristic(NULL); model->incrementUsed(solver->getColSolution()); cutoff = model->getCutoff(); if (newObjectiveValue >= cutoff) // *new* cutoff objectiveChange = 1.0e100 ; } } } else if (iStatus == 1) { objectiveChange = 1.0e100 ; } else { // Can't say much as we did not finish choice.finishedUp = false ; } choice.upMovement = objectiveChange ; // restore bounds for ( j = 0; j < numberColumns; j++) { if (saveLower[j] != lower[j]) solver->setColLower(j, saveLower[j]); if (saveUpper[j] != upper[j]) solver->setColUpper(j, saveUpper[j]); } } // If objective goes above certain amount we can set bound int jInt = back[iColumn]; newLower[jInt] = upperValue; if (choice.finishedDown) objLower[jInt] = choice.downMovement + objectiveValue_; else objLower[jInt] = objectiveValue_; newUpper[jInt] = lowerValue; if (choice.finishedUp) objUpper[jInt] = choice.upMovement + objectiveValue_; else objUpper[jInt] = objectiveValue_; objMin = CoinMin(CoinMin(objLower[jInt], objUpper[jInt]), objMin); /* End of evaluation for this candidate variable. Possibilities are: * Both sides below cutoff; this variable is a candidate for branching. * Both sides infeasible or above the objective cutoff: no further action here. Break from the evaluation loop and assume the node will be purged by the caller. * One side below cutoff: Install the branch (i.e., fix the variable). Break from the evaluation loop and assume the node will be reoptimised by the caller. */ if (choice.upMovement < 1.0e100) { if (choice.downMovement < 1.0e100) { objMax = CoinMax(CoinMax(objLower[jInt], objUpper[jInt]), objMax); // In case solution coming in was odd choice.upMovement = CoinMax(0.0, choice.upMovement); choice.downMovement = CoinMax(0.0, choice.downMovement); // feasible - model->messageHandler()->message(CBC_STRONG, *model->messagesPointer()) << iObject << iColumn << choice.downMovement << choice.numIntInfeasDown << choice.upMovement << choice.numIntInfeasUp << value << CoinMessageEol; } else { // up feasible, down infeasible if (!satisfied) needResolve = true; choice.fix = 1; numberToFix++; saveLower[iColumn] = upperValue; solver->setColLower(iColumn, upperValue); } } else { if (choice.downMovement < 1.0e100) { // down feasible, up infeasible if (!satisfied) needResolve = true; choice.fix = -1; numberToFix++; saveUpper[iColumn] = lowerValue; solver->setColUpper(iColumn, lowerValue); } else { // neither side feasible COIN_DETAIL_PRINT(printf("Both infeasible for choice %d sequence %d\n", i, model->object(choice.objectNumber)->columnNumber())); delete ws; ws = NULL; //solver->writeMps("bad"); numberToFix = -1; delete choice.possibleBranch; choice.possibleBranch = NULL; break; } } delete choice.possibleBranch; if (numberIterationsAllowed <= 0) break; //printf("obj %d, col %d, down %g up %g value %g\n",iObject,iColumn, // choice.downMovement,choice.upMovement,value); } COIN_DETAIL_PRINT(printf("Best possible solution %g, can fix more if solution of %g found - looked at %d variables in %d iterations\n", objMin, objMax, iDo, model->numberAnalyzeIterations() - numberIterationsAllowed)); model->setNumberAnalyzeIterations(numberIterationsAllowed); // Delete the snapshot solver->unmarkHotStart(); // back to normal solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit); // restore basis solver->setWarmStart(ws); delete ws; delete [] sort; delete [] whichObject; delete [] saveLower; delete [] saveUpper; delete [] back; // restore solution solver->setColSolution(saveSolution); # ifdef COIN_HAS_CLP if (osiclp) osiclp->setSpecialOptions(saveClpOptions); # endif model->reserveCurrentSolution(saveSolution); delete [] saveSolution; if (needResolve) solver->resolve(); return numberToFix; } CbcNode::CbcNode(const CbcNode & rhs) : CoinTreeNode(rhs) { #ifdef CHECK_NODE printf("CbcNode %x Constructor from rhs %x\n", this, &rhs); #endif if (rhs.nodeInfo_) nodeInfo_ = rhs.nodeInfo_->clone(); else nodeInfo_ = NULL; objectiveValue_ = rhs.objectiveValue_; guessedObjectiveValue_ = rhs.guessedObjectiveValue_; sumInfeasibilities_ = rhs.sumInfeasibilities_; if (rhs.branch_) branch_ = rhs.branch_->clone(); else branch_ = NULL; depth_ = rhs.depth_; numberUnsatisfied_ = rhs.numberUnsatisfied_; nodeNumber_ = rhs.nodeNumber_; state_ = rhs.state_; if (nodeInfo_) assert ((state_&2) != 0); else assert ((state_&2) == 0); } CbcNode & CbcNode::operator=(const CbcNode & rhs) { if (this != &rhs) { delete nodeInfo_; if (rhs.nodeInfo_) nodeInfo_ = rhs.nodeInfo_->clone(); else nodeInfo_ = NULL; objectiveValue_ = rhs.objectiveValue_; guessedObjectiveValue_ = rhs.guessedObjectiveValue_; sumInfeasibilities_ = rhs.sumInfeasibilities_; if (rhs.branch_) branch_ = rhs.branch_->clone(); else branch_ = NULL, depth_ = rhs.depth_; numberUnsatisfied_ = rhs.numberUnsatisfied_; nodeNumber_ = rhs.nodeNumber_; state_ = rhs.state_; if (nodeInfo_) assert ((state_&2) != 0); else assert ((state_&2) == 0); } return *this; } CbcNode::~CbcNode () { #ifdef CHECK_NODE if (nodeInfo_) { printf("CbcNode %x Destructor nodeInfo %x (%d)\n", this, nodeInfo_, nodeInfo_->numberPointingToThis()); //assert(nodeInfo_->numberPointingToThis()>=0); } else { printf("CbcNode %x Destructor nodeInfo %x (?)\n", this, nodeInfo_); } #endif if (nodeInfo_) { // was if (nodeInfo_&&(state_&2)!=0) { nodeInfo_->nullOwner(); int numberToDelete = nodeInfo_->numberBranchesLeft(); // CbcNodeInfo * parent = nodeInfo_->parent(); //assert (nodeInfo_->numberPointingToThis()>0); if (nodeInfo_->decrement(numberToDelete) == 0 || (state_&2) == 0) { if ((state_&2) == 0) nodeInfo_->nullParent(); delete nodeInfo_; } else { //printf("node %x nodeinfo %x parent %x\n",this,nodeInfo_,nodeInfo_->parent()); // anyway decrement parent //if (parent) ///parent->decrement(1); } } delete branch_; } // Decrement active cut counts void CbcNode::decrementCuts(int change) { if (nodeInfo_) assert ((state_&2) != 0); else assert ((state_&2) == 0); if (nodeInfo_) { nodeInfo_->decrementCuts(change); } } void CbcNode::decrementParentCuts(CbcModel * model, int change) { if (nodeInfo_) assert ((state_&2) != 0); else assert ((state_&2) == 0); if (nodeInfo_) { nodeInfo_->decrementParentCuts(model, change); } } /* Initialize reference counts (numberPointingToThis, numberBranchesLeft_) in the attached nodeInfo_. */ void CbcNode::initializeInfo() { assert(nodeInfo_ && branch_) ; nodeInfo_->initializeInfo(branch_->numberBranches()); assert ((state_&2) != 0); assert (nodeInfo_->numberBranchesLeft() == branch_->numberBranchesLeft()); } // Nulls out node info void CbcNode::nullNodeInfo() { nodeInfo_ = NULL; // say not active state_ &= ~2; } int CbcNode::branch(OsiSolverInterface * solver) { double changeInGuessed; assert (nodeInfo_->numberBranchesLeft() == branch_->numberBranchesLeft()); if (!solver) changeInGuessed = branch_->branch(); else changeInGuessed = branch_->branch(solver); guessedObjectiveValue_ += changeInGuessed; //#define PRINTIT #ifdef PRINTIT int numberLeft = nodeInfo_->numberBranchesLeft(); CbcNodeInfo * parent = nodeInfo_->parent(); int parentNodeNumber = -1; CbcBranchingObject * object1 = dynamic_cast(branch_) ; //OsiObject * object = object1-> //int sequence = object->columnNumber); int id = -1; double value = 0.0; if (object1) { id = object1->variable(); value = object1->value(); } printf("id %d value %g objvalue %g\n", id, value, objectiveValue_); if (parent) parentNodeNumber = parent->nodeNumber(); printf("Node number %d, %s, way %d, depth %d, parent node number %d\n", nodeInfo_->nodeNumber(), (numberLeft == 2) ? "leftBranch" : "rightBranch", way(), depth_, parentNodeNumber); assert (parentNodeNumber != nodeInfo_->nodeNumber()); #endif return nodeInfo_->branchedOn(); } /* Active arm of the attached OsiBranchingObject. In the simplest instance, coded -1 for the down arm of the branch, +1 for the up arm. But see OsiBranchingObject::way() Use nodeInfo--.numberBranchesLeft_ to see how active Except that there is no OsiBranchingObject::way(), and this'll fail in any event because we have various OsiXXXBranchingObjects which aren't descended from CbcBranchingObjects. I think branchIndex() is the appropriate equivalent, but could be wrong. (lh, 061220) 071212: I'm finally getting back to cbc-generic and rescuing a lot of my annotation from branches/devel (which was killed in summer). I'm going to put back an assert(obj) just to see what happens. It's still present as of the most recent change to CbcNode (r833). 080104: Yep, we can arrive here with an OsiBranchingObject. Removed the assert, it's served its purpose. 080226: John finally noticed this problem and added a way() method to the OsiBranchingObject hierarchy. Removing my workaround. */ int CbcNode::way() const { if (branch_) { CbcBranchingObject * obj = dynamic_cast (branch_) ; if (obj) { return obj->way(); } else { OsiTwoWayBranchingObject * obj2 = dynamic_cast (branch_) ; assert (obj2); return obj2->way(); } } else { return 0; } } /* Create a branching object for the node The routine scans the object list of the model and selects a set of unsatisfied objects as candidates for branching. The candidates are evaluated, and an appropriate branch object is installed. The numberPassesLeft is decremented to stop fixing one variable each time and going on and on (e.g. for stock cutting, air crew scheduling) If evaluation determines that an object is monotone or infeasible, the routine returns immediately. In the case of a monotone object, the branch object has already been called to modify the model. Return value:
  • 0: A branching object has been installed
  • -1: A monotone object was discovered
  • -2: An infeasible object was discovered
Branch state:
  • -1: start
  • -1: A monotone object was discovered
  • -2: An infeasible object was discovered
*/ int CbcNode::chooseOsiBranch (CbcModel * model, CbcNode * lastNode, OsiBranchingInformation * usefulInfo, int branchState) { int returnStatus = 0; if (lastNode) depth_ = lastNode->depth_ + 1; else depth_ = 0; OsiSolverInterface * solver = model->solver(); objectiveValue_ = solver->getObjValue() * solver->getObjSense(); usefulInfo->objectiveValue_ = objectiveValue_; usefulInfo->depth_ = depth_; const double * saveInfoSol = usefulInfo->solution_; double * saveSolution = new double[solver->getNumCols()]; memcpy(saveSolution, solver->getColSolution(), solver->getNumCols()*sizeof(double)); usefulInfo->solution_ = saveSolution; OsiChooseVariable * choose = model->branchingMethod()->chooseMethod(); int numberUnsatisfied = -1; if (branchState < 0) { // initialize // initialize sum of "infeasibilities" sumInfeasibilities_ = 0.0; numberUnsatisfied = choose->setupList(usefulInfo, true); numberUnsatisfied_ = numberUnsatisfied; branchState = 0; if (numberUnsatisfied_ < 0) { // infeasible delete [] saveSolution; return -2; } } // unset best int best = -1; choose->setBestObjectIndex(-1); if (numberUnsatisfied) { if (branchState > 0 || !choose->numberOnList()) { // we need to return at once - don't do strong branching or anything if (choose->numberOnList() || !choose->numberStrong()) { best = choose->candidates()[0]; choose->setBestObjectIndex(best); } else { // nothing on list - need to try again - keep any solution numberUnsatisfied = choose->setupList(usefulInfo, false); numberUnsatisfied_ = numberUnsatisfied; if (numberUnsatisfied) { best = choose->candidates()[0]; choose->setBestObjectIndex(best); } } } else { // carry on with strong branching or whatever int returnCode = choose->chooseVariable(solver, usefulInfo, true); // update number of strong iterations etc model->incrementStrongInfo(choose->numberStrongDone(), choose->numberStrongIterations(), returnCode == -1 ? 0 : choose->numberStrongFixed(), returnCode == -1); if (returnCode > 1) { // has fixed some returnStatus = -1; } else if (returnCode == -1) { // infeasible returnStatus = -2; } else if (returnCode == 0) { // normal returnStatus = 0; numberUnsatisfied = 1; } else { // ones on list satisfied - double check numberUnsatisfied = choose->setupList(usefulInfo, false); numberUnsatisfied_ = numberUnsatisfied; if (numberUnsatisfied) { best = choose->candidates()[0]; choose->setBestObjectIndex(best); } } } } delete branch_; branch_ = NULL; guessedObjectiveValue_ = COIN_DBL_MAX;//objectiveValue_; // for now if (!returnStatus) { if (numberUnsatisfied) { // create branching object const OsiObject * obj = model->solver()->object(choose->bestObjectIndex()); //const OsiSolverInterface * solver = usefulInfo->solver_; branch_ = obj->createBranch(model->solver(), usefulInfo, obj->whichWay()); } } usefulInfo->solution_ = saveInfoSol; delete [] saveSolution; // may have got solution if (choose->goodSolution() && model->problemFeasibility()->feasible(model, -1) >= 0) { // yes double objValue = choose->goodObjectiveValue(); model->setBestSolution(CBC_STRONGSOL, objValue, choose->goodSolution()) ; model->setLastHeuristic(NULL); model->incrementUsed(choose->goodSolution()); choose->clearGoodSolution(); } return returnStatus; } int CbcNode::chooseClpBranch (CbcModel * model, CbcNode * lastNode) { assert(lastNode); depth_ = lastNode->depth_ + 1; delete branch_; branch_ = NULL; OsiSolverInterface * solver = model->solver(); //double saveObjectiveValue = solver->getObjValue(); //double objectiveValue = CoinMax(solver->getObjSense()*saveObjectiveValue,objectiveValue_); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); // point to useful information OsiBranchingInformation usefulInfo = model->usefulInformation(); // and modify usefulInfo.depth_ = depth_; int i; //bool beforeSolution = model->getSolutionCount()==0; int numberObjects = model->numberObjects(); int numberColumns = model->getNumCols(); double * saveUpper = new double[numberColumns]; double * saveLower = new double[numberColumns]; // Save solution in case heuristics need good solution later double * saveSolution = new double[numberColumns]; memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double)); model->reserveCurrentSolution(saveSolution); for (i = 0; i < numberColumns; i++) { saveLower[i] = lower[i]; saveUpper[i] = upper[i]; } // Save basis CoinWarmStart * ws = solver->getWarmStart(); numberUnsatisfied_ = 0; // initialize sum of "infeasibilities" sumInfeasibilities_ = 0.0; // Note looks as if off end (hidden one) OsiObject * object = model->modifiableObject(numberObjects); CbcGeneralDepth * thisOne = dynamic_cast (object); assert (thisOne); OsiClpSolverInterface * clpSolver = dynamic_cast (solver); assert (clpSolver); ClpSimplex * simplex = clpSolver->getModelPtr(); int preferredWay; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); if (thisOne->whichSolution() >= 0) { ClpNode * nodeInfo=NULL; if ((model->moreSpecialOptions()&33554432)==0) { nodeInfo = thisOne->nodeInfo(thisOne->whichSolution()); nodeInfo->applyNode(simplex, 2); } else { // from diving CbcSubProblem ** nodes = reinterpret_cast (model->temporaryPointer()); assert (nodes); int numberDo=thisOne->numberNodes()-1; for (int iNode=0;iNodeapply(solver,1); nodes[numberDo]->apply(solver,9+16); } int saveLogLevel = simplex->logLevel(); simplex->setLogLevel(0); simplex->dual(); simplex->setLogLevel(saveLogLevel); double cutoff = model->getCutoff(); bool goodSolution = true; if (simplex->status()) { //simplex->writeMps("bad7.mps",2); if (nodeInfo) { if (nodeInfo->objectiveValue() > cutoff - 1.0e-2) goodSolution = false; else assert (!simplex->status()); } else { // debug diving assert (!simplex->status()); } } if (goodSolution) { double newObjectiveValue = solver->getObjSense() * solver->getObjValue(); // See if integer solution int numInf; int numInf2; bool gotSol = model->feasibleSolution(numInf, numInf2); if (!gotSol) { COIN_DETAIL_PRINT(printf("numinf %d\n", numInf)); double * sol = simplex->primalColumnSolution(); for (int i = 0; i < numberColumns; i++) { if (simplex->isInteger(i)) { double value = floor(sol[i] + 0.5); if (fabs(value - sol[i]) > 1.0e-7) { COIN_DETAIL_PRINT(printf("%d value %g\n", i, sol[i])); if (fabs(value - sol[i]) < 1.0e-3) { sol[i] = value; } } } } simplex->writeMps("bad8.mps", 2); bool gotSol = model->feasibleSolution(numInf, numInf2); if (!gotSol) assert (gotSol); } model->setBestSolution(CBC_STRONGSOL, newObjectiveValue, solver->getColSolution()) ; model->setLastHeuristic(NULL); model->incrementUsed(solver->getColSolution()); } } // restore bounds { for (int j = 0; j < numberColumns; j++) { if (saveLower[j] != lower[j]) solver->setColLower(j, saveLower[j]); if (saveUpper[j] != upper[j]) solver->setColUpper(j, saveUpper[j]); } } // restore basis solver->setWarmStart(ws); delete ws; int anyAction; //#define CHECK_PATH #ifdef CHECK_PATH extern int gotGoodNode_Z; if (gotGoodNode_Z >= 0) printf("good node %d %g\n", gotGoodNode_Z, infeasibility); #endif if (infeasibility > 0.0) { if (infeasibility == COIN_DBL_MAX) { anyAction = -2; // infeasible } else { branch_ = thisOne->createCbcBranch(solver, &usefulInfo, preferredWay); if (branch_) { // Set to first one (and change when re-pushing) CbcGeneralBranchingObject * branch = dynamic_cast (branch_); branch->state(objectiveValue_, sumInfeasibilities_, numberUnsatisfied_, 0); branch->setNode(this); anyAction = 0; } else { anyAction = -2; // mark as infeasible } } } else { anyAction = -1; } #ifdef CHECK_PATH gotGoodNode_Z = -1; #endif // Set guessed solution value guessedObjectiveValue_ = objectiveValue_ + 1.0e-5; delete [] saveLower; delete [] saveUpper; // restore solution solver->setColSolution(saveSolution); delete [] saveSolution; return anyAction; } /* Double checks in case node can change its mind! Returns objective value Can change objective etc */ double CbcNode::checkIsCutoff(double cutoff) { branch_->checkIsCutoff(cutoff); return objectiveValue_; } Cbc-2.8.12/src/CbcCompareDefault.cpp0000644000076600007660000002670212131315050015545 0ustar coincoin// $Id: CbcCompareDefault.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCompareActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CbcMessage.hpp" #include "CbcModel.hpp" #include "CbcTree.hpp" #include "CbcCompareActual.hpp" #include "CoinError.hpp" #include "CbcCompareDefault.hpp" /** Default Constructor */ CbcCompareDefault::CbcCompareDefault () : CbcCompareBase(), weight_(-1.0), saveWeight_(0.0), cutoff_(COIN_DBL_MAX), bestPossible_(-COIN_DBL_MAX), numberSolutions_(0), treeSize_(0), breadthDepth_(5), startNodeNumber_(-1), afterNodeNumber_(-1), setupForDiving_(false) { test_ = this; } // Constructor with weight CbcCompareDefault::CbcCompareDefault (double weight) : CbcCompareBase(), weight_(weight) , saveWeight_(0.0), cutoff_(COIN_DBL_MAX), bestPossible_(-COIN_DBL_MAX), numberSolutions_(0), treeSize_(0), breadthDepth_(5), startNodeNumber_(-1), afterNodeNumber_(-1), setupForDiving_(false) { test_ = this; } // Copy constructor CbcCompareDefault::CbcCompareDefault ( const CbcCompareDefault & rhs) : CbcCompareBase(rhs) { weight_ = rhs.weight_; saveWeight_ = rhs.saveWeight_; cutoff_ = rhs.cutoff_; bestPossible_ = rhs.bestPossible_; numberSolutions_ = rhs.numberSolutions_; treeSize_ = rhs.treeSize_; breadthDepth_ = rhs.breadthDepth_; startNodeNumber_ = rhs.startNodeNumber_; afterNodeNumber_ = rhs.afterNodeNumber_; setupForDiving_ = rhs.setupForDiving_ ; } // Clone CbcCompareBase * CbcCompareDefault::clone() const { return new CbcCompareDefault(*this); } // Assignment operator CbcCompareDefault & CbcCompareDefault::operator=( const CbcCompareDefault & rhs) { if (this != &rhs) { CbcCompareBase::operator=(rhs); weight_ = rhs.weight_; saveWeight_ = rhs.saveWeight_; cutoff_ = rhs.cutoff_; bestPossible_ = rhs.bestPossible_; numberSolutions_ = rhs.numberSolutions_; treeSize_ = rhs.treeSize_; breadthDepth_ = rhs.breadthDepth_; startNodeNumber_ = rhs.startNodeNumber_; afterNodeNumber_ = rhs.afterNodeNumber_; setupForDiving_ = rhs.setupForDiving_ ; } return *this; } // Destructor CbcCompareDefault::~CbcCompareDefault () { } // Returns true if y better than x bool CbcCompareDefault::test (CbcNode * x, CbcNode * y) { if (startNodeNumber_ >= 0) { // Diving int nX = x->nodeNumber(); int nY = y->nodeNumber(); if (nY == startNodeNumber_) return true; else if (nX == startNodeNumber_) return false; if (nX >= afterNodeNumber_ && nY < afterNodeNumber_) return false; else if (nY >= afterNodeNumber_ && nX < afterNodeNumber_) return true; // treat as depth first int depthX = x->depth(); int depthY = y->depth(); if (depthX != depthY) { return depthX < depthY; } else { double weight = CoinMax(weight_, 1.0e-9); double testX = x->objectiveValue() + weight * x->numberUnsatisfied(); double testY = y->objectiveValue() + weight * y->numberUnsatisfied(); if (testX != testY) return testX > testY; else return equalityTest(x, y); // so ties will be broken in consistent manner } } if (!weight_) { double testX = x->objectiveValue() + 1.0e-9 * x->numberUnsatisfied(); double testY = y->objectiveValue() + 1.0e-9 * y->numberUnsatisfied(); if (testX != testY) return testX > testY; else return equalityTest(x, y); // so ties will be broken in consistent manner } //weight_=0.0; if ((weight_ == -1.0 && (y->depth() > breadthDepth_ && x->depth() > breadthDepth_)) || weight_ == -3.0 || weight_ == -2.0) { int adjust = (weight_ == -3.0) ? 10000 : 0; // before solution /*printf("x %d %d %g, y %d %d %g\n", x->numberUnsatisfied(),x->depth(),x->objectiveValue(), y->numberUnsatisfied(),y->depth(),y->objectiveValue()); */ if (x->numberUnsatisfied() > y->numberUnsatisfied() + adjust) { return true; } else if (x->numberUnsatisfied() < y->numberUnsatisfied() - adjust) { return false; } else { int depthX = x->depth(); int depthY = y->depth(); if (depthX != depthY) return depthX < depthY; else return equalityTest(x, y); // so ties will be broken in consistent manner } } else { // always choose *greatest* depth if both <= breadthDepth_ otherwise <= breadthDepth_ if just one int depthX = x->depth(); int depthY = y->depth(); /*if ((depthX==4&&depthY==5)||(depthX==5&&depthY==4)) printf("X %x depth %d, Y %x depth %d, breadth %d\n", x,depthX,y,depthY,breadthDepth_);*/ if (depthX <= breadthDepth_ || depthY <= breadthDepth_) { if (depthX <= breadthDepth_ && depthY <= breadthDepth_) { if (depthX != depthY) { return depthX < depthY; } } else { assert (depthX != depthY) ; return depthX < depthY; } } // after solution ? #define THRESH2 0.999 #define TRY_THIS 0 #if TRY_THIS==0 double weight = CoinMax(weight_, 1.0e-9); double testX = x->objectiveValue() + weight * x->numberUnsatisfied(); double testY = y->objectiveValue() + weight * y->numberUnsatisfied(); #elif TRY_THIS==1 /* compute what weight would have to be to hit target then reverse sign as large weight good */ double target = (1.0 - THRESH2) * bestPossible_ + THRESH2 * cutoff_; double weight; weight = (target - x->objectiveValue()) / static_cast(x->numberUnsatisfied()); double testX = - weight; weight = (target - y->objectiveValue()) / static_cast(y->numberUnsatisfied()); double testY = - weight; #elif TRY_THIS==2 // Use estimates double testX = x->guessedObjectiveValue(); double testY = y->guessedObjectiveValue(); #elif TRY_THIS==3 #define THRESH 0.95 // Use estimates double testX = x->guessedObjectiveValue(); double testY = y->guessedObjectiveValue(); if (x->objectiveValue() - bestPossible_ > THRESH*(cutoff_ - bestPossible_)) testX *= 2.0; // make worse if (y->objectiveValue() - bestPossible_ > THRESH*(cutoff_ - bestPossible_)) testY *= 2.0; // make worse #endif if (testX != testY) return testX > testY; else return equalityTest(x, y); // so ties will be broken in consistent manner } } /* Change the weight attached to unsatisfied integer variables, unless it's fairly early on in the search and all solutions to date are heuristic. */ bool CbcCompareDefault::newSolution(CbcModel * model, double objectiveAtContinuous, int numberInfeasibilitiesAtContinuous) { cutoff_ = model->getCutoff(); if (model->getSolutionCount() == model->getNumberHeuristicSolutions() && model->getSolutionCount() < 5 && model->getNodeCount() < 500) return (false) ; // solution was got by rounding // set to get close to this solution double costPerInteger = (model->getObjValue() - objectiveAtContinuous) / static_cast (numberInfeasibilitiesAtContinuous); weight_ = 0.95 * costPerInteger; saveWeight_ = 0.95 * weight_; numberSolutions_++; //if (numberSolutions_>5) //weight_ =0.0; // this searches on objective return (true) ; } // This allows method to change behavior bool CbcCompareDefault::every1000Nodes(CbcModel * model, int numberNodes) { #ifdef JJF_ZERO // was if (numberNodes > 10000) weight_ = 0.0; // this searches on objective // get size of tree treeSize_ = model->tree()->size(); #else double saveWeight = weight_; int numberNodes1000 = numberNodes / 1000; if (numberNodes > 10000) { weight_ = 0.0; // this searches on objective // but try a bit of other stuff if ((numberNodes1000 % 4) == 1) weight_ = saveWeight_; } else if (numberNodes == 1000 && weight_ == -2.0) { weight_ = -1.0; // Go to depth first } // get size of tree treeSize_ = model->tree()->size(); if (treeSize_ > 10000) { int n1 = model->solver()->getNumRows() + model->solver()->getNumCols(); int n2 = model->numberObjects(); double size = n1 * 0.1 + n2 * 2.0; // set weight to reduce size most of time if (treeSize_*(size + 100.0) > 5.0e7) weight_ = -3.0; else if ((numberNodes1000 % 4) == 0 && treeSize_*size > 1.0e6) weight_ = -1.0; else if ((numberNodes1000 % 4) == 1) weight_ = 0.0; else weight_ = saveWeight_; } #endif //return numberNodes==11000; // resort if first time return (weight_ != saveWeight); } // Start dive void CbcCompareDefault::startDive(CbcModel * model) { // Get best - using ? criterion double saveWeight = weight_; weight_ = 0.5 * saveWeight_; //0.0; // Switch off to get best startNodeNumber_ = -1; afterNodeNumber_ = -1; CbcNode * best = model->tree()->bestAlternate(); startNodeNumber_ = best->nodeNumber(); // send signal to setComparison setupForDiving_ = true ; /* TODO (review when fixing cleanDive and setComparison) Both afterNodeNumber_ and weight_ must not change after setComparison is invoked, as that will change the behaviour of test(). I replaced the overload on afterNodeNumber_ (magic number -2) with a boolean. Weight_ is more problematic. Either it's correct before calling setComparison, or it needs to be cut from the tie-breaking part of test() during a dive, or there needs to be a new attribute to save and restore it around the dive. Otherwise heap checks fail in debug builds with Visual Studio. Given that weight_ was restored immediately after the call to setComparison, there should be no change in behaviour in terms of calls to test(). -- lh, 100921 -- */ afterNodeNumber_ = model->tree()->maximumNodeNumber(); weight_ = saveWeight ; // redo tree model->tree()->setComparison(*this); setupForDiving_ = false ; } // Clean up dive void CbcCompareDefault::cleanDive() { if (setupForDiving_ == false) { // switch off startNodeNumber_ = -1; afterNodeNumber_ = -1; } } // Create C++ lines to get to current state void CbcCompareDefault::generateCpp( FILE * fp) { CbcCompareDefault other; fprintf(fp, "0#include \"CbcCompareActual.hpp\"\n"); fprintf(fp, "3 CbcCompareDefault compare;\n"); if (weight_ != other.weight_) fprintf(fp, "3 compare.setWeight(%g);\n", weight_); fprintf(fp, "3 cbcModel->setNodeComparison(compare);\n"); } Cbc-2.8.12/src/CbcModel.cpp0000644000076600007660000263524312372200415013727 0ustar coincoin/* $Id: CbcModel.cpp 2056 2014-08-11 17:44:45Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" #include //#define CBC_DEBUG 1 //#define CHECK_CUT_COUNTS //#define CHECK_NODE //#define CHECK_NODE_FULL //#define NODE_LOG //#define GLOBAL_CUTS_JUST_POINTERS #ifdef CGL_DEBUG_GOMORY extern int gomory_try; #endif #include #include #include #ifdef COIN_HAS_CLP // include Presolve from Clp #include "ClpPresolve.hpp" #include "OsiClpSolverInterface.hpp" #include "ClpNode.hpp" #include "ClpDualRowDantzig.hpp" #include "ClpSimplexPrimal.hpp" #endif #include "CbcEventHandler.hpp" #include "OsiSolverInterface.hpp" #include "OsiAuxInfo.hpp" #include "OsiSolverBranch.hpp" #include "OsiChooseVariable.hpp" #include "CoinWarmStartBasis.hpp" #include "CoinPackedMatrix.hpp" #include "CoinHelperFunctions.hpp" #include "CbcBranchActual.hpp" #include "CbcBranchDynamic.hpp" #include "CbcHeuristic.hpp" #include "CbcHeuristicFPump.hpp" #include "CbcHeuristicRINS.hpp" #include "CbcHeuristicDive.hpp" #include "CbcModel.hpp" #include "CbcTreeLocal.hpp" #include "CbcStatistics.hpp" #include "CbcStrategy.hpp" #include "CbcMessage.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" #include "OsiRowCutDebugger.hpp" #include "OsiCuts.hpp" #include "CbcCountRowCut.hpp" #include "CbcCutGenerator.hpp" #include "CbcFeasibilityBase.hpp" #include "CbcFathom.hpp" #include "CbcFullNodeInfo.hpp" // include Probing #include "CglProbing.hpp" #include "CglGomory.hpp" #include "CglTwomir.hpp" // include preprocessing #include "CglPreProcess.hpp" #include "CglDuplicateRow.hpp" #include "CglStored.hpp" #include "CglClique.hpp" #include "CoinTime.hpp" #include "CoinMpsIO.hpp" #include "CbcCompareActual.hpp" #include "CbcTree.hpp" // This may be dummy #include "CbcThread.hpp" /* Various functions local to CbcModel.cpp */ static void * doRootCbcThread(void * voidInfo); namespace { //------------------------------------------------------------------- // Returns the greatest common denominator of two // positive integers, a and b, found using Euclid's algorithm //------------------------------------------------------------------- static int gcd(int a, int b) { int remainder = -1; // make sure a<=b (will always remain so) if (a > b) { // Swap a and b int temp = a; a = b; b = temp; } // if zero then gcd is nonzero (zero may occur in rhs of packed) if (!a) { if (b) { return b; } else { printf("**** gcd given two zeros!!\n"); abort(); } } while (remainder) { remainder = b % a; b = a; a = remainder; } return b; } #ifdef CHECK_NODE_FULL /* Routine to verify that tree linkage is correct. The invariant that is tested is reference count = (number of actual references) + (number of branches left) The routine builds a set of paired arrays, info and count, by traversing the tree. Each CbcNodeInfo is recorded in info, and the number of times it is referenced (via the parent field) is recorded in count. Then a final check is made to see if the numberPointingToThis_ field agrees. */ void verifyTreeNodes (const CbcTree * branchingTree, const CbcModel &model) { if (model.getNodeCount() == 661) return; printf("*** CHECKING tree after %d nodes\n", model.getNodeCount()) ; int j ; int nNodes = branchingTree->size() ; # define MAXINFO 1000 int *count = new int [MAXINFO] ; CbcNodeInfo **info = new CbcNodeInfo*[MAXINFO] ; int nInfo = 0 ; /* Collect all CbcNodeInfo objects in info, by starting from each live node and traversing back to the root. Nodes in the live set should have unexplored branches remaining. TODO: The `while (nodeInfo)' loop could be made to break on reaching a common ancester (nodeInfo is found in info[k]). Alternatively, the check could change to signal an error if nodeInfo is not found above a common ancestor. */ for (j = 0 ; j < nNodes ; j++) { CbcNode *node = branchingTree->nodePointer(j) ; if (!node) continue; CbcNodeInfo *nodeInfo = node->nodeInfo() ; int change = node->nodeInfo()->numberBranchesLeft() ; assert(change) ; while (nodeInfo) { int k ; for (k = 0 ; k < nInfo ; k++) { if (nodeInfo == info[k]) break ; } if (k == nInfo) { assert(nInfo < MAXINFO) ; nInfo++ ; info[k] = nodeInfo ; count[k] = 0 ; } nodeInfo = nodeInfo->parent() ; } } /* Walk the info array. For each nodeInfo, look up its parent in info and increment the corresponding count. */ for (j = 0 ; j < nInfo ; j++) { CbcNodeInfo *nodeInfo = info[j] ; nodeInfo = nodeInfo->parent() ; if (nodeInfo) { int k ; for (k = 0 ; k < nInfo ; k++) { if (nodeInfo == info[k]) break ; } assert (k < nInfo) ; count[k]++ ; } } /* Walk the info array one more time and check that the invariant holds. The number of references (numberPointingToThis()) should equal the sum of the number of actual references (held in count[]) plus the number of potential references (unexplored branches, numberBranchesLeft()). */ for (j = 0; j < nInfo; j++) { CbcNodeInfo * nodeInfo = info[j] ; if (nodeInfo) { int k ; for (k = 0; k < nInfo; k++) if (nodeInfo == info[k]) break ; printf("Nodeinfo %x - %d left, %d count\n", nodeInfo, nodeInfo->numberBranchesLeft(), nodeInfo->numberPointingToThis()) ; assert(nodeInfo->numberPointingToThis() == count[k] + nodeInfo->numberBranchesLeft()) ; } } delete [] count ; delete [] info ; return ; } #endif /* CHECK_NODE_FULL */ #ifdef CHECK_CUT_COUNTS /* Routine to verify that cut reference counts are correct. */ void verifyCutCounts (const CbcTree * branchingTree, CbcModel &model) { printf("*** CHECKING cuts after %d nodes\n", model.getNodeCount()) ; int j ; int nNodes = branchingTree->size() ; /* cut.tempNumber_ exists for the purpose of doing this verification. Clear it in all cuts. We traverse the tree by starting from each live node and working back to the root. At each CbcNodeInfo, check for cuts. */ for (j = 0 ; j < nNodes ; j++) { CbcNode *node = branchingTree->nodePointer(j) ; CbcNodeInfo * nodeInfo = node->nodeInfo() ; assert (node->nodeInfo()->numberBranchesLeft()) ; while (nodeInfo) { int k ; for (k = 0 ; k < nodeInfo->numberCuts() ; k++) { CbcCountRowCut *cut = nodeInfo->cuts()[k] ; if (cut) cut->tempNumber_ = 0; } nodeInfo = nodeInfo->parent() ; } } /* Walk the live set again, this time collecting the list of cuts in use at each node. addCuts1 will collect the cuts in model.addedCuts_. Take into account that when we recreate the basis for a node, we compress out the slack cuts. */ for (j = 0 ; j < nNodes ; j++) { CoinWarmStartBasis *debugws = model.getEmptyBasis() ; CbcNode *node = branchingTree->nodePointer(j) ; CbcNodeInfo *nodeInfo = node->nodeInfo(); int change = node->nodeInfo()->numberBranchesLeft() ; printf("Node %d %x (info %x) var %d way %d obj %g", j, node, node->nodeInfo(), node->columnNumber(), node->way(), node->objectiveValue()) ; model.addCuts1(node, debugws) ; int i ; int numberRowsAtContinuous = model.numberRowsAtContinuous() ; CbcCountRowCut **addedCuts = model.addedCuts() ; for (i = 0 ; i < model.currentNumberCuts() ; i++) { CoinWarmStartBasis::Status status = debugws->getArtifStatus(i + numberRowsAtContinuous) ; if (status != CoinWarmStartBasis::basic && addedCuts[i]) { addedCuts[i]->tempNumber_ += change ; } } while (nodeInfo) { nodeInfo = nodeInfo->parent() ; if (nodeInfo) printf(" -> %x", nodeInfo); } printf("\n") ; delete debugws ; } /* The moment of truth: We've tallied up the references by direct scan of the search tree. Check for agreement with the count in the cut. TODO: Rewrite to check and print mismatch only when tempNumber_ == 0? */ for (j = 0 ; j < nNodes ; j++) { CbcNode *node = branchingTree->nodePointer(j) ; CbcNodeInfo *nodeInfo = node->nodeInfo(); while (nodeInfo) { int k ; for (k = 0 ; k < nodeInfo->numberCuts() ; k++) { CbcCountRowCut *cut = nodeInfo->cuts()[k] ; if (cut && cut->tempNumber_ >= 0) { if (cut->tempNumber_ != cut->numberPointingToThis()) printf("mismatch %x %d %x %d %d\n", nodeInfo, k, cut, cut->tempNumber_, cut->numberPointingToThis()) ; else printf(" match %x %d %x %d %d\n", nodeInfo, k, cut, cut->tempNumber_, cut->numberPointingToThis()) ; cut->tempNumber_ = -1 ; } } nodeInfo = nodeInfo->parent() ; } } return ; } #endif /* CHECK_CUT_COUNTS */ #ifdef CHECK_CUT_SIZE /* Routine to verify that cut reference counts are correct. */ void verifyCutSize (const CbcTree * branchingTree, CbcModel &model) { int j ; int nNodes = branchingTree->size() ; int totalCuts = 0; /* cut.tempNumber_ exists for the purpose of doing this verification. Clear it in all cuts. We traverse the tree by starting from each live node and working back to the root. At each CbcNodeInfo, check for cuts. */ for (j = 0 ; j < nNodes ; j++) { CbcNode *node = branchingTree->nodePointer(j) ; CbcNodeInfo * nodeInfo = node->nodeInfo() ; assert (node->nodeInfo()->numberBranchesLeft()) ; while (nodeInfo) { totalCuts += nodeInfo->numberCuts(); nodeInfo = nodeInfo->parent() ; } } printf("*** CHECKING cuts (size) after %d nodes - %d cuts\n", model.getNodeCount(), totalCuts) ; return ; } #endif /* CHECK_CUT_SIZE */ } /* End unnamed namespace for CbcModel.cpp */ void CbcModel::analyzeObjective () /* Try to find a minimum change in the objective function. The first scan checks that there are no continuous variables with non-zero coefficients, and grabs the largest objective coefficient associated with an unfixed integer variable. The second scan attempts to scale up the objective coefficients to a point where they are sufficiently close to integer that we can pretend they are integer, and calculate a gcd over the coefficients of interest. This will be the minimum increment for the scaled coefficients. The final action is to scale the increment back for the original coefficients and install it, if it's better than the existing value. John's note: We could do better than this. John's second note - apologies for changing s to z */ { const double *objective = getObjCoefficients() ; const double *lower = getColLower() ; const double *upper = getColUpper() ; /* Scan continuous and integer variables to see if continuous are cover or network with integral rhs. */ double continuousMultiplier = 1.0; double * coeffMultiplier = NULL; double largestObj = 0.0; double smallestObj = COIN_DBL_MAX; { const double *rowLower = getRowLower() ; const double *rowUpper = getRowUpper() ; int numberRows = solver_->getNumRows() ; double * rhs = new double [numberRows]; memset(rhs, 0, numberRows*sizeof(double)); int iColumn; int numberColumns = solver_->getNumCols() ; // Column copy of matrix int problemType = -1; const double * element = solver_->getMatrixByCol()->getElements(); const int * row = solver_->getMatrixByCol()->getIndices(); const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts(); const int * columnLength = solver_->getMatrixByCol()->getVectorLengths(); int numberInteger = 0; int numberIntegerObj = 0; int numberGeneralIntegerObj = 0; int numberIntegerWeight = 0; int numberContinuousObj = 0; double cost = COIN_DBL_MAX; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] == lower[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; rhs[iRow] += lower[iColumn] * element[j]; } } else { double objValue = objective[iColumn]; if (solver_->isInteger(iColumn)) numberInteger++; if (objValue) { if (!solver_->isInteger(iColumn)) { numberContinuousObj++; } else { largestObj = CoinMax(largestObj, fabs(objValue)); smallestObj = CoinMin(smallestObj, fabs(objValue)); numberIntegerObj++; if (cost == COIN_DBL_MAX) cost = objValue; else if (cost != objValue) cost = -COIN_DBL_MAX; int gap = static_cast (upper[iColumn] - lower[iColumn]); if (gap > 1) { numberGeneralIntegerObj++; numberIntegerWeight += gap; } } } } } int iType = 0; if (!numberContinuousObj && numberIntegerObj <= 5 && numberIntegerWeight <= 100 && numberIntegerObj*3 < numberObjects_ && !parentModel_ && solver_->getNumRows() > 100) iType = 1 + 4 + ((moreSpecialOptions_&536870912)==0) ? 2 : 0; else if (!numberContinuousObj && numberIntegerObj <= 100 && numberIntegerObj*5 < numberObjects_ && numberIntegerWeight <= 100 && !parentModel_ && solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX) iType = 4 + ((moreSpecialOptions_&536870912)==0) ? 2 : 0; else if (!numberContinuousObj && numberIntegerObj <= 100 && numberIntegerObj*5 < numberObjects_ && !parentModel_ && solver_->getNumRows() > 100 && cost != -COIN_DBL_MAX) iType = 8; int iTest = getMaximumNodes(); if (iTest >= 987654320 && iTest < 987654330 && numberObjects_ && !parentModel_) { iType = iTest - 987654320; printf("Testing %d integer variables out of %d objects (%d integer) have cost of %g - %d continuous\n", numberIntegerObj, numberObjects_, numberInteger, cost, numberContinuousObj); if (iType == 9) exit(77); if (numberContinuousObj) iType = 0; } //if (!numberContinuousObj&&(numberIntegerObj<=5||cost!=-COIN_DBL_MAX)&& //numberIntegerObj*3getNumRows()>100) { if (iType) { /* A) put high priority on (if none) B) create artificial objective (if clp) */ int iPriority = -1; for (int i = 0; i < numberObjects_; i++) { int k = object_[i]->priority(); if (iPriority == -1) iPriority = k; else if (iPriority != k) iPriority = -2; } bool branchOnSatisfied = ((iType & 1) != 0); bool createFake = ((iType & 2) != 0); bool randomCost = ((iType & 4) != 0); if (iPriority >= 0) { char general[200]; if (cost == -COIN_DBL_MAX) { sprintf(general, "%d integer variables out of %d objects (%d integer) have costs - high priority", numberIntegerObj, numberObjects_, numberInteger); } else if (cost == COIN_DBL_MAX) { sprintf(general, "No integer variables out of %d objects (%d integer) have costs", numberObjects_, numberInteger); branchOnSatisfied = false; } else { sprintf(general, "%d integer variables out of %d objects (%d integer) have cost of %g - high priority", numberIntegerObj, numberObjects_, numberInteger, cost); } messageHandler()->message(CBC_GENERAL, messages()) << general << CoinMessageEol ; sprintf(general, "branch on satisfied %c create fake objective %c random cost %c", branchOnSatisfied ? 'Y' : 'N', createFake ? 'Y' : 'N', randomCost ? 'Y' : 'N'); messageHandler()->message(CBC_GENERAL, messages()) << general << CoinMessageEol ; // switch off clp type branching // no ? fastNodeDepth_ = -1; int highPriority = (branchOnSatisfied) ? -999 : 100; for (int i = 0; i < numberObjects_; i++) { CbcSimpleInteger * thisOne = dynamic_cast (object_[i]); object_[i]->setPriority(1000); if (thisOne) { int iColumn = thisOne->columnNumber(); if (objective[iColumn]) thisOne->setPriority(highPriority); } } } #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver && createFake) { // Create artificial objective to be used when all else fixed int numberColumns = clpSolver->getNumCols(); double * fakeObj = new double [numberColumns]; // Column copy const CoinPackedMatrix * matrixByCol = clpSolver->getMatrixByCol(); //const double * element = matrixByCol.getElements(); //const int * row = matrixByCol.getIndices(); //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); const int * columnLength = matrixByCol->getVectorLengths(); const double * solution = clpSolver->getColSolution(); #ifdef JJF_ZERO int nAtBound = 0; for (int i = 0; i < numberColumns; i++) { double lowerValue = lower[i]; double upperValue = upper[i]; if (clpSolver->isInteger(i)) { double lowerValue = lower[i]; double upperValue = upper[i]; double value = solution[i]; if (value < lowerValue + 1.0e-6 || value > upperValue - 1.0e-6) nAtBound++; } } #endif /* Generate a random objective function for problems where the given objective function is not terribly useful. (Nearly feasible, single integer variable, that sort of thing. */ CoinDrand48(true, 1234567); for (int i = 0; i < numberColumns; i++) { double lowerValue = lower[i]; double upperValue = upper[i]; double value = (randomCost) ? ceil((CoinDrand48() + 0.5) * 1000) : i + 1 + columnLength[i] * 1000; value *= 0.001; //value += columnLength[i]; if (lowerValue > -1.0e5 || upperValue < 1.0e5) { if (fabs(lowerValue) > fabs(upperValue)) value = - value; if (clpSolver->isInteger(i)) { double solValue = solution[i]; // Better to add in 0.5 or 1.0?? if (solValue < lowerValue + 1.0e-6) value = fabs(value) + 0.5; //fabs(value*1.5); else if (solValue > upperValue - 1.0e-6) value = -fabs(value) - 0.5; //-fabs(value*1.5); } } else { value = 0.0; } fakeObj[i] = value; } // pass to solver clpSolver->setFakeObjective(fakeObj); delete [] fakeObj; } #endif } else if (largestObj < smallestObj*5.0 && !parentModel_ && !numberContinuousObj && !numberGeneralIntegerObj && numberIntegerObj*2 < numberColumns) { // up priorities on costed int iPriority = -1; for (int i = 0; i < numberObjects_; i++) { int k = object_[i]->priority(); if (iPriority == -1) iPriority = k; else if (iPriority != k) iPriority = -2; } if (iPriority >= 100) { #ifdef CLP_INVESTIGATE printf("Setting variables with obj to high priority\n"); #endif for (int i = 0; i < numberObjects_; i++) { CbcSimpleInteger * obj = dynamic_cast (object_[i]) ; if (obj) { int iColumn = obj->columnNumber(); if (objective[iColumn]) object_[i]->setPriority(iPriority - 1); } } } } int iRow; for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] > -1.0e20 && fabs(rowLower[iRow] - rhs[iRow] - floor(rowLower[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) { continuousMultiplier = 0.0; break; } if (rowUpper[iRow] < 1.0e20 && fabs(rowUpper[iRow] - rhs[iRow] - floor(rowUpper[iRow] - rhs[iRow] + 0.5)) > 1.0e-10) { continuousMultiplier = 0.0; break; } // set rhs to limiting value if (rowLower[iRow] != rowUpper[iRow]) { if (rowLower[iRow] > -1.0e20) { if (rowUpper[iRow] < 1.0e20) { // no good continuousMultiplier = 0.0; break; } else { rhs[iRow] = rowLower[iRow] - rhs[iRow]; if (problemType < 0) problemType = 3; // set cover else if (problemType != 3) problemType = 4; } } else { rhs[iRow] = rowUpper[iRow] - rhs[iRow]; if (problemType < 0) problemType = 1; // set partitioning <= else if (problemType != 1) problemType = 4; } } else { rhs[iRow] = rowUpper[iRow] - rhs[iRow]; if (problemType < 0) problemType = 3; // set partitioning == else if (problemType != 2) problemType = 2; } if (fabs(rhs[iRow] - 1.0) > 1.0e-12) problemType = 4; } if (continuousMultiplier) { // 1 network, 2 cover, 4 negative cover int possible = 7; bool unitRhs = true; // See which rows could be set cover for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { double value = element[j]; if (value == 1.0) { } else if (value == -1.0) { rhs[row[j]] = -0.5; } else { rhs[row[j]] = -COIN_DBL_MAX; } } } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8) { if (!isInteger(iColumn)) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; double rhsValue = 0.0; // 1 all ones, -1 all -1s, 2 all +- 1, 3 no good int type = 0; for (CoinBigIndex j = start; j < end; j++) { double value = element[j]; if (fabs(value) != 1.0) { type = 3; break; } else if (value == 1.0) { if (!type) type = 1; else if (type != 1) type = 2; } else { if (!type) type = -1; else if (type != -1) type = 2; } int iRow = row[j]; if (rhs[iRow] == -COIN_DBL_MAX) { type = 3; break; } else if (rhs[iRow] == -0.5) { // different values unitRhs = false; } else if (rhsValue) { if (rhsValue != rhs[iRow]) unitRhs = false; } else { rhsValue = rhs[iRow]; } } // if no elements OK if (type == 3) { // no good possible = 0; break; } else if (type == 2) { if (end - start > 2) { // no good possible = 0; break; } else { // only network possible &= 1; if (!possible) break; } } else if (type == 1) { // only cover possible &= 2; if (!possible) break; } else if (type == -1) { // only negative cover possible &= 4; if (!possible) break; } } } } if ((possible == 2 || possible == 4) && !unitRhs) { #if COIN_DEVELOP>1 printf("XXXXXX Continuous all +1 but different rhs\n"); #endif possible = 0; } // may be all integer if (possible != 7) { if (!possible) continuousMultiplier = 0.0; else if (possible == 1) continuousMultiplier = 1.0; else continuousMultiplier = 0.0; // 0.5 was incorrect; #if COIN_DEVELOP>1 if (continuousMultiplier) printf("XXXXXX multiplier of %g\n", continuousMultiplier); #endif if (continuousMultiplier == 0.5) { coeffMultiplier = new double [numberColumns]; bool allOne = true; for (iColumn = 0; iColumn < numberColumns; iColumn++) { coeffMultiplier[iColumn] = 1.0; if (upper[iColumn] > lower[iColumn] + 1.0e-8) { if (!isInteger(iColumn)) { CoinBigIndex start = columnStart[iColumn]; int iRow = row[start]; double value = rhs[iRow]; assert (value >= 0.0); if (value != 0.0 && value != 1.0) allOne = false; coeffMultiplier[iColumn] = 0.5 * value; } } } if (allOne) { // back to old way delete [] coeffMultiplier; coeffMultiplier = NULL; } } } else { // all integer problemType_ = problemType; #if COIN_DEVELOP>1 printf("Problem type is %d\n", problemType_); #endif } } // But try again if (continuousMultiplier < 1.0) { memset(rhs, 0, numberRows*sizeof(double)); int * count = new int [numberRows]; memset(count, 0, numberRows*sizeof(int)); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; if (upper[iColumn] == lower[iColumn]) { for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; rhs[iRow] += lower[iColumn] * element[j]; } } else if (solver_->isInteger(iColumn)) { for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; if (fabs(element[j] - floor(element[j] + 0.5)) > 1.0e-10) rhs[iRow] = COIN_DBL_MAX; } } else { for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; count[iRow]++; if (fabs(element[j]) != 1.0) rhs[iRow] = COIN_DBL_MAX; } } } // now look at continuous bool allGood = true; double direction = solver_->getObjSense() ; int numberObj = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn]) { double objValue = objective[iColumn] * direction; if (objValue && !solver_->isInteger(iColumn)) { numberObj++; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; if (objValue > 0.0) { // wants to be as low as possible if (lower[iColumn] < -1.0e10 || fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) { allGood = false; break; } else if (upper[iColumn] < 1.0e10 && fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) { allGood = false; break; } bool singletonRow = true; bool equality = false; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; if (count[iRow] > 1) singletonRow = false; else if (rowLower[iRow] == rowUpper[iRow]) equality = true; double rhsValue = rhs[iRow]; double lowerValue = rowLower[iRow]; double upperValue = rowUpper[iRow]; if (rhsValue < 1.0e20) { if (lowerValue > -1.0e20) lowerValue -= rhsValue; if (upperValue < 1.0e20) upperValue -= rhsValue; } if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10 || fabs(element[j]) != 1.0) { // no good allGood = false; break; } if (element[j] > 0.0) { if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) { // no good allGood = false; break; } } else { if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) { // no good allGood = false; break; } } } if (!singletonRow && end > start + 1 && !equality) allGood = false; if (!allGood) break; } else { // wants to be as high as possible if (upper[iColumn] > 1.0e10 || fabs(upper[iColumn] - floor(upper[iColumn] + 0.5)) > 1.0e-10) { allGood = false; break; } else if (lower[iColumn] > -1.0e10 && fabs(lower[iColumn] - floor(lower[iColumn] + 0.5)) > 1.0e-10) { allGood = false; break; } bool singletonRow = true; bool equality = false; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; if (count[iRow] > 1) singletonRow = false; else if (rowLower[iRow] == rowUpper[iRow]) equality = true; double rhsValue = rhs[iRow]; double lowerValue = rowLower[iRow]; double upperValue = rowUpper[iRow]; if (rhsValue < 1.0e20) { if (lowerValue > -1.0e20) lowerValue -= rhsValue; if (upperValue < 1.0e20) upperValue -= rhsValue; } if (fabs(rhsValue) > 1.0e20 || fabs(rhsValue - floor(rhsValue + 0.5)) > 1.0e-10 || fabs(element[j]) != 1.0) { // no good allGood = false; break; } if (element[j] < 0.0) { if (lowerValue > -1.0e20 && fabs(lowerValue - floor(lowerValue + 0.5)) > 1.0e-10) { // no good allGood = false; break; } } else { if (upperValue < 1.0e20 && fabs(upperValue - floor(upperValue + 0.5)) > 1.0e-10) { // no good allGood = false; break; } } } if (!singletonRow && end > start + 1 && !equality) allGood = false; if (!allGood) break; } } } } delete [] count; if (allGood) { #if COIN_DEVELOP>1 if (numberObj) printf("YYYY analysis says all continuous with costs will be integer\n"); #endif continuousMultiplier = 1.0; } } delete [] rhs; } /* Take a first scan to see if there are unfixed continuous variables in the objective. If so, the minimum objective change could be arbitrarily small. Also pick off the maximum coefficient of an unfixed integer variable. If the objective is found to contain only integer variables, set the fathoming discipline to strict. */ double maximumCost = 0.0 ; //double trueIncrement=0.0; int iColumn ; int numberColumns = getNumCols() ; double scaleFactor = 1.0; // due to rhs etc /* Original model did not have integer bounds. */ if ((specialOptions_&65536) == 0) { /* be on safe side (later look carefully as may be able to to get 0.5 say if bounds are multiples of 0.5 */ for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8) { double value; value = fabs(lower[iColumn]); if (floor(value + 0.5) != value) { scaleFactor = CoinMin(scaleFactor, 0.5); if (floor(2.0*value + 0.5) != 2.0*value) { scaleFactor = CoinMin(scaleFactor, 0.25); if (floor(4.0*value + 0.5) != 4.0*value) { scaleFactor = 0.0; } } } value = fabs(upper[iColumn]); if (floor(value + 0.5) != value) { scaleFactor = CoinMin(scaleFactor, 0.5); if (floor(2.0*value + 0.5) != 2.0*value) { scaleFactor = CoinMin(scaleFactor, 0.25); if (floor(4.0*value + 0.5) != 4.0*value) { scaleFactor = 0.0; } } } } } } bool possibleMultiple = continuousMultiplier != 0.0 && scaleFactor != 0.0 ; if (possibleMultiple) { for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8) { maximumCost = CoinMax(maximumCost, fabs(objective[iColumn])) ; } } } setIntParam(CbcModel::CbcFathomDiscipline, possibleMultiple) ; /* If a nontrivial increment is possible, try and figure it out. We're looking for gcd(c) for all c that are coefficients of unfixed integer variables. Since the c might not be integers, try and inflate them sufficiently that they look like integers (and we'll deflate the gcd later). 2520.0 is used as it is a nice multiple of 2,3,5,7 */ if (possibleMultiple && maximumCost) { int increment = 0 ; double multiplier = 2520.0 ; while (10.0*multiplier*maximumCost < 1.0e8) multiplier *= 10.0 ; int bigIntegers = 0; // Count of large costs which are integer for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8) { double objValue = fabs(objective[iColumn]); if (!isInteger(iColumn)) { if (!coeffMultiplier) objValue *= continuousMultiplier; else objValue *= coeffMultiplier[iColumn]; } if (objValue) { double value = objValue * multiplier ; if (value < 2.1e9) { int nearest = static_cast (floor(value + 0.5)) ; if (fabs(value - floor(value + 0.5)) > 1.0e-8) { increment = 0 ; break ; } else if (!increment) { increment = nearest ; } else { increment = gcd(increment, nearest) ; } } else { // large value - may still be multiple of 1.0 if (fabs(objValue - floor(objValue + 0.5)) > 1.0e-8) { increment = 0; break; } else { bigIntegers++; } } } } } delete [] coeffMultiplier; /* If the increment beats the current value for objective change, install it. */ if (increment) { double value = increment ; double cutoff = getDblParam(CbcModel::CbcCutoffIncrement) ; if (bigIntegers) { // allow for 1.0 increment = gcd(increment, static_cast (multiplier)); value = increment; } value /= multiplier ; value *= scaleFactor; //trueIncrement=CoinMax(cutoff,value);; if (value*0.999 > cutoff) { messageHandler()->message(CBC_INTEGERINCREMENT, messages()) << value << CoinMessageEol ; setDblParam(CbcModel::CbcCutoffIncrement, CoinMax(value*0.999,value-1.0e-4)) ; } } } return ; } /* saveModel called (carved out of) BranchandBound */ void CbcModel::saveModel(OsiSolverInterface * saveSolver, double * checkCutoffForRestart, bool * feasible) { if (saveSolver && (specialOptions_&32768) != 0) { // See if worth trying reduction *checkCutoffForRestart = getCutoff(); bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() && (*checkCutoffForRestart < 1.0e20); int numberColumns = getNumCols(); if (tryNewSearch) { #ifdef CLP_INVESTIGATE printf("after %d nodes, cutoff %g - looking\n", numberNodes_, getCutoff()); #endif saveSolver->resolve(); double direction = saveSolver->getObjSense() ; double gap = *checkCutoffForRestart - saveSolver->getObjValue() * direction ; double tolerance; saveSolver->getDblParam(OsiDualTolerance, tolerance) ; if (gap <= 0.0) gap = tolerance; gap += 100.0 * tolerance; double integerTolerance = getDblParam(CbcIntegerTolerance) ; const double *lower = saveSolver->getColLower() ; const double *upper = saveSolver->getColUpper() ; const double *solution = saveSolver->getColSolution() ; const double *reducedCost = saveSolver->getReducedCost() ; int numberFixed = 0 ; int numberFixed2 = 0; for (int i = 0 ; i < numberIntegers_ ; i++) { int iColumn = integerVariable_[i] ; double djValue = direction * reducedCost[iColumn] ; if (upper[iColumn] - lower[iColumn] > integerTolerance) { if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) { saveSolver->setColUpper(iColumn, lower[iColumn]) ; numberFixed++ ; } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) { saveSolver->setColLower(iColumn, upper[iColumn]) ; numberFixed++ ; } } else { numberFixed2++; } } #ifdef COIN_DEVELOP /* We're debugging. (specialOptions 1) */ if ((specialOptions_&1) != 0) { const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger() ; if (debugger) { printf("Contains optimal\n") ; OsiSolverInterface * temp = saveSolver->clone(); const double * solution = debugger->optimalSolution(); const double *lower = temp->getColLower() ; const double *upper = temp->getColUpper() ; int n = temp->getNumCols(); for (int i = 0; i < n; i++) { if (temp->isInteger(i)) { double value = floor(solution[i] + 0.5); assert (value >= lower[i] && value <= upper[i]); temp->setColLower(i, value); temp->setColUpper(i, value); } } temp->writeMps("reduced_fix"); delete temp; saveSolver->writeMps("reduced"); } else { abort(); } } printf("Restart could fix %d integers (%d already fixed)\n", numberFixed + numberFixed2, numberFixed2); #endif numberFixed += numberFixed2; if (numberFixed*20 < numberColumns) tryNewSearch = false; } if (tryNewSearch) { // back to solver without cuts? OsiSolverInterface * solver2 = continuousSolver_->clone(); const double *lower = saveSolver->getColLower() ; const double *upper = saveSolver->getColUpper() ; for (int i = 0 ; i < numberIntegers_ ; i++) { int iColumn = integerVariable_[i] ; solver2->setColLower(iColumn, lower[iColumn]); solver2->setColUpper(iColumn, upper[iColumn]); } // swap delete saveSolver; saveSolver = solver2; double * newSolution = new double[numberColumns]; double objectiveValue = *checkCutoffForRestart; CbcSerendipity heuristic(*this); if (bestSolution_) heuristic.setInputSolution(bestSolution_, bestObjective_); heuristic.setFractionSmall(0.9); heuristic.setFeasibilityPumpOptions(1008013); // Use numberNodes to say how many are original rows heuristic.setNumberNodes(continuousSolver_->getNumRows()); #ifdef COIN_DEVELOP if (continuousSolver_->getNumRows() < saveSolver->getNumRows()) printf("%d rows added ZZZZZ\n", solver_->getNumRows() - continuousSolver_->getNumRows()); #endif int returnCode = heuristic.smallBranchAndBound(saveSolver, -1, newSolution, objectiveValue, *checkCutoffForRestart, "Reduce"); if (returnCode < 0) { #ifdef COIN_DEVELOP printf("Restart - not small enough to do search after fixing\n"); #endif delete [] newSolution; } else { if ((returnCode&1) != 0) { // increment number of solutions so other heuristics can test numberSolutions_++; numberHeuristicSolutions_++; lastHeuristic_ = NULL; setBestSolution(CBC_ROUNDING, objectiveValue, newSolution) ; } delete [] newSolution; *feasible = false; // stop search } #if 0 // probably not needed def CBC_THREAD if (master_) { lockThread(); if (parallelMode() > 0) { while (master_->waitForThreadsInTree(0)) { lockThread(); double dummyBest; tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ; //unlockThread(); } } master_->waitForThreadsInTree(2); delete master_; master_ = NULL; masterThread_ = NULL; } #endif } } } /* Adds integers, called from BranchandBound() */ void CbcModel::AddIntegers() { int numberColumns = continuousSolver_->getNumCols(); int numberRows = continuousSolver_->getNumRows(); int * del = new int [CoinMax(numberColumns, numberRows)]; int * original = new int [numberColumns]; int numberOriginalIntegers=numberIntegers_; char * possibleRow = new char [numberRows]; { const CoinPackedMatrix * rowCopy = continuousSolver_->getMatrixByRow(); const int * column = rowCopy->getIndices(); const int * rowLength = rowCopy->getVectorLengths(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const double * rowLower = continuousSolver_->getRowLower(); const double * rowUpper = continuousSolver_->getRowUpper(); const double * element = rowCopy->getElements(); for (int i = 0; i < numberRows; i++) { int nLeft = 0; bool possible = false; if (rowLower[i] < -1.0e20) { double value = rowUpper[i]; if (fabs(value - floor(value + 0.5)) < 1.0e-8) possible = true; } else if (rowUpper[i] > 1.0e20) { double value = rowLower[i]; if (fabs(value - floor(value + 0.5)) < 1.0e-8) possible = true; } else { double value = rowUpper[i]; if (rowLower[i] == rowUpper[i] && fabs(value - floor(value + 0.5)) < 1.0e-8) possible = true; } double allSame = (possible) ? 0.0 : -1.0; for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; double value = fabs(element[j]); if (continuousSolver_->isInteger(iColumn)) { if (value != 1.0) possible = false; } else { nLeft++; if (value>100.0) allSame=-1.0; // not safe if (!allSame) { allSame = value; } else if (allSame>0.0) { if (allSame!=value) allSame = -1.0; } } } if (nLeft == rowLength[i] && allSame > 0.0) possibleRow[i] = 2; else if (possible || !nLeft) possibleRow[i] = 1; else possibleRow[i] = 0; } } int nDel = 0; for (int i = 0; i < numberColumns; i++) { original[i] = i; if (continuousSolver_->isInteger(i)) del[nDel++] = i; } { // we must not exclude current best solution (rounding errors) // also not if large values const int * row = continuousSolver_->getMatrixByCol()->getIndices(); const CoinBigIndex * columnStart = continuousSolver_->getMatrixByCol()->getVectorStarts(); const int * columnLength = continuousSolver_->getMatrixByCol()->getVectorLengths(); const double * solution = continuousSolver_->getColSolution(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!continuousSolver_->isInteger(iColumn)) { double value = bestSolution_ ? bestSolution_[iColumn] : 0.0; double value2 = solution[iColumn]; if (fabs(value-floor(value+0.5))>1.0e-8 || fabs(value2)>1.0e3) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; possibleRow[iRow]=0; } } } } } int nExtra = 0; OsiSolverInterface * copy1 = continuousSolver_->clone(); int nPass = 0; while (nDel && nPass < 10) { nPass++; OsiSolverInterface * copy2 = copy1->clone(); int nLeft = 0; for (int i = 0; i < nDel; i++) original[del[i]] = -1; for (int i = 0; i < numberColumns; i++) { int kOrig = original[i]; if (kOrig >= 0) original[nLeft++] = kOrig; } assert (nLeft == numberColumns - nDel); copy2->deleteCols(nDel, del); numberColumns = copy2->getNumCols(); const CoinPackedMatrix * rowCopy = copy2->getMatrixByRow(); numberRows = rowCopy->getNumRows(); const int * column = rowCopy->getIndices(); const int * rowLength = rowCopy->getVectorLengths(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const double * rowLower = copy2->getRowLower(); const double * rowUpper = copy2->getRowUpper(); const double * element = rowCopy->getElements(); const CoinPackedMatrix * columnCopy = copy2->getMatrixByCol(); const int * columnLength = columnCopy->getVectorLengths(); nDel = 0; // Could do gcd stuff on ones with costs for (int i = 0; i < numberRows; i++) { if (!rowLength[i]) { del[nDel++] = i; } else if (possibleRow[i]) { if (rowLength[i] == 1) { int k = rowStart[i]; int iColumn = column[k]; if (!copy2->isInteger(iColumn)) { double mult = 1.0 / fabs(element[k]); if (rowLower[i] < -1.0e20) { // treat rhs as multiple of 1 unless elements all same double value = ((possibleRow[i]==2) ? rowUpper[i] : 1.0) * mult; if (fabs(value - floor(value + 0.5)) < 1.0e-8) { del[nDel++] = i; if (columnLength[iColumn] == 1) { copy2->setInteger(iColumn); int kOrig = original[iColumn]; setOptionalInteger(kOrig); } } } else if (rowUpper[i] > 1.0e20) { // treat rhs as multiple of 1 unless elements all same double value = ((possibleRow[i]==2) ? rowLower[i] : 1.0) * mult; if (fabs(value - floor(value + 0.5)) < 1.0e-8) { del[nDel++] = i; if (columnLength[iColumn] == 1) { copy2->setInteger(iColumn); int kOrig = original[iColumn]; setOptionalInteger(kOrig); } } } else { // treat rhs as multiple of 1 unless elements all same double value = ((possibleRow[i]==2) ? rowUpper[i] : 1.0) * mult; if (rowLower[i] == rowUpper[i] && fabs(value - floor(value + 0.5)) < 1.0e-8) { del[nDel++] = i; copy2->setInteger(iColumn); int kOrig = original[iColumn]; setOptionalInteger(kOrig); } } } } else { // only if all singletons bool possible = false; if (rowLower[i] < -1.0e20) { double value = rowUpper[i]; if (fabs(value - floor(value + 0.5)) < 1.0e-8) possible = true; } else if (rowUpper[i] > 1.0e20) { double value = rowLower[i]; if (fabs(value - floor(value + 0.5)) < 1.0e-8) possible = true; } else { double value = rowUpper[i]; if (rowLower[i] == rowUpper[i] && fabs(value - floor(value + 0.5)) < 1.0e-8) possible = true; } if (possible) { for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (columnLength[iColumn] != 1 || fabs(element[j]) != 1.0) { possible = false; break; } } if (possible) { for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) { int iColumn = column[j]; if (!copy2->isInteger(iColumn)) { copy2->setInteger(iColumn); int kOrig = original[iColumn]; setOptionalInteger(kOrig); } } del[nDel++] = i; } } } } } if (nDel) { copy2->deleteRows(nDel, del); // pack down possible int n=0; for (int i=0;i=0) possibleRow[n++]=possibleRow[i]; } } if (nDel != numberRows) { nDel = 0; for (int i = 0; i < numberColumns; i++) { if (copy2->isInteger(i)) { del[nDel++] = i; nExtra++; } } } else { nDel = 0; } delete copy1; copy1 = copy2->clone(); delete copy2; } // See if what's left is a network bool couldBeNetwork = false; if (copy1->getNumRows() && copy1->getNumCols()) { #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (copy1); if (false && clpSolver) { numberRows = clpSolver->getNumRows(); char * rotate = new char[numberRows]; int n = clpSolver->getModelPtr()->findNetwork(rotate, 1.0); delete [] rotate; #ifdef CLP_INVESTIGATE printf("INTA network %d rows out of %d\n", n, numberRows); #endif if (CoinAbs(n) == numberRows) { couldBeNetwork = true; for (int i = 0; i < numberRows; i++) { if (!possibleRow[i]) { couldBeNetwork = false; #ifdef CLP_INVESTIGATE printf("but row %d is bad\n", i); #endif break; } } } } else #endif { numberColumns = copy1->getNumCols(); numberRows = copy1->getNumRows(); const double * rowLower = copy1->getRowLower(); const double * rowUpper = copy1->getRowUpper(); couldBeNetwork = true; for (int i = 0; i < numberRows; i++) { if (rowLower[i] > -1.0e20 && fabs(rowLower[i] - floor(rowLower[i] + 0.5)) > 1.0e-12) { couldBeNetwork = false; break; } if (rowUpper[i] < 1.0e20 && fabs(rowUpper[i] - floor(rowUpper[i] + 0.5)) > 1.0e-12) { couldBeNetwork = false; break; } if (possibleRow[i]==0) { couldBeNetwork = false; break; } } if (couldBeNetwork) { const CoinPackedMatrix * matrixByCol = copy1->getMatrixByCol(); const double * element = matrixByCol->getElements(); //const int * row = matrixByCol->getIndices(); const CoinBigIndex * columnStart = matrixByCol->getVectorStarts(); const int * columnLength = matrixByCol->getVectorLengths(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; if (end > start + 2) { couldBeNetwork = false; break; } int type = 0; for (CoinBigIndex j = start; j < end; j++) { double value = element[j]; if (fabs(value) != 1.0) { couldBeNetwork = false; break; } else if (value == 1.0) { if ((type&1) == 0) type |= 1; else type = 7; } else if (value == -1.0) { if ((type&2) == 0) type |= 2; else type = 7; } } if (type > 3) { couldBeNetwork = false; break; } } } } } if (couldBeNetwork) { for (int i = 0; i < numberColumns; i++) setOptionalInteger(original[i]); } if (nExtra || couldBeNetwork) { numberColumns = copy1->getNumCols(); numberRows = copy1->getNumRows(); if (!numberColumns || !numberRows) { int numberColumns = solver_->getNumCols(); for (int i = 0; i < numberColumns; i++) assert(solver_->isInteger(i)); } #ifdef CLP_INVESTIGATE if (couldBeNetwork || nExtra) printf("INTA %d extra integers, %d left%s\n", nExtra, numberColumns, couldBeNetwork ? ", all network" : ""); #endif findIntegers(true, 2); convertToDynamic(); } #ifdef CLP_INVESTIGATE if (!couldBeNetwork && copy1->getNumCols() && copy1->getNumRows()) { printf("INTA %d rows and %d columns remain\n", copy1->getNumRows(), copy1->getNumCols()); if (copy1->getNumCols() < 200) { copy1->writeMps("moreint"); printf("INTA Written remainder to moreint.mps.gz %d rows %d cols\n", copy1->getNumRows(), copy1->getNumCols()); } } #endif delete copy1; delete [] del; delete [] original; delete [] possibleRow; // double check increment analyzeObjective(); // If any changes - tell code if(numberOriginalIntegersgetObjSense()<0.0); if (flipObjective) flipModel(); dblParam_[CbcOptimizationDirection] = 1.0; // was solver_->getObjSense(); strongInfo_[0] = 0; strongInfo_[1] = 0; strongInfo_[2] = 0; strongInfo_[3] = 0; strongInfo_[4] = 0; strongInfo_[5] = 0; strongInfo_[6] = 0; numberStrongIterations_ = 0; currentNode_ = NULL; // See if should do cuts old way if (parallelMode() < 0) { specialOptions_ |= 4096 + 8192; } else if (parallelMode() > 0) { specialOptions_ |= 4096; } int saveMoreSpecialOptions = moreSpecialOptions_; if (dynamic_cast (tree_)) specialOptions_ |= 4096 + 8192; #ifdef COIN_HAS_CLP { OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { // pass in disaster handler CbcDisasterHandler handler(this); clpSolver->passInDisasterHandler(&handler); // Initialise solvers seed (unless users says not) if ((specialOptions_&4194304)==0) clpSolver->getModelPtr()->setRandomSeed(1234567); #ifdef JJF_ZERO // reduce factorization frequency int frequency = clpSolver->getModelPtr()->factorizationFrequency(); clpSolver->getModelPtr()->setFactorizationFrequency(CoinMin(frequency, 120)); #endif } } #endif // original solver (only set if pre-processing) OsiSolverInterface * originalSolver = NULL; int numberOriginalObjects = numberObjects_; OsiObject ** originalObject = NULL; // Save whether there were any objects bool noObjects = (numberObjects_ == 0); // Set up strategies /* See if the user has supplied a strategy object and deal with it if present. The call to setupOther will set numberStrong_ and numberBeforeTrust_, and perform integer preprocessing, if requested. We need to hang on to a pointer to solver_. setupOther will assign a preprocessed solver to model, but will instruct assignSolver not to trash the existing one. */ if (strategy_) { // May do preprocessing originalSolver = solver_; strategy_->setupOther(*this); if (strategy_->preProcessState()) { // pre-processing done if (strategy_->preProcessState() < 0) { // infeasible (or unbounded) status_ = 0 ; if (!solver_->isProvenDualInfeasible()) { handler_->message(CBC_INFEAS, messages_) << CoinMessageEol ; secondaryStatus_ = 1; } else { handler_->message(CBC_UNBOUNDED, messages_) << CoinMessageEol ; secondaryStatus_ = 7; } originalContinuousObjective_ = COIN_DBL_MAX; if (flipObjective) flipModel(); return ; } else if (numberObjects_ && object_) { numberOriginalObjects = numberObjects_; // redo sequence numberIntegers_ = 0; int numberColumns = getNumCols(); int nOrig = originalSolver->getNumCols(); CglPreProcess * process = strategy_->process(); assert (process); const int * originalColumns = process->originalColumns(); // allow for cliques etc nOrig = CoinMax(nOrig, originalColumns[numberColumns-1] + 1); // try and redo debugger OsiRowCutDebugger * debugger = const_cast (solver_->getRowCutDebuggerAlways()); if (debugger) { if (numberColumns<=debugger->numberColumns()) debugger->redoSolution(numberColumns, originalColumns); else debugger=NULL; // no idea how to handle (SOS?) } // User-provided solution might have been best. Synchronise. if (bestSolution_) { // need to redo - in case no better found in BAB // just get integer part right for (int i = 0; i < numberColumns; i++) { int jColumn = originalColumns[i]; bestSolution_[i] = bestSolution_[jColumn]; } } originalObject = object_; // object number or -1 int * temp = new int[nOrig]; int iColumn; for (iColumn = 0; iColumn < nOrig; iColumn++) temp[iColumn] = -1; int iObject; int nNonInt = 0; for (iObject = 0; iObject < numberOriginalObjects; iObject++) { iColumn = originalObject[iObject]->columnNumber(); if (iColumn < 0) { nNonInt++; } else { temp[iColumn] = iObject; } } int numberNewIntegers = 0; int numberOldIntegers = 0; int numberOldOther = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; CbcSimpleInteger * obj = dynamic_cast (originalObject[iObject]) ; if (obj) numberOldIntegers++; else numberOldOther++; } else if (isInteger(iColumn)) { numberNewIntegers++; } } /* Allocate an array to hold the indices of the integer variables. Make a large enough array for all objects */ numberObjects_ = numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt; object_ = new OsiObject * [numberObjects_]; delete [] integerVariable_; integerVariable_ = new int [numberNewIntegers+numberOldIntegers]; /* Walk the variables again, filling in the indices and creating objects for the integer variables. Initially, the objects hold the index and upper & lower bounds. */ numberIntegers_ = 0; int n = originalColumns[numberColumns-1] + 1; int * backward = new int[n]; int i; for ( i = 0; i < n; i++) backward[i] = -1; for (i = 0; i < numberColumns; i++) backward[originalColumns[i]] = i; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; CbcSimpleInteger * obj = dynamic_cast (originalObject[iObject]) ; if (obj) { object_[numberIntegers_] = originalObject[iObject]->clone(); // redo ids etc //object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns); object_[numberIntegers_]->resetSequenceEtc(numberColumns, backward); integerVariable_[numberIntegers_++] = iColumn; } } else if (isInteger(iColumn)) { object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn); integerVariable_[numberIntegers_++] = iColumn; } } delete [] backward; numberObjects_ = numberIntegers_; // Now append other column stuff for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; CbcSimpleInteger * obj = dynamic_cast (originalObject[iObject]) ; if (!obj) { object_[numberObjects_] = originalObject[iObject]->clone(); // redo ids etc CbcObject * obj = dynamic_cast (object_[numberObjects_]) ; assert (obj); obj->redoSequenceEtc(this, numberColumns, originalColumns); numberObjects_++; } } } // now append non column stuff for (iObject = 0; iObject < numberOriginalObjects; iObject++) { iColumn = originalObject[iObject]->columnNumber(); if (iColumn < 0) { // already has column numbers changed object_[numberObjects_] = originalObject[iObject]->clone(); #ifdef JJF_ZERO // redo ids etc CbcObject * obj = dynamic_cast (object_[numberObjects_]) ; assert (obj); obj->redoSequenceEtc(this, numberColumns, originalColumns); #endif numberObjects_++; } } delete [] temp; if (!numberObjects_) handler_->message(CBC_NOINT, messages_) << CoinMessageEol ; } else { int numberColumns = getNumCols(); CglPreProcess * process = strategy_->process(); assert (process); const int * originalColumns = process->originalColumns(); // try and redo debugger OsiRowCutDebugger * debugger = const_cast (solver_->getRowCutDebuggerAlways()); if (debugger) debugger->redoSolution(numberColumns, originalColumns); } } else { //no preprocessing originalSolver = NULL; } strategy_->setupCutGenerators(*this); strategy_->setupHeuristics(*this); // Set strategy print level to models strategy_->setupPrinting(*this, handler_->logLevel()); } eventHappened_ = false; CbcEventHandler *eventHandler = getEventHandler() ; if (eventHandler) eventHandler->setModel(this); #define CLIQUE_ANALYSIS #ifdef CLIQUE_ANALYSIS // set up for probing // If we're doing clever stuff with cliques, additional info here. if (!parentModel_) probingInfo_ = new CglTreeProbingInfo(solver_); else probingInfo_ = NULL; #else probingInfo_ = NULL; #endif // Try for dominated columns if ((specialOptions_&64) != 0) { CglDuplicateRow dupcuts(solver_); dupcuts.setMode(2); CglStored * storedCuts = dupcuts.outDuplicates(solver_); if (storedCuts) { COIN_DETAIL_PRINT(printf("adding dup cuts\n")); addCutGenerator(storedCuts, 1, "StoredCuts from dominated", true, false, false, -200); } } if (!nodeCompare_) nodeCompare_ = new CbcCompareDefault();; // See if hot start wanted CbcCompareBase * saveCompare = NULL; // User supplied hotstart. Adapt for preprocessing. if (hotstartSolution_) { if (strategy_ && strategy_->preProcessState() > 0) { CglPreProcess * process = strategy_->process(); assert (process); int n = solver_->getNumCols(); const int * originalColumns = process->originalColumns(); // columns should be in order ... but double * tempS = new double[n]; for (int i = 0; i < n; i++) { int iColumn = originalColumns[i]; tempS[i] = hotstartSolution_[iColumn]; } delete [] hotstartSolution_; hotstartSolution_ = tempS; if (hotstartPriorities_) { int * tempP = new int [n]; for (int i = 0; i < n; i++) { int iColumn = originalColumns[i]; tempP[i] = hotstartPriorities_[iColumn]; } delete [] hotstartPriorities_; hotstartPriorities_ = tempP; } } saveCompare = nodeCompare_; // depth first nodeCompare_ = new CbcCompareDepth(); } if (!problemFeasibility_) problemFeasibility_ = new CbcFeasibilityBase(); # ifdef CBC_DEBUG std::string problemName ; solver_->getStrParam(OsiProbName, problemName) ; printf("Problem name - %s\n", problemName.c_str()) ; solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0) ; # endif /* Assume we're done, and see if we're proven wrong. */ status_ = 0 ; secondaryStatus_ = 0; phase_ = 0; /* Scan the variables, noting the integer variables. Create an CbcSimpleInteger object for each integer variable. */ findIntegers(false) ; // Say not dynamic pseudo costs ownership_ &= ~0x40000000; // If dynamic pseudo costs then do if (numberBeforeTrust_) convertToDynamic(); // Set up char array to say if integer (speed) delete [] integerInfo_; { int n = solver_->getNumCols(); integerInfo_ = new char [n]; for (int i = 0; i < n; i++) { if (solver_->isInteger(i)) integerInfo_[i] = 1; else integerInfo_[i] = 0; } } if (preferredWay_) { // set all unset ones for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) { CbcObject * obj = dynamic_cast (object_[iObject]) ; if (obj && !obj->preferredWay()) obj->setPreferredWay(preferredWay_); } } /* Ensure that objects on the lists of OsiObjects, heuristics, and cut generators attached to this model all refer to this model. */ synchronizeModel() ; if (!solverCharacteristics_) { OsiBabSolver * solverCharacteristics = dynamic_cast (solver_->getAuxiliaryInfo()); if (solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } else { // replace in solver OsiBabSolver defaultC; solver_->setAuxiliaryInfo(&defaultC); solverCharacteristics_ = dynamic_cast (solver_->getAuxiliaryInfo()); } } solverCharacteristics_->setSolver(solver_); // Set so we can tell we are in initial phase in resolve continuousObjective_ = -COIN_DBL_MAX ; /* Solve the relaxation. Apparently there are circumstances where this will be non-trivial --- i.e., we've done something since initialSolve that's trashed the solution to the continuous relaxation. */ /* Tell solver we are in Branch and Cut Could use last parameter for subtle differences */ solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; #ifdef COIN_HAS_CLP { OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { ClpSimplex * clpSimplex = clpSolver->getModelPtr(); if ((specialOptions_&32) == 0) { // take off names clpSimplex->dropNames(); } // no crunch if mostly continuous if ((clpSolver->specialOptions()&(1 + 8)) != (1 + 8)) { int numberColumns = solver_->getNumCols(); if (numberColumns > 1000 && numberIntegers_*4 < numberColumns) clpSolver->setSpecialOptions(clpSolver->specialOptions()&(~1)); } //#define NO_CRUNCH #ifdef NO_CRUNCH printf("TEMP switching off crunch\n"); int iOpt = clpSolver->specialOptions(); iOpt &= ~1; iOpt |= 65536; clpSolver->setSpecialOptions(iOpt); #endif } } #endif bool feasible; { // check int numberOdd = 0; for (int i = 0; i < numberObjects_; i++) { CbcSimpleInteger * obj = dynamic_cast (object_[i]) ; if (!obj) numberOdd++; } if (numberOdd) moreSpecialOptions_ |= 1073741824; } numberSolves_ = 0 ; // If NLP then we assume already solved outside branchAndbound if (!solverCharacteristics_->solverType() || solverCharacteristics_->solverType() == 4) { feasible = resolve(NULL, 0) != 0 ; } else { // pick up given status feasible = (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached()) ; } if (problemFeasibility_->feasible(this, 0) < 0) { feasible = false; // pretend infeasible } numberSavedSolutions_ = 0; int saveNumberStrong = numberStrong_; int saveNumberBeforeTrust = numberBeforeTrust_; /* If the linear relaxation of the root is infeasible, bail out now. Otherwise, continue with processing the root node. */ if (!feasible) { status_ = 0 ; if (!solver_->isProvenDualInfeasible()) { handler_->message(CBC_INFEAS, messages_) << CoinMessageEol ; secondaryStatus_ = 1; } else { handler_->message(CBC_UNBOUNDED, messages_) << CoinMessageEol ; secondaryStatus_ = 7; } originalContinuousObjective_ = COIN_DBL_MAX; solverCharacteristics_ = NULL; if (flipObjective) flipModel(); return ; } else if (!numberObjects_) { // nothing to do // Undo preprocessing performed during BaB. if (strategy_ && strategy_->preProcessState() > 0) { // undo preprocessing CglPreProcess * process = strategy_->process(); assert (process); int n = originalSolver->getNumCols(); if (bestSolution_) { delete [] bestSolution_; bestSolution_ = new double [n]; process->postProcess(*solver_); } strategy_->deletePreProcess(); // Solution now back in originalSolver delete solver_; solver_ = originalSolver; if (bestSolution_) { bestObjective_ = solver_->getObjValue() * solver_->getObjSense(); memcpy(bestSolution_, solver_->getColSolution(), n*sizeof(double)); } // put back original objects if there were any if (originalObject) { int iColumn; assert (ownObjects_); for (iColumn = 0; iColumn < numberObjects_; iColumn++) delete object_[iColumn]; delete [] object_; numberObjects_ = numberOriginalObjects; object_ = originalObject; delete [] integerVariable_; numberIntegers_ = 0; for (iColumn = 0; iColumn < n; iColumn++) { if (solver_->isInteger(iColumn)) numberIntegers_++; } integerVariable_ = new int[numberIntegers_]; numberIntegers_ = 0; for (iColumn = 0; iColumn < n; iColumn++) { if (solver_->isInteger(iColumn)) integerVariable_[numberIntegers_++] = iColumn; } } } if (flipObjective) flipModel(); solverCharacteristics_ = NULL; bestObjective_ = solver_->getObjValue() * solver_->getObjSense(); int numberColumns = solver_->getNumCols(); delete [] bestSolution_; bestSolution_ = new double[numberColumns]; CoinCopyN(solver_->getColSolution(), numberColumns, bestSolution_); return ; } /* See if we're using the Osi side of the branching hierarchy. If so, either convert existing CbcObjects to OsiObjects, or generate them fresh. In the first case, CbcModel owns the objects on the object_ list. In the second case, the solver holds the objects and object_ simply points to the solver's list. 080417 The conversion code here (the block protected by `if (obj)') cannot possibly be correct. On the Osi side, descent is OsiObject -> OsiObject2 -> all other Osi object classes. On the Cbc side, it's OsiObject -> CbcObject -> all other Cbc object classes. It's structurally impossible for any Osi object to descend from CbcObject. The only thing I can see is that this is really dead code, and object detection is now handled from the Osi side. */ // Convert to Osi if wanted //OsiBranchingInformation * persistentInfo = NULL; if (branchingMethod_ && branchingMethod_->chooseMethod()) { //persistentInfo = new OsiBranchingInformation(solver_); if (numberOriginalObjects) { for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) { CbcObject * obj = dynamic_cast (object_[iObject]) ; if (obj) { CbcSimpleInteger * obj2 = dynamic_cast (obj) ; if (obj2) { // back to Osi land object_[iObject] = obj2->osiObject(); delete obj; } else { OsiSimpleInteger * obj3 = dynamic_cast (obj) ; if (!obj3) { OsiSOS * obj4 = dynamic_cast (obj) ; if (!obj4) { CbcSOS * obj5 = dynamic_cast (obj) ; if (obj5) { // back to Osi land object_[iObject] = obj5->osiObject(solver_); } else { printf("Code up CbcObject type in Osi land\n"); abort(); } } } } } } // and add to solver //if (!solver_->numberObjects()) { solver_->addObjects(numberObjects_, object_); //} else { //if (solver_->numberObjects()!=numberOriginalObjects) { //printf("should have trapped that solver has objects before\n"); //abort(); //} //} } else { /* As of 080104, findIntegersAndSOS is misleading --- the default OSI implementation finds only integers. */ // do from solver deleteObjects(false); solver_->findIntegersAndSOS(false); numberObjects_ = solver_->numberObjects(); object_ = solver_->objects(); ownObjects_ = false; } branchingMethod_->chooseMethod()->setSolver(solver_); } // take off heuristics if have to (some do not work with SOS, for example) // object should know what's safe. { int numberOdd = 0; int numberSOS = 0; for (int i = 0; i < numberObjects_; i++) { if (!object_[i]->canDoHeuristics()) numberOdd++; CbcSOS * obj = dynamic_cast (object_[i]) ; if (obj) numberSOS++; } if (numberOdd) { if (numberHeuristics_) { int k = 0; for (int i = 0; i < numberHeuristics_; i++) { if (!heuristic_[i]->canDealWithOdd()) delete heuristic_[i]; else heuristic_[k++] = heuristic_[i]; } if (!k) { delete [] heuristic_; heuristic_ = NULL; } numberHeuristics_ = k; handler_->message(CBC_HEURISTICS_OFF, messages_) << numberOdd << CoinMessageEol ; } // If odd switch off AddIntegers specialOptions_ &= ~65536; } else if (numberSOS) { specialOptions_ |= 128; // say can do SOS in dynamic mode // switch off fast nodes for now fastNodeDepth_ = -1; moreSpecialOptions_ &= ~33554432; // no diving } if (numberThreads_ > 0) { // switch off fast nodes for now fastNodeDepth_ = -1; } } // Save objective (just so user can access it) originalContinuousObjective_ = solver_->getObjValue()* solver_->getObjSense(); bestPossibleObjective_ = originalContinuousObjective_; sumChangeObjective1_ = 0.0; sumChangeObjective2_ = 0.0; /* OsiRowCutDebugger knows an optimal answer for a subset of MIP problems. Assuming it recognises the problem, when called upon it will check a cut to see if it cuts off the optimal answer. */ // If debugger exists set specialOptions_ bit if (solver_->getRowCutDebuggerAlways()) { specialOptions_ |= 1; } # ifdef CBC_DEBUG if ((specialOptions_&1) == 0) solver_->activateRowCutDebugger(problemName.c_str()) ; if (solver_->getRowCutDebuggerAlways()) specialOptions_ |= 1; # endif /* Begin setup to process a feasible root node. */ bestObjective_ = CoinMin(bestObjective_, 1.0e50) ; if (!bestSolution_) { numberSolutions_ = 0 ; numberHeuristicSolutions_ = 0 ; } stateOfSearch_ = 0; // Everything is minimization { // needed to sync cutoffs double value ; solver_->getDblParam(OsiDualObjectiveLimit, value) ; dblParam_[CbcCurrentCutoff] = value * solver_->getObjSense(); } double cutoff = getCutoff() ; double direction = solver_->getObjSense() ; dblParam_[CbcOptimizationDirection] = direction; if (cutoff < 1.0e20 && direction < 0.0) messageHandler()->message(CBC_CUTOFF_WARNING1, messages()) << cutoff << -cutoff << CoinMessageEol ; if (cutoff > bestObjective_) cutoff = bestObjective_ ; setCutoff(cutoff) ; /* We probably already have a current solution, but just in case ... */ int numberColumns = getNumCols() ; if (!currentSolution_) currentSolution_ = new double[numberColumns] ; testSolution_ = currentSolution_; /* Create a copy of the solver, thus capturing the original (root node) constraint system (aka the continuous system). */ continuousSolver_ = solver_->clone() ; // add cutoff as constraint if wanted if (cutoffRowNumber_==-2) { if (!parentModel_) { int numberColumns=solver_->getNumCols(); double * obj = CoinCopyOfArray(solver_->getObjCoefficients(),numberColumns); int * indices = new int [numberColumns]; int n=0; for (int i=0;igetDblParam(OsiObjOffset, offset); cutoffRowNumber_ = solver_->getNumRows(); solver_->addRow(n,indices,obj,-COIN_DBL_MAX,CoinMin(cutoff,1.0e25)+offset); } else { // no objective! cutoffRowNumber_ = -1; } delete [] indices; delete [] obj; } else { // switch off cutoffRowNumber_ = -1; } } numberRowsAtContinuous_ = getNumRows() ; solver_->saveBaseModel(); /* Check the objective to see if we can deduce a nontrivial increment. If it's better than the current value for CbcCutoffIncrement, it'll be installed. */ if (solverCharacteristics_->reducedCostsAccurate()) analyzeObjective() ; { // may be able to change cutoff now double cutoff = getCutoff(); double increment = getDblParam(CbcModel::CbcCutoffIncrement) ; if (cutoff > bestObjective_ - increment) { cutoff = bestObjective_ - increment ; setCutoff(cutoff) ; } } #ifdef COIN_HAS_CLP // Possible save of pivot method ClpDualRowPivot * savePivotMethod = NULL; { // pass tolerance and increment to solver OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) clpSolver->setStuff(getIntegerTolerance(), getCutoffIncrement()); #ifdef CLP_RESOLVE if ((moreSpecialOptions_&1048576)!=0&&!parentModel_&&clpSolver) { resolveClp(clpSolver,0); } #endif } #endif /* Set up for cut generation. addedCuts_ holds the cuts which are relevant for the active subproblem. whichGenerator will be used to record the generator that produced a given cut. */ maximumWhich_ = 1000 ; delete [] whichGenerator_; whichGenerator_ = new int[maximumWhich_] ; memset(whichGenerator_, 0, maximumWhich_*sizeof(int)); maximumNumberCuts_ = 0 ; currentNumberCuts_ = 0 ; delete [] addedCuts_ ; addedCuts_ = NULL ; OsiObject ** saveObjects = NULL; maximumRows_ = numberRowsAtContinuous_; currentDepth_ = 0; workingBasis_.resize(maximumRows_, numberColumns); /* Set up an empty heap and associated data structures to hold the live set (problems which require further exploration). */ CbcCompareDefault * compareActual = dynamic_cast (nodeCompare_); if (compareActual) { compareActual->setBestPossible(direction*solver_->getObjValue()); compareActual->setCutoff(getCutoff()); #ifdef JJF_ZERO if (false && !numberThreads_ && !parentModel_) { printf("CbcTreeArray ? threads ? parentArray\n"); // Setup new style tree delete tree_; tree_ = new CbcTreeArray(); } #endif } tree_->setComparison(*nodeCompare_) ; /* Used to record the path from a node to the root of the search tree, so that we can then traverse from the root to the node when restoring a subproblem. */ maximumDepth_ = 10 ; delete [] walkback_ ; walkback_ = new CbcNodeInfo * [maximumDepth_] ; lastDepth_ = 0; delete [] lastNodeInfo_ ; lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ; delete [] lastNumberCuts_ ; lastNumberCuts_ = new int [maximumDepth_] ; maximumCuts_ = 100; lastNumberCuts2_ = 0; delete [] lastCut_; lastCut_ = new const OsiRowCut * [maximumCuts_]; /* Used to generate bound edits for CbcPartialNodeInfo. */ double * lowerBefore = new double [numberColumns] ; double * upperBefore = new double [numberColumns] ; /* Set up to run heuristics and generate cuts at the root node. The heavy lifting is hidden inside the calls to doHeuristicsAtRoot and solveWithCuts. To start, tell cut generators they can be a bit more aggressive at the root node. QUESTION: phase_ = 0 is documented as `initial solve', phase = 1 as `solve with cuts at root'. Is phase_ = 1 the correct indication when doHeurisiticsAtRoot is called to run heuristics outside of the main cut / heurisitc / reoptimise loop in solveWithCuts? Generate cuts at the root node and reoptimise. solveWithCuts does the heavy lifting. It will iterate a generate/reoptimise loop (including reduced cost fixing) until no cuts are generated, the change in objective falls off, or the limit on the number of rounds of cut generation is exceeded. At the end of all this, any cuts will be recorded in cuts and also installed in the solver's constraint system. We'll have reoptimised, and removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been adjusted accordingly). Tell cut generators they can be a bit more aggressive at root node TODO: Why don't we make a copy of the solution after solveWithCuts? TODO: If numberUnsatisfied == 0, don't we have a solution? */ phase_ = 1; int iCutGenerator; for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { // If parallel switch off global cuts if (numberThreads_) { generator_[iCutGenerator]->setGlobalCuts(false); generator_[iCutGenerator]->setGlobalCutsAtRoot(false); } CglCutGenerator * generator = generator_[iCutGenerator]->generator(); generator->setAggressiveness(generator->getAggressiveness() + 100); if (!generator->canDoGlobalCuts()) generator->setGlobalCuts(false); } OsiCuts cuts ; int anyAction = -1 ; numberOldActiveCuts_ = 0 ; numberNewCuts_ = 0 ; // Array to mark solution delete [] usedInSolution_; usedInSolution_ = new int[numberColumns]; CoinZeroN(usedInSolution_, numberColumns); /* For printing totals and for CbcNode (numberNodes_) */ numberIterations_ = 0 ; numberNodes_ = 0 ; numberNodes2_ = 0 ; maximumStatistics_ = 0; maximumDepthActual_ = 0; numberDJFixed_ = 0.0; if (!parentModel_) { if ((specialOptions_&262144) != 0) { // create empty stored cuts //storedRowCuts_ = new CglStored(solver_->getNumCols()); } else if ((specialOptions_&524288) != 0 && storedRowCuts_) { // tighten and set best solution // A) tight bounds on integer variables /* storedRowCuts_ are coming in from outside, probably for nonlinear. John was unsure about origin. */ const double * lower = solver_->getColLower(); const double * upper = solver_->getColUpper(); const double * tightLower = storedRowCuts_->tightLower(); const double * tightUpper = storedRowCuts_->tightUpper(); int nTightened = 0; for (int i = 0; i < numberIntegers_; i++) { int iColumn = integerVariable_[i]; if (tightLower[iColumn] > lower[iColumn]) { nTightened++; solver_->setColLower(iColumn, tightLower[iColumn]); } if (tightUpper[iColumn] < upper[iColumn]) { nTightened++; solver_->setColUpper(iColumn, tightUpper[iColumn]); } } if (nTightened) COIN_DETAIL_PRINT(printf("%d tightened by alternate cuts\n", nTightened)); if (storedRowCuts_->bestObjective() < bestObjective_) { // B) best solution double objValue = storedRowCuts_->bestObjective(); setBestSolution(CBC_SOLUTION, objValue, storedRowCuts_->bestSolution()) ; // Do heuristics // Allow RINS for (int i = 0; i < numberHeuristics_; i++) { CbcHeuristicRINS * rins = dynamic_cast (heuristic_[i]); if (rins) { rins->setLastNode(-100); } } } } } /* Run heuristics at the root. This is the only opportunity to run FPump; it will be removed from the heuristics list by doHeuristicsAtRoot. */ // See if multiple runs wanted CbcModel ** rootModels=NULL; if (!parentModel_&&multipleRootTries_%100) { double rootTimeCpu=CoinCpuTime(); double startTimeRoot=CoinGetTimeOfDay(); int numberRootThreads=1; /* undocumented fine tuning aabbcc where cc is number of tries bb if nonzero is number of threads aa if nonzero just do heuristics */ int numberModels = multipleRootTries_%100; #ifdef CBC_THREAD numberRootThreads = (multipleRootTries_/100)%100; if (!numberRootThreads) numberRootThreads=numberModels; #endif int otherOptions = (multipleRootTries_/10000)%100; rootModels = new CbcModel * [numberModels]; unsigned int newSeed = randomSeed_; if (newSeed==0) { double time = fabs(CoinGetTimeOfDay()); while (time>=COIN_INT_MAX) time *= 0.5; newSeed = static_cast(time); } else if (newSeed<0) { newSeed = 123456789; #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { newSeed += clpSolver->getModelPtr()->randomNumberGenerator()->getSeed(); } #endif } CoinWarmStartBasis * basis = dynamic_cast (solver_->getEmptyWarmStart()); int numberIterations=0; for (int i=0;isetNumberThreads(0); rootModels[i]->setMaximumNodes(otherOptions ? -1 : 0); rootModels[i]->setRandomSeed(newSeed+10000000*i); rootModels[i]->randomNumberGenerator()->setSeed(newSeed+50000000*i); rootModels[i]->setMultipleRootTries(0); // use seed rootModels[i]->setSpecialOptions(specialOptions_ |(4194304|8388608)); rootModels[i]->setMoreSpecialOptions(moreSpecialOptions_ & (~134217728)); rootModels[i]->solver_->setWarmStart(basis); #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (rootModels[i]->solver_); if (clpSolver) { ClpSimplex * simplex = clpSolver->getModelPtr(); if (defaultHandler_) simplex->setDefaultMessageHandler(); simplex->setRandomSeed(newSeed+20000000*i); simplex->allSlackBasis(); int logLevel=simplex->logLevel(); if (logLevel==1) simplex->setLogLevel(0); if (i!=0) { double random = simplex->randomNumberGenerator()->randomDouble(); int bias = static_cast(random*(numberIterations/4)); simplex->setMaximumIterations(numberIterations/2+bias); simplex->primal(); simplex->setMaximumIterations(COIN_INT_MAX); simplex->dual(); } else { simplex->primal(); numberIterations=simplex->numberIterations(); } simplex->setLogLevel(logLevel); clpSolver->setWarmStart(NULL); } #endif for (int j=0;jheuristic_[j]->setSeed(rootModels[i]->heuristic_[j]->getSeed()+100000000*i); for (int j=0;jgenerator_[j]->generator()->refreshSolver(rootModels[i]->solver_); } delete basis; #ifdef CBC_THREAD if (numberRootThreads==1) { #endif for (int iModel=0;iModelgetMaximumNodes()) { feasible=false; break; } } #ifdef CBC_THREAD } else { Coin_pthread_t * threadId = new Coin_pthread_t [numberRootThreads]; for (int kModel=0;kModelgetMaximumNodes()) finished=true; } if (finished) { feasible=false; break; } } delete [] threadId; } #endif // sort solutions int * which = new int [numberModels]; double * value = new double [numberModels]; int numberSolutions=0; for (int iModel=0;iModelbestSolution()) { which[numberSolutions]=iModel; value[numberSolutions++]= -rootModels[iModel]->getMinimizationObjValue(); } } char general[100]; rootTimeCpu=CoinCpuTime()-rootTimeCpu; if (numberRootThreads==1) sprintf(general,"Multiple root solvers took a total of %.2f seconds\n", rootTimeCpu); else sprintf(general,"Multiple root solvers took a total of %.2f seconds (%.2f elapsed)\n", rootTimeCpu,CoinGetTimeOfDay()-startTimeRoot); messageHandler()->message(CBC_GENERAL, messages()) << general << CoinMessageEol ; CoinSort_2(value,value+numberSolutions,which); // to get name CbcHeuristicRINS dummyHeuristic; dummyHeuristic.setHeuristicName("Multiple root solvers"); lastHeuristic_=&dummyHeuristic; for (int i=0;ibestSolution()); } } lastHeuristic_=NULL; delete [] which; delete [] value; } // Do heuristics if (numberObjects_&&!rootModels) doHeuristicsAtRoot(); if (solverCharacteristics_->solutionAddsCuts()) { // With some heuristics solver needs a resolve here solver_->resolve(); if(!isProvenOptimal()){ solver_->initialSolve(); } } /* Grepping through the code, it would appear that this is a command line debugging hook. There's no obvious place in the code where this is set to a negative value. User hook, says John. */ if ( intParam_[CbcMaxNumNode] < 0 ||numberSolutions_>=getMaximumSolutions()) eventHappened_ = true; // stop as fast as possible stoppedOnGap_ = false ; // See if can stop on gap bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense(); if(canStopOnGap()) { if (bestPossibleObjective_ < getCutoff()) stoppedOnGap_ = true ; feasible = false; //eventHappened_=true; // stop as fast as possible } /* Set up for statistics collection, if requested. Standard values are documented in CbcModel.hpp. The magic number 100 will trigger a dump of CbcSimpleIntegerDynamicPseudoCost objects (no others). Looks like another command line debugging hook. */ statistics_ = NULL; // Do on switch if (doStatistics > 0 && doStatistics <= 100) { maximumStatistics_ = 10000; statistics_ = new CbcStatistics * [maximumStatistics_]; memset(statistics_, 0, maximumStatistics_*sizeof(CbcStatistics *)); } // See if we can add integers if (noObjects && numberIntegers_ < solver_->getNumCols() && (specialOptions_&65536) != 0 && !parentModel_) AddIntegers(); /* Do an initial round of cut generation for the root node. Depending on the type of underlying solver, we may want to do this even if the initial query to the objects indicates they're satisfied. solveWithCuts does the heavy lifting. It will iterate a generate/reoptimise loop (including reduced cost fixing) until no cuts are generated, the change in objective falls off, or the limit on the number of rounds of cut generation is exceeded. At the end of all this, any cuts will be recorded in cuts and also installed in the solver's constraint system. We'll have reoptimised, and removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been adjusted accordingly). */ int iObject ; int preferredWay ; int numberUnsatisfied = 0 ; delete [] currentSolution_; currentSolution_ = new double [numberColumns]; testSolution_ = currentSolution_; memcpy(currentSolution_, solver_->getColSolution(), numberColumns*sizeof(double)) ; // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); for (iObject = 0 ; iObject < numberObjects_ ; iObject++) { double infeasibility = object_[iObject]->infeasibility(&usefulInfo, preferredWay) ; if (infeasibility ) numberUnsatisfied++ ; } // replace solverType double * tightBounds = NULL; if (solverCharacteristics_->tryCuts()) { if (numberUnsatisfied) { // User event if (!eventHappened_ && feasible) { if (rootModels) { // for fixings int numberColumns=solver_->getNumCols(); tightBounds = new double [2*numberColumns]; { const double * lower = solver_->getColLower(); const double * upper = solver_->getColUpper(); for (int i=0;igetNumRows(); int maxCuts=0; for (int i=0;isolver(); const double * lower = solvers[i]->getColLower(); const double * upper = solvers[i]->getColUpper(); for (int j=0;jgetNumRows(); assert (numberRows2>=numberRows); maxCuts += numberRows2-numberRows; // accumulate statistics for (int j=0;jaddStatistics(rootModels[i]->cutGenerator(j)); } } for (int j=0;jscaleBackStatistics(numberModels); } //CbcRowCuts rowCut(maxCuts); const OsiRowCutDebugger *debugger = NULL; if ((specialOptions_&1) != 0) debugger = solver_->getRowCutDebugger() ; for (int iModel=0;iModelgetNumRows(); const CoinPackedMatrix * rowCopy = solvers[iModel]->getMatrixByRow(); const int * rowLength = rowCopy->getVectorLengths(); const double * elements = rowCopy->getElements(); const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const double * rowLower = solvers[iModel]->getRowLower(); const double * rowUpper = solvers[iModel]->getRowUpper(); for (int iRow=numberRows;iRowinvalidCut(rc)); globalCuts_.addCutIfNotDuplicate(rc); } //int cutsAdded=globalCuts_.numberCuts()-numberCuts; //numberCuts += cutsAdded; //printf("Model %d gave %d cuts (out of %d possible)\n", // iModel,cutsAdded,numberRows2-numberRows); } // normally replace global cuts //if (!globalCuts_.()) //globalCuts_=rowCutrowCut.addCuts(globalCuts_); //rowCut.addCuts(globalCuts_); int nTightened=0; bool feasible=true; { double tolerance=1.0e-5; const double * lower = solver_->getColLower(); const double * upper = solver_->getColUpper(); for (int i=0;itightBounds[2*i+1]) { feasible=false; printf("Bad bounds on %d %g,%g was %g,%g\n", i,tightBounds[2*i+0],tightBounds[2*i+1], lower[i],upper[i]); } //int k=0; double oldLower=lower[i]; double oldUpper=upper[i]; if (tightBounds[2*i+0]>oldLower+tolerance) { nTightened++; //k++; solver_->setColLower(i,tightBounds[2*i+0]); } if (tightBounds[2*i+1]setColUpper(i,tightBounds[2*i+1]); } //if (k) //printf("new bounds on %d %g,%g was %g,%g\n", // i,tightBounds[2*i+0],tightBounds[2*i+1], // oldLower,oldUpper); } if (!feasible) abort(); // deal with later } delete [] tightBounds; tightBounds=NULL; char printBuffer[200]; sprintf(printBuffer,"%d solvers added %d different cuts out of pool of %d", numberModels,globalCuts_.sizeRowCuts(),maxCuts); messageHandler()->message(CBC_GENERAL, messages()) << printBuffer << CoinMessageEol ; if (nTightened) { sprintf(printBuffer,"%d bounds were tightened", nTightened); messageHandler()->message(CBC_GENERAL, messages()) << printBuffer << CoinMessageEol ; } delete [] solvers; } if (!parentModel_&&(moreSpecialOptions_&67108864) != 0) { // load cuts from file FILE * fp = fopen("global.cuts","rb"); if (fp) { size_t nRead; int numberColumns=solver_->getNumCols(); int numCols; nRead = fread(&numCols, sizeof(int), 1, fp); if (nRead != 1) throw("Error in fread"); if (numberColumns!=numCols) { printf("Mismatch on columns %d %d\n",numberColumns,numCols); fclose(fp); } else { // If rootModel just do some double threshold=-1.0; if (!multipleRootTries_) threshold=0.5; int initialCuts=0; int initialGlobal = globalCuts_.sizeRowCuts(); double * elements = new double [numberColumns+2]; int * indices = new int [numberColumns]; int numberEntries=1; while (numberEntries>0) { nRead = fread(&numberEntries, sizeof(int), 1, fp); if (nRead != 1) throw("Error in fread"); double randomNumber=randomNumberGenerator_.randomDouble(); if (numberEntries>0) { initialCuts++; nRead = fread(elements, sizeof(double), numberEntries+2, fp); if (nRead != static_cast(numberEntries+2)) throw("Error in fread"); nRead = fread(indices, sizeof(int), numberEntries, fp); if (nRead != static_cast(numberEntries)) throw("Error in fread"); if (randomNumber>threshold) { OsiRowCut rc; rc.setLb(elements[numberEntries]); rc.setUb(elements[numberEntries+1]); rc.setRow(numberEntries,indices,elements, false); rc.setGloballyValidAsInteger(2); globalCuts_.addCutIfNotDuplicate(rc) ; } } } fclose(fp); // fixes int nTightened=0; fp = fopen("global.fix","rb"); if (fp) { nRead = fread(indices, sizeof(int), 2, fp); if (nRead != 2) throw("Error in fread"); if (numberColumns!=indices[0]) { printf("Mismatch on columns %d %d\n",numberColumns, indices[0]); } else { indices[0]=1; while (indices[0]>=0) { nRead = fread(indices, sizeof(int), 2, fp); if (nRead != 2) throw("Error in fread"); int iColumn=indices[0]; if (iColumn>=0) { nTightened++; nRead = fread(elements, sizeof(double), 4, fp); if (nRead != 4) throw("Error in fread"); solver_->setColLower(iColumn,elements[0]); solver_->setColUpper(iColumn,elements[1]); } } } } if (fp) fclose(fp); char printBuffer[200]; sprintf(printBuffer,"%d cuts read in of which %d were unique, %d bounds tightened", initialCuts, globalCuts_.sizeRowCuts()-initialGlobal,nTightened); messageHandler()->message(CBC_GENERAL, messages()) << printBuffer << CoinMessageEol ; delete [] elements; delete [] indices; } } } feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, NULL); if (multipleRootTries_&& (moreSpecialOptions_&134217728)!=0) { FILE * fp=NULL; size_t nRead; int numberColumns=solver_->getNumCols(); int initialCuts=0; if ((moreSpecialOptions_&134217728)!=0) { // append so go down to end fp = fopen("global.cuts","r+b"); if (fp) { int numCols; nRead = fread(&numCols, sizeof(int), 1, fp); if (nRead != 1) throw("Error in fread"); if (numberColumns!=numCols) { printf("Mismatch on columns %d %d\n",numberColumns,numCols); fclose(fp); fp=NULL; } } } double * elements = new double [numberColumns+2]; int * indices = new int [numberColumns]; if (fp) { int numberEntries=1; while (numberEntries>0) { fpos_t position; fgetpos(fp, &position); nRead = fread(&numberEntries, sizeof(int), 1, fp); if (nRead != 1) throw("Error in fread"); if (numberEntries>0) { initialCuts++; nRead = fread(elements, sizeof(double), numberEntries+2, fp); if (nRead != static_cast(numberEntries+2)) throw("Error in fread"); nRead = fread(indices, sizeof(int), numberEntries, fp); if (nRead != static_cast(numberEntries)) throw("Error in fread"); } else { // end fsetpos(fp, &position); } } } else { fp = fopen("global.cuts","wb"); size_t nWrite; nWrite=fwrite(&numberColumns,sizeof(int),1,fp); if (nWrite != 1) throw("Error in fwrite"); } size_t nWrite; // now append binding cuts int numberC=continuousSolver_->getNumRows(); int numberRows=solver_->getNumRows(); printf("Saving %d cuts (up from %d)\n", initialCuts+numberRows-numberC,initialCuts); const double * rowLower = solver_->getRowLower(); const double * rowUpper = solver_->getRowUpper(); // Row copy CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow()); const double * elementByRow = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); for (int iRow=numberC;iRow(n+2)) throw("Error in fwrite"); nWrite=fwrite(indices,sizeof(int),n,fp); if (nWrite != static_cast(n)) throw("Error in fwrite"); } // eof marker int eofMarker=-1; nWrite=fwrite(&eofMarker,sizeof(int),1,fp); if (nWrite != 1) throw("Error in fwrite"); fclose(fp); // do tighter bounds (? later extra to original columns) int nTightened=0; const double * lower = solver_->getColLower(); const double * upper = solver_->getColUpper(); const double * originalLower = continuousSolver_->getColLower(); const double * originalUpper = continuousSolver_->getColUpper(); double tolerance=1.0e-5; for (int i=0;ioriginalLower[i]+tolerance) { nTightened++; } if (upper[i]originalLower[i]+tolerance) { nTightened++; } if (upper[i]getColLower(); const double * upper = solver_->getColUpper(); const double * tightLower = storedRowCuts_->tightLower(); const double * tightUpper = storedRowCuts_->tightUpper(); int nTightened = 0; for (int i = 0; i < numberIntegers_; i++) { int iColumn = integerVariable_[i]; if (tightLower[iColumn] > lower[iColumn]) { nTightened++; solver_->setColLower(iColumn, tightLower[iColumn]); } if (tightUpper[iColumn] < upper[iColumn]) { nTightened++; solver_->setColUpper(iColumn, tightUpper[iColumn]); } } if (nTightened) COIN_DETAIL_PRINT(printf("%d tightened by alternate cuts\n", nTightened)); if (storedRowCuts_->bestObjective() < bestObjective_) { // B) best solution double objValue = storedRowCuts_->bestObjective(); setBestSolution(CBC_SOLUTION, objValue, storedRowCuts_->bestSolution()) ; // Do heuristics // Allow RINS for (int i = 0; i < numberHeuristics_; i++) { CbcHeuristicRINS * rins = dynamic_cast (heuristic_[i]); if (rins) { rins->setLastNode(-100); } } doHeuristicsAtRoot(); } #ifdef JJF_ZERO int nCuts = storedRowCuts_->sizeRowCuts(); // add to global list for (int i = 0; i < nCuts; i++) { OsiRowCut newCut(*storedRowCuts_->rowCutPointer(i)); newCut.setGloballyValidAsInteger(2); newCut.mutableRow().setTestForDuplicateIndex(false); globalCuts_.insert(newCut) ; } #else addCutGenerator(storedRowCuts_, -99, "Stored from previous run", true, false, false, -200); #endif // Set cuts as active delete [] addedCuts_ ; maximumNumberCuts_ = cuts.sizeRowCuts(); if (maximumNumberCuts_) { addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_]; } else { addedCuts_ = NULL; } for (int i = 0; i < maximumNumberCuts_; i++) addedCuts_[i] = new CbcCountRowCut(*cuts.rowCutPtr(i), NULL, -1, -1, 2); COIN_DETAIL_PRINT(printf("size %d\n", cuts.sizeRowCuts())); cuts = OsiCuts(); currentNumberCuts_ = maximumNumberCuts_; feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, NULL); for (int i = 0; i < maximumNumberCuts_; i++) delete addedCuts_[i]; } delete storedRowCuts_; storedRowCuts_ = NULL; } } else { feasible = false; } } else if (solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->alwaysTryCutsAtRootNode()) { // may generate cuts and turn the solution //to an infeasible one feasible = solveWithCuts(cuts, 2, NULL); } } if (rootModels) { int numberModels = multipleRootTries_%100; for (int i=0;imipFeasible()) feasible = false; // If max nodes==0 - don't do strong branching if (!getMaximumNodes()) { if (feasible) feasible=false; else setMaximumNodes(1); //allow to stop on success } topOfTree_=NULL; #ifdef CLP_RESOLVE if ((moreSpecialOptions_&2097152)!=0&&!parentModel_&&feasible) { OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) resolveClp(clpSolver,0); } #endif // make cut generators less aggressive for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { CglCutGenerator * generator = generator_[iCutGenerator]->generator(); generator->setAggressiveness(generator->getAggressiveness() - 100); } currentNumberCuts_ = numberNewCuts_ ; if (solverCharacteristics_->solutionAddsCuts()) { // With some heuristics solver needs a resolve here (don't know if this is bug in heuristics) solver_->resolve(); if(!isProvenOptimal()){ solver_->initialSolve(); } } // See if can stop on gap bestPossibleObjective_ = solver_->getObjValue() * solver_->getObjSense(); if(canStopOnGap()) { if (bestPossibleObjective_ < getCutoff()) stoppedOnGap_ = true ; feasible = false; } // User event if (eventHappened_) feasible = false; #if defined(COIN_HAS_CLP)&&defined(COIN_HAS_CPX) /* This is the notion of using Cbc stuff to get going, then calling cplex to finish off. */ if (feasible && (specialOptions_&16384) != 0 && fastNodeDepth_ == -2 && !parentModel_) { // Use Cplex to do search! double time1 = CoinCpuTime(); OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); OsiCpxSolverInterface cpxSolver; double direction = clpSolver->getObjSense(); cpxSolver.setObjSense(direction); // load up cplex const CoinPackedMatrix * matrix = continuousSolver_->getMatrixByCol(); const double * rowLower = continuousSolver_->getRowLower(); const double * rowUpper = continuousSolver_->getRowUpper(); const double * columnLower = continuousSolver_->getColLower(); const double * columnUpper = continuousSolver_->getColUpper(); const double * objective = continuousSolver_->getObjCoefficients(); cpxSolver.loadProblem(*matrix, columnLower, columnUpper, objective, rowLower, rowUpper); double * setSol = new double [numberIntegers_]; int * setVar = new int [numberIntegers_]; // cplex doesn't know about objective offset double offset = clpSolver->getModelPtr()->objectiveOffset(); for (int i = 0; i < numberIntegers_; i++) { int iColumn = integerVariable_[i]; cpxSolver.setInteger(iColumn); if (bestSolution_) { setSol[i] = bestSolution_[iColumn]; setVar[i] = iColumn; } } CPXENVptr env = cpxSolver.getEnvironmentPtr(); CPXLPptr lpPtr = cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL); cpxSolver.switchToMIP(); if (bestSolution_) { CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol); } if (clpSolver->getNumRows() > continuousSolver_->getNumRows() && false) { // add cuts const CoinPackedMatrix * matrix = clpSolver->getMatrixByRow(); const double * rhs = clpSolver->getRightHandSide(); const char * rowSense = clpSolver->getRowSense(); const double * elementByRow = matrix->getElements(); const int * column = matrix->getIndices(); const CoinBigIndex * rowStart = matrix->getVectorStarts(); const int * rowLength = matrix->getVectorLengths(); int nStart = continuousSolver_->getNumRows(); int nRows = clpSolver->getNumRows(); int size = rowStart[nRows-1] + rowLength[nRows-1] - rowStart[nStart]; int nAdd = 0; double * rmatval = new double [size]; int * rmatind = new int [size]; int * rmatbeg = new int [nRows-nStart+1]; size = 0; rmatbeg[0] = 0; for (int i = nStart; i < nRows; i++) { for (int k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) { rmatind[size] = column[k]; rmatval[size++] = elementByRow[k]; } nAdd++; rmatbeg[nAdd] = size; } CPXaddlazyconstraints(env, lpPtr, nAdd, size, rhs, rowSense, rmatbeg, rmatind, rmatval, NULL); CPXsetintparam( env, CPX_PARAM_REDUCE, // CPX_PREREDUCE_NOPRIMALORDUAL (0) CPX_PREREDUCE_PRIMALONLY); } if (getCutoff() < 1.0e50) { double useCutoff = getCutoff() + offset; if (bestObjective_ < 1.0e50) useCutoff = bestObjective_ + offset + 1.0e-7; cpxSolver.setDblParam(OsiDualObjectiveLimit, useCutoff* direction); if ( direction > 0.0 ) CPXsetdblparam( env, CPX_PARAM_CUTUP, useCutoff ) ; // min else CPXsetdblparam( env, CPX_PARAM_CUTLO, useCutoff ) ; // max } CPXsetdblparam(env, CPX_PARAM_EPGAP, dblParam_[CbcAllowableFractionGap]); delete [] setSol; delete [] setVar; char printBuffer[200]; if (offset) { sprintf(printBuffer, "Add %g to all Cplex messages for true objective", -offset); messageHandler()->message(CBC_GENERAL, messages()) << printBuffer << CoinMessageEol ; cpxSolver.setDblParam(OsiObjOffset, offset); } cpxSolver.branchAndBound(); double timeTaken = CoinCpuTime() - time1; sprintf(printBuffer, "Cplex took %g seconds", timeTaken); messageHandler()->message(CBC_GENERAL, messages()) << printBuffer << CoinMessageEol ; numberExtraNodes_ = CPXgetnodecnt(env, lpPtr); numberExtraIterations_ = CPXgetmipitcnt(env, lpPtr); double value = cpxSolver.getObjValue() * direction; if (cpxSolver.isProvenOptimal() && value <= getCutoff()) { feasible = true; clpSolver->setWarmStart(NULL); // try and do solution double * newSolution = CoinCopyOfArray(cpxSolver.getColSolution(), getNumCols()); setBestSolution(CBC_STRONGSOL, value, newSolution) ; delete [] newSolution; } feasible = false; } #endif if (!parentModel_&&(moreSpecialOptions_&268435456) != 0) { // try idiotic idea CbcObject * obj = new CbcIdiotBranch(this); obj->setPriority(1); // temp addObjects(1, &obj); delete obj; } /* A hook to use clp to quickly explore some part of the tree. */ if (fastNodeDepth_ == 1000 &&/*!parentModel_*/(specialOptions_&2048) == 0) { fastNodeDepth_ = -1; CbcObject * obj = new CbcFollowOn(this); obj->setPriority(1); addObjects(1, &obj); delete obj; } int saveNumberSolves = numberSolves_; int saveNumberIterations = numberIterations_; if ((fastNodeDepth_ >= 0||(moreSpecialOptions_&33554432)!=0) &&/*!parentModel_*/(specialOptions_&2048) == 0) { // add in a general depth object doClp int type = (fastNodeDepth_ <= 100) ? fastNodeDepth_ : -(fastNodeDepth_ - 100); if ((moreSpecialOptions_&33554432)!=0) type=12; else fastNodeDepth_ += 1000000; // mark as done CbcObject * obj = new CbcGeneralDepth(this, type); addObjects(1, &obj); delete obj; // fake number of objects numberObjects_--; if (parallelMode() < -1) { // But make sure position is correct OsiObject * obj2 = object_[numberObjects_]; obj = dynamic_cast (obj2); assert (obj); obj->setPosition(numberObjects_); } } #ifdef COIN_HAS_CLP #ifdef NO_CRUNCH if (true) { OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver && !parentModel_) { ClpSimplex * clpSimplex = clpSolver->getModelPtr(); clpSimplex->setSpecialOptions(clpSimplex->specialOptions() | 131072); //clpSimplex->startPermanentArrays(); clpSimplex->setPersistenceFlag(2); } } #endif #endif // Save copy of solver OsiSolverInterface * saveSolver = NULL; if (!parentModel_ && (specialOptions_&(512 + 32768)) != 0) saveSolver = solver_->clone(); double checkCutoffForRestart = 1.0e100; saveModel(saveSolver, &checkCutoffForRestart, &feasible); if ((specialOptions_&262144) != 0 && !parentModel_) { // Save stuff and return! storedRowCuts_->saveStuff(bestObjective_, bestSolution_, solver_->getColLower(), solver_->getColUpper()); delete [] lowerBefore; delete [] upperBefore; delete saveSolver; if (flipObjective) flipModel(); return; } /* We've taken the continuous relaxation as far as we can. Time to branch. The first order of business is to actually create a node. chooseBranch currently uses strong branching to evaluate branch object candidates, unless forced back to simple branching. If chooseBranch concludes that a branching candidate is monotone (anyAction == -1) or infeasible (anyAction == -2) when forced to integer values, it returns here immediately. Monotone variables trigger a call to resolve(). If the problem remains feasible, try again to choose a branching variable. At the end of the loop, resolved == true indicates that some variables were fixed. Loss of feasibility will result in the deletion of newNode. */ bool resolved = false ; CbcNode *newNode = NULL ; numberFixedAtRoot_ = 0; numberFixedNow_ = 0; int numberIterationsAtContinuous = numberIterations_; //solverCharacteristics_->setSolver(solver_); if (feasible) { #define HOTSTART -1 #if HOTSTART<0 if (bestSolution_ && !parentModel_ && !hotstartSolution_ && (moreSpecialOptions_&1024) != 0) { // Set priorities so only branch on ones we need to // use djs and see if only few branches needed #ifndef NDEBUG double integerTolerance = getIntegerTolerance() ; #endif bool possible = true; const double * saveLower = continuousSolver_->getColLower(); const double * saveUpper = continuousSolver_->getColUpper(); for (int i = 0; i < numberObjects_; i++) { const CbcSimpleInteger * thisOne = dynamic_cast (object_[i]); if (thisOne) { int iColumn = thisOne->columnNumber(); if (saveUpper[iColumn] > saveLower[iColumn] + 1.5) { possible = false; break; } } else { possible = false; break; } } if (possible) { OsiSolverInterface * solver = continuousSolver_->clone(); int numberColumns = solver->getNumCols(); for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) { double value = bestSolution_[iColumn] ; value = CoinMax(value, saveLower[iColumn]) ; value = CoinMin(value, saveUpper[iColumn]) ; value = floor(value + 0.5); if (solver->isInteger(iColumn)) { solver->setColLower(iColumn, value); solver->setColUpper(iColumn, value); } } solver->setHintParam(OsiDoDualInResolve, false, OsiHintTry); // objlim and all slack double direction = solver->getObjSense(); solver->setDblParam(OsiDualObjectiveLimit, 1.0e50*direction); CoinWarmStartBasis * basis = dynamic_cast (solver->getEmptyWarmStart()); solver->setWarmStart(basis); delete basis; bool changed = true; hotstartPriorities_ = new int [numberColumns]; for (int iColumn = 0; iColumn < numberColumns; iColumn++) hotstartPriorities_[iColumn] = 1; while (changed) { changed = false; solver->resolve(); if (!solver->isProvenOptimal()) { possible = false; break; } const double * dj = solver->getReducedCost(); const double * colLower = solver->getColLower(); const double * colUpper = solver->getColUpper(); const double * solution = solver->getColSolution(); int nAtLbNatural = 0; int nAtUbNatural = 0; int nZeroDj = 0; int nForced = 0; for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) { double value = solution[iColumn] ; value = CoinMax(value, saveLower[iColumn]) ; value = CoinMin(value, saveUpper[iColumn]) ; if (solver->isInteger(iColumn)) { assert(fabs(value - solution[iColumn]) <= integerTolerance) ; if (hotstartPriorities_[iColumn] == 1) { if (dj[iColumn] < -1.0e-6) { // negative dj if (saveUpper[iColumn] == colUpper[iColumn]) { nAtUbNatural++; hotstartPriorities_[iColumn] = 2; solver->setColLower(iColumn, saveLower[iColumn]); solver->setColUpper(iColumn, saveUpper[iColumn]); } else { nForced++; } } else if (dj[iColumn] > 1.0e-6) { // positive dj if (saveLower[iColumn] == colLower[iColumn]) { nAtLbNatural++; hotstartPriorities_[iColumn] = 2; solver->setColLower(iColumn, saveLower[iColumn]); solver->setColUpper(iColumn, saveUpper[iColumn]); } else { nForced++; } } else { // zero dj nZeroDj++; } } } } #ifdef CLP_INVESTIGATE printf("%d forced, %d naturally at lower, %d at upper - %d zero dj\n", nForced, nAtLbNatural, nAtUbNatural, nZeroDj); #endif if (nAtLbNatural || nAtUbNatural) { changed = true; } else { if (nForced + nZeroDj > 5000 || (nForced + nZeroDj)*2 > numberIntegers_) possible = false; } } delete solver; } if (possible) { setHotstartSolution(bestSolution_); if (!saveCompare) { // create depth first comparison saveCompare = nodeCompare_; // depth first nodeCompare_ = new CbcCompareDepth(); tree_->setComparison(*nodeCompare_) ; } } else { delete [] hotstartPriorities_; hotstartPriorities_ = NULL; } } #endif #if HOTSTART>0 if (hotstartSolution_ && !hotstartPriorities_) { // Set up hot start OsiSolverInterface * solver = solver_->clone(); double direction = solver_->getObjSense() ; int numberColumns = solver->getNumCols(); double * saveLower = CoinCopyOfArray(solver->getColLower(), numberColumns); double * saveUpper = CoinCopyOfArray(solver->getColUpper(), numberColumns); // move solution solver->setColSolution(hotstartSolution_); // point to useful information const double * saveSolution = testSolution_; testSolution_ = solver->getColSolution(); OsiBranchingInformation usefulInfo = usefulInformation(); testSolution_ = saveSolution; /* Run through the objects and use feasibleRegion() to set variable bounds so as to fix the variables specified in the objects at their value in this solution. Since the object list contains (at least) one object for every integer variable, this has the effect of fixing all integer variables. */ for (int i = 0; i < numberObjects_; i++) object_[i]->feasibleRegion(solver, &usefulInfo); solver->resolve(); assert (solver->isProvenOptimal()); double gap = CoinMax((solver->getObjValue() - solver_->getObjValue()) * direction, 0.0) ; const double * dj = solver->getReducedCost(); const double * colLower = solver->getColLower(); const double * colUpper = solver->getColUpper(); const double * solution = solver->getColSolution(); int nAtLbNatural = 0; int nAtUbNatural = 0; int nAtLbNaturalZero = 0; int nAtUbNaturalZero = 0; int nAtLbFixed = 0; int nAtUbFixed = 0; int nAtOther = 0; int nAtOtherNatural = 0; int nNotNeeded = 0; delete [] hotstartSolution_; hotstartSolution_ = new double [numberColumns]; delete [] hotstartPriorities_; hotstartPriorities_ = new int [numberColumns]; int * order = (int *) saveUpper; int nFix = 0; double bestRatio = COIN_DBL_MAX; for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) { double value = solution[iColumn] ; value = CoinMax(value, saveLower[iColumn]) ; value = CoinMin(value, saveUpper[iColumn]) ; double sortValue = COIN_DBL_MAX; if (solver->isInteger(iColumn)) { assert(fabs(value - solution[iColumn]) <= 1.0e-5) ; double value2 = floor(value + 0.5); if (dj[iColumn] < -1.0e-6) { // negative dj //assert (value2==colUpper[iColumn]); if (saveUpper[iColumn] == colUpper[iColumn]) { nAtUbNatural++; sortValue = 0.0; double value = -dj[iColumn]; if (value > gap) nFix++; else if (gap < value*bestRatio) bestRatio = gap / value; if (saveLower[iColumn] != colLower[iColumn]) { nNotNeeded++; sortValue = 1.0e20; } } else if (saveLower[iColumn] == colUpper[iColumn]) { nAtLbFixed++; sortValue = dj[iColumn]; } else { nAtOther++; sortValue = 0.0; if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) { nNotNeeded++; sortValue = 1.0e20; } } } else if (dj[iColumn] > 1.0e-6) { // positive dj //assert (value2==colLower[iColumn]); if (saveLower[iColumn] == colLower[iColumn]) { nAtLbNatural++; sortValue = 0.0; double value = dj[iColumn]; if (value > gap) nFix++; else if (gap < value*bestRatio) bestRatio = gap / value; if (saveUpper[iColumn] != colUpper[iColumn]) { nNotNeeded++; sortValue = 1.0e20; } } else if (saveUpper[iColumn] == colLower[iColumn]) { nAtUbFixed++; sortValue = -dj[iColumn]; } else { nAtOther++; sortValue = 0.0; if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) { nNotNeeded++; sortValue = 1.0e20; } } } else { // zero dj if (value2 == saveUpper[iColumn]) { nAtUbNaturalZero++; sortValue = 0.0; if (saveLower[iColumn] != colLower[iColumn]) { nNotNeeded++; sortValue = 1.0e20; } } else if (value2 == saveLower[iColumn]) { nAtLbNaturalZero++; sortValue = 0.0; } else { nAtOtherNatural++; sortValue = 0.0; if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) { nNotNeeded++; sortValue = 1.0e20; } } } #if HOTSTART==3 sortValue = -fabs(dj[iColumn]); #endif } hotstartSolution_[iColumn] = value ; saveLower[iColumn] = sortValue; order[iColumn] = iColumn; } COIN_DETAIL_PRINT(printf("** can fix %d columns - best ratio for others is %g on gap of %g\n", nFix, bestRatio, gap)); int nNeg = 0; CoinSort_2(saveLower, saveLower + numberColumns, order); for (int i = 0; i < numberColumns; i++) { if (saveLower[i] < 0.0) { nNeg++; #if HOTSTART==2||HOTSTART==3 // swap sign ? saveLower[i] = -saveLower[i]; #endif } } CoinSort_2(saveLower, saveLower + nNeg, order); for (int i = 0; i < numberColumns; i++) { #if HOTSTART==1 hotstartPriorities_[order[i]] = 100; #else hotstartPriorities_[order[i]] = -(i + 1); #endif } COIN_DETAIL_PRINT(printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d %d\n", nAtLbNatural, nAtUbNatural, nAtLbNaturalZero, nAtUbNaturalZero, nAtLbFixed, nAtUbFixed, nAtOther, nAtOtherNatural, nNotNeeded, nNeg)); delete [] saveLower; delete [] saveUpper; if (!saveCompare) { // create depth first comparison saveCompare = nodeCompare_; // depth first nodeCompare_ = new CbcCompareDepth(); tree_->setComparison(*nodeCompare_) ; } } #endif newNode = new CbcNode ; // Set objective value (not so obvious if NLP etc) setObjectiveValue(newNode, NULL); anyAction = -1 ; // To make depth available we may need a fake node CbcNode fakeNode; if (!currentNode_) { // Not true if sub trees assert (!numberNodes_); currentNode_ = &fakeNode; } phase_ = 3; // only allow 1000 passes int numberPassesLeft = 1000; // This is first crude step if (numberAnalyzeIterations_) { delete [] analyzeResults_; analyzeResults_ = new double [4*numberIntegers_]; numberFixedAtRoot_ = newNode->analyze(this, analyzeResults_); if (numberFixedAtRoot_ > 0) { COIN_DETAIL_PRINT(printf("%d fixed by analysis\n", numberFixedAtRoot_)); setPointers(solver_); numberFixedNow_ = numberFixedAtRoot_; } else if (numberFixedAtRoot_ < 0) { COIN_DETAIL_PRINT(printf("analysis found to be infeasible\n")); anyAction = -2; delete newNode ; newNode = NULL ; feasible = false ; } } OsiSolverBranch * branches = NULL; anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts, resolved, NULL, NULL, NULL, branches); if (anyAction == -2 || newNode->objectiveValue() >= cutoff) { if (anyAction != -2) { // zap parent nodeInfo #ifdef COIN_DEVELOP printf("zapping CbcNodeInfo %x\n", reinterpret_cast(newNode->nodeInfo()->parent())); #endif if (newNode->nodeInfo()) newNode->nodeInfo()->nullParent(); } delete newNode ; newNode = NULL ; feasible = false ; } } if (newNode && probingInfo_) { int number01 = probingInfo_->numberIntegers(); //const fixEntry * entry = probingInfo_->fixEntries(); const int * toZero = probingInfo_->toZero(); //const int * toOne = probingInfo_->toOne(); //const int * integerVariable = probingInfo_->integerVariable(); if (toZero[number01]) { CglTreeProbingInfo info(*probingInfo_); #ifdef JJF_ZERO /* Marginal idea. Further exploration probably good. Build some extra cliques from probing info. Not quite worth the effort? */ OsiSolverInterface * fake = info.analyze(*solver_, 1); if (fake) { fake->writeMps("fake"); CglFakeClique cliqueGen(fake); cliqueGen.setStarCliqueReport(false); cliqueGen.setRowCliqueReport(false); cliqueGen.setMinViolation(0.1); addCutGenerator(&cliqueGen, 1, "Fake cliques", true, false, false, -200); generator_[numberCutGenerators_-1]->setTiming(true); } #endif if (probingInfo_->packDown()) { #ifdef CLP_INVESTIGATE printf("%d implications on %d 0-1\n", toZero[number01], number01); #endif // Create a cut generator that remembers implications discovered at root. CglImplication implication(probingInfo_); addCutGenerator(&implication, 1, "ImplicationCuts", true, false, false, -200); generator_[numberCutGenerators_-1]->setGlobalCuts(true); } else { delete probingInfo_; probingInfo_ = NULL; } } else { delete probingInfo_; probingInfo_ = NULL; } } /* At this point, the root subproblem is infeasible or fathomed by bound (newNode == NULL), or we're live with an objective value that satisfies the current objective cutoff. */ assert (!newNode || newNode->objectiveValue() <= cutoff) ; // Save address of root node as we don't want to delete it // initialize for print out int lastDepth = 0; int lastUnsatisfied = 0; if (newNode) lastUnsatisfied = newNode->numberUnsatisfied(); /* The common case is that the lp relaxation is feasible but doesn't satisfy integrality (i.e., newNode->branchingObject(), indicating we've been able to select a branching variable). Remove any cuts that have gone slack due to forcing monotone variables. Then tack on an CbcFullNodeInfo object and full basis (via createInfo()) and stash the new cuts in the nodeInfo (via addCuts()). If, by some miracle, we have an integral solution at the root (newNode->branchingObject() is NULL), takeOffCuts() will ensure that the solver holds a valid solution for use by setBestSolution(). */ CoinWarmStartBasis *lastws = NULL ; if (feasible && newNode->branchingObject()) { if (resolved) { takeOffCuts(cuts, false, NULL) ; # ifdef CHECK_CUT_COUNTS { printf("Number of rows after chooseBranch fix (root)" "(active only) %d\n", numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_) ; const CoinWarmStartBasis* debugws = dynamic_cast (solver_->getWarmStart()) ; debugws->print() ; delete debugws ; } # endif } //newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ; //newNode->nodeInfo()->addCuts(cuts, // newNode->numberBranches(),whichGenerator_) ; if (lastws) delete lastws ; lastws = dynamic_cast(solver_->getWarmStart()) ; } /* Continuous data to be used later */ continuousObjective_ = solver_->getObjValue() * solver_->getObjSense(); continuousInfeasibilities_ = 0 ; if (newNode) { continuousObjective_ = newNode->objectiveValue() ; delete [] continuousSolution_; continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), numberColumns); continuousInfeasibilities_ = newNode->numberUnsatisfied() ; } /* Bound may have changed so reset in objects */ { int i ; for (i = 0; i < numberObjects_; i++) object_[i]->resetBounds(solver_) ; } /* Feasible? Then we should have either a live node prepped for future expansion (indicated by variable() >= 0), or (miracle of miracles) an integral solution at the root node. initializeInfo sets the reference counts in the nodeInfo object. Since this node is still live, push it onto the heap that holds the live set. */ if (newNode) { if (newNode->branchingObject()) { newNode->initializeInfo() ; tree_->push(newNode) ; // save pointer to root node - so can pick up bounds if (!topOfTree_) topOfTree_ = dynamic_cast(newNode->nodeInfo()) ; if (statistics_) { if (numberNodes2_ == maximumStatistics_) { maximumStatistics_ = 2 * maximumStatistics_; CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_]; memset(temp, 0, maximumStatistics_*sizeof(CbcStatistics *)); memcpy(temp, statistics_, numberNodes2_*sizeof(CbcStatistics *)); delete [] statistics_; statistics_ = temp; } assert (!statistics_[numberNodes2_]); statistics_[numberNodes2_] = new CbcStatistics(newNode, this); } numberNodes2_++; # ifdef CHECK_NODE printf("Node %x on tree\n", newNode) ; # endif } else { // continuous is integer double objectiveValue = newNode->objectiveValue(); setBestSolution(CBC_SOLUTION, objectiveValue, solver_->getColSolution()) ; if (eventHandler) { // we are stopping anyway so no need to test return code eventHandler->event(CbcEventHandler::solution); } delete newNode ; newNode = NULL ; } } if (printFrequency_ <= 0) { printFrequency_ = 1000 ; if (getNumCols() > 2000) printFrequency_ = 100 ; } /* It is possible that strong branching fixes one variable and then the code goes round again and again. This can take too long. So we need to warn user - just once. */ numberLongStrong_ = 0; CbcNode * createdNode = NULL; #ifdef CBC_THREAD if ((specialOptions_&2048) != 0) numberThreads_ = 0; if (numberThreads_ ) { nodeCompare_->sayThreaded(); // need to use addresses master_ = new CbcBaseModel(*this, (parallelMode() < -1) ? 1 : 0); masterThread_ = master_->masterThread(); } #endif #ifdef COIN_HAS_CLP { OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver && !parentModel_) { clpSolver->computeLargestAway(); } } #endif /* At last, the actual branch-and-cut search loop, which will iterate until the live set is empty or we hit some limit (integrality gap, time, node count, etc.). The overall flow is to rebuild a subproblem, reoptimise using solveWithCuts(), choose a branching pattern with chooseBranch(), and finally add the node to the live set. The first action is to winnow the live set to remove nodes which are worse than the current objective cutoff. */ if (solver_->getRowCutDebuggerAlways()) { OsiRowCutDebugger * debuggerX = const_cast (solver_->getRowCutDebuggerAlways()); const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ; if (!debugger) { // infeasible!! printf("before search\n"); const double * lower = solver_->getColLower(); const double * upper = solver_->getColUpper(); const double * solution = debuggerX->optimalSolution(); int numberColumns = solver_->getNumCols(); for (int i = 0; i < numberColumns; i++) { if (solver_->isInteger(i)) { if (solution[i] < lower[i] - 1.0e-6 || solution[i] > upper[i] + 1.0e-6) printf("**** "); printf("%d %g <= %g <= %g\n", i, lower[i], solution[i], upper[i]); } } //abort(); } } { // may be able to change cutoff now double cutoff = getCutoff(); double increment = getDblParam(CbcModel::CbcCutoffIncrement) ; if (cutoff > bestObjective_ - increment) { cutoff = bestObjective_ - increment ; setCutoff(cutoff) ; } } #ifdef CBC_THREAD bool goneParallel = false; #endif #define MAX_DEL_NODE 1 CbcNode * delNode[MAX_DEL_NODE+1]; int nDeleteNode = 0; // For Printing etc when parallel int lastEvery1000 = 0; int lastPrintEvery = 0; int numberConsecutiveInfeasible = 0; #define PERTURB_IN_FATHOM #ifdef PERTURB_IN_FATHOM // allow in fathom if ((moreSpecialOptions_& 262144) != 0) specialOptions_ |= 131072; #endif while (true) { lockThread(); #ifdef COIN_HAS_CLP // See if we want dantzig row choice goToDantzig(100, savePivotMethod); #endif if (tree_->empty()) { #ifdef CBC_THREAD if (parallelMode() > 0 && master_) { int anyLeft = master_->waitForThreadsInTree(0); if (!anyLeft) { master_->stopThreads(-1); break; } } else { break; } #else break; #endif } else { unlockThread(); } // If done 100 nodes see if worth trying reduction if (numberNodes_ == 50 || numberNodes_ == 100) { #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver && ((specialOptions_&131072) == 0) && true) { ClpSimplex * simplex = clpSolver->getModelPtr(); int perturbation = simplex->perturbation(); #ifdef CLP_INVESTIGATE printf("Testing its n,s %d %d solves n,s %d %d - pert %d\n", numberIterations_, saveNumberIterations, numberSolves_, saveNumberSolves, perturbation); #endif if (perturbation == 50 && (numberIterations_ - saveNumberIterations) < 8*(numberSolves_ - saveNumberSolves)) { // switch off perturbation simplex->setPerturbation(100); #ifdef CLP_INVESTIGATE printf("Perturbation switched off\n"); #endif } } #endif /* Decide if we want to do a restart. */ if (saveSolver && (specialOptions_&(512 + 32768)) != 0) { bool tryNewSearch = solverCharacteristics_->reducedCostsAccurate() && (getCutoff() < 1.0e20 && getCutoff() < checkCutoffForRestart); int numberColumns = getNumCols(); if (tryNewSearch) { checkCutoffForRestart = getCutoff() ; #ifdef CLP_INVESTIGATE printf("after %d nodes, cutoff %g - looking\n", numberNodes_, getCutoff()); #endif saveSolver->resolve(); double direction = saveSolver->getObjSense() ; double gap = checkCutoffForRestart - saveSolver->getObjValue() * direction ; double tolerance; saveSolver->getDblParam(OsiDualTolerance, tolerance) ; if (gap <= 0.0) gap = tolerance; gap += 100.0 * tolerance; double integerTolerance = getDblParam(CbcIntegerTolerance) ; const double *lower = saveSolver->getColLower() ; const double *upper = saveSolver->getColUpper() ; const double *solution = saveSolver->getColSolution() ; const double *reducedCost = saveSolver->getReducedCost() ; int numberFixed = 0 ; int numberFixed2 = 0; #ifdef COIN_DEVELOP printf("gap %g\n", gap); #endif for (int i = 0 ; i < numberIntegers_ ; i++) { int iColumn = integerVariable_[i] ; double djValue = direction * reducedCost[iColumn] ; if (upper[iColumn] - lower[iColumn] > integerTolerance) { if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) { //printf("%d to lb on dj of %g - bounds %g %g\n", // iColumn,djValue,lower[iColumn],upper[iColumn]); saveSolver->setColUpper(iColumn, lower[iColumn]) ; numberFixed++ ; } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) { //printf("%d to ub on dj of %g - bounds %g %g\n", // iColumn,djValue,lower[iColumn],upper[iColumn]); saveSolver->setColLower(iColumn, upper[iColumn]) ; numberFixed++ ; } } else { //printf("%d has dj of %g - already fixed to %g\n", // iColumn,djValue,lower[iColumn]); numberFixed2++; } } #ifdef COIN_DEVELOP if ((specialOptions_&1) != 0) { const OsiRowCutDebugger *debugger = saveSolver->getRowCutDebugger() ; if (debugger) { printf("Contains optimal\n") ; OsiSolverInterface * temp = saveSolver->clone(); const double * solution = debugger->optimalSolution(); const double *lower = temp->getColLower() ; const double *upper = temp->getColUpper() ; int n = temp->getNumCols(); for (int i = 0; i < n; i++) { if (temp->isInteger(i)) { double value = floor(solution[i] + 0.5); assert (value >= lower[i] && value <= upper[i]); temp->setColLower(i, value); temp->setColUpper(i, value); } } temp->writeMps("reduced_fix"); delete temp; saveSolver->writeMps("reduced"); } else { abort(); } } printf("Restart could fix %d integers (%d already fixed)\n", numberFixed + numberFixed2, numberFixed2); #endif numberFixed += numberFixed2; if (numberFixed*10 < numberColumns && numberFixed*4 < numberIntegers_) tryNewSearch = false; } if (tryNewSearch) { // back to solver without cuts? OsiSolverInterface * solver2 = saveSolver->clone(); const double *lower = saveSolver->getColLower() ; const double *upper = saveSolver->getColUpper() ; for (int i = 0 ; i < numberIntegers_ ; i++) { int iColumn = integerVariable_[i] ; solver2->setColLower(iColumn, lower[iColumn]); solver2->setColUpper(iColumn, upper[iColumn]); } // swap delete saveSolver; saveSolver = solver2; double * newSolution = new double[numberColumns]; double objectiveValue = checkCutoffForRestart; // Save the best solution so far. CbcSerendipity heuristic(*this); if (bestSolution_) heuristic.setInputSolution(bestSolution_, bestObjective_); // Magic number heuristic.setFractionSmall(0.8); // `pumpTune' to stand-alone solver for explanations. heuristic.setFeasibilityPumpOptions(1008013); // Use numberNodes to say how many are original rows heuristic.setNumberNodes(continuousSolver_->getNumRows()); #ifdef COIN_DEVELOP if (continuousSolver_->getNumRows() < solver_->getNumRows()) printf("%d rows added ZZZZZ\n", solver_->getNumRows() - continuousSolver_->getNumRows()); #endif int returnCode = heuristic.smallBranchAndBound(saveSolver, -1, newSolution, objectiveValue, checkCutoffForRestart, "Reduce"); if (returnCode < 0) { #ifdef COIN_DEVELOP printf("Restart - not small enough to do search after fixing\n"); #endif delete [] newSolution; } else { // 1 for sol'n, 2 for finished, 3 for both if ((returnCode&1) != 0) { // increment number of solutions so other heuristics can test numberSolutions_++; numberHeuristicSolutions_++; lastHeuristic_ = NULL; setBestSolution(CBC_ROUNDING, objectiveValue, newSolution) ; } delete [] newSolution; #ifdef CBC_THREAD if (master_) { lockThread(); if (parallelMode() > 0) { while (master_->waitForThreadsInTree(0)) { lockThread(); double dummyBest; tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ; //unlockThread(); } } else { double dummyBest; tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ; } master_->waitForThreadsInTree(2); delete master_; master_ = NULL; masterThread_ = NULL; } #endif if (tree_->size()) { double dummyBest; tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ; } break; } } delete saveSolver; saveSolver = NULL; } } /* Check for abort on limits: node count, solution count, time, integrality gap. */ if (!(numberNodes_ < intParam_[CbcMaxNumNode] && numberSolutions_ < intParam_[CbcMaxNumSol] && !maximumSecondsReached() && !stoppedOnGap_ && !eventHappened_ && (maximumNumberIterations_ < 0 || numberIterations_ < maximumNumberIterations_))) { // out of loop break; } #ifdef BONMIN assert(!solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->mipFeasible()); #endif // Sets percentage of time when we try diving. Diving requires a bit of heap reorganisation, because // we need to replace the comparison function to dive, and that requires reordering to retain the // heap property. #define DIVE_WHEN 1000 #define DIVE_STOP 2000 int kNode = numberNodes_ % 4000; if (numberNodes_<100000 && kNode>DIVE_WHEN && kNode <= DIVE_STOP) { if (!parallelMode()) { if (kNode == DIVE_WHEN + 1 || numberConsecutiveInfeasible > 1) { CbcCompareDefault * compare = dynamic_cast (nodeCompare_); // Don't interfere if user has replaced the compare function. if (compare) { //printf("Redoing tree\n"); compare->startDive(this); numberConsecutiveInfeasible = 0; } } } } // replace current cutoff? if (cutoff > getCutoff()) { double newCutoff = getCutoff(); if (analyzeResults_) { // see if we could fix any (more) int n = 0; double * newLower = analyzeResults_; double * objLower = newLower + numberIntegers_; double * newUpper = objLower + numberIntegers_; double * objUpper = newUpper + numberIntegers_; for (int i = 0; i < numberIntegers_; i++) { if (objLower[i] > newCutoff) { n++; if (objUpper[i] > newCutoff) { newCutoff = -COIN_DBL_MAX; break; } } else if (objUpper[i] > newCutoff) { n++; } } if (newCutoff == -COIN_DBL_MAX) { COIN_DETAIL_PRINT(printf("Root analysis says finished\n")); } else if (n > numberFixedNow_) { COIN_DETAIL_PRINT(printf("%d more fixed by analysis - now %d\n", n - numberFixedNow_, n)); numberFixedNow_ = n; } } if (eventHandler) { if (!eventHandler->event(CbcEventHandler::solution)) { eventHappened_ = true; // exit } newCutoff = getCutoff(); } lockThread(); /* Clean the tree to reflect the new solution, then see if the node comparison predicate wants to make any changes. If so, call setComparison for the side effect of rebuilding the heap. */ tree_->cleanTree(this,newCutoff,bestPossibleObjective_) ; if (nodeCompare_->newSolution(this) || nodeCompare_->newSolution(this,continuousObjective_, continuousInfeasibilities_)) { tree_->setComparison(*nodeCompare_) ; } if (tree_->empty()) { continue; } unlockThread(); } cutoff = getCutoff() ; /* Periodic activities: Opportunities to + tweak the nodeCompare criteria, + check if we've closed the integrality gap enough to quit, + print a summary line to let the user know we're working */ if (numberNodes_ >= lastEvery1000) { lockThread(); #ifdef COIN_HAS_CLP // See if we want dantzig row choice goToDantzig(1000, savePivotMethod); #endif lastEvery1000 = numberNodes_ + 1000; bool redoTree = nodeCompare_->every1000Nodes(this, numberNodes_) ; #ifdef CHECK_CUT_SIZE verifyCutSize (tree_, *this); #endif // redo tree if requested if (redoTree) tree_->setComparison(*nodeCompare_) ; unlockThread(); } // Had hotstart before, now switched off if (saveCompare && !hotstartSolution_) { // hotstart switched off delete nodeCompare_; // off depth first nodeCompare_ = saveCompare; saveCompare = NULL; // redo tree lockThread(); tree_->setComparison(*nodeCompare_) ; unlockThread(); } if (numberNodes_ >= lastPrintEvery) { lastPrintEvery = numberNodes_ + printFrequency_; lockThread(); int nNodes = tree_->size() ; //MODIF PIERRE bestPossibleObjective_ = tree_->getBestPossibleObjective(); #ifdef CBC_THREAD if (parallelMode() > 0 && master_) { // need to adjust for ones not on tree int numberThreads = master_->numberThreads(); for (int i=0;ichild(i); if (child->node()) { // adjust double value = child->node()->objectiveValue(); bestPossibleObjective_ = CoinMin(bestPossibleObjective_, value); } } } #endif unlockThread(); #ifdef CLP_INVESTIGATE if (getCutoff() < 1.0e20) { if (fabs(getCutoff() - (bestObjective_ - getCutoffIncrement())) > 1.0e-6 && !parentModel_) printf("model cutoff in status %g, best %g, increment %g\n", getCutoff(), bestObjective_, getCutoffIncrement()); assert (getCutoff() < bestObjective_ - getCutoffIncrement() + 1.0e-6 + 1.0e-10*fabs(bestObjective_)); } #endif if (!intParam_[CbcPrinting]) { messageHandler()->message(CBC_STATUS, messages()) << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_ << getCurrentSeconds() << CoinMessageEol ; } else if (intParam_[CbcPrinting] == 1) { messageHandler()->message(CBC_STATUS2, messages()) << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_ << lastDepth << lastUnsatisfied << numberIterations_ << getCurrentSeconds() << CoinMessageEol ; } else if (!numberExtraIterations_) { messageHandler()->message(CBC_STATUS2, messages()) << numberNodes_ << nNodes << bestObjective_ << bestPossibleObjective_ << lastDepth << lastUnsatisfied << numberIterations_ << getCurrentSeconds() << CoinMessageEol ; } else { messageHandler()->message(CBC_STATUS3, messages()) << numberNodes_ << numberExtraNodes_ << nNodes << bestObjective_ << bestPossibleObjective_ << lastDepth << lastUnsatisfied << numberIterations_ << numberExtraIterations_ << getCurrentSeconds() << CoinMessageEol ; } if (eventHandler && !eventHandler->event(CbcEventHandler::treeStatus)) { eventHappened_ = true; // exit } } // See if can stop on gap if(canStopOnGap()) { stoppedOnGap_ = true ; } #ifdef CHECK_NODE_FULL verifyTreeNodes(tree_, *this) ; # endif # ifdef CHECK_CUT_COUNTS verifyCutCounts(tree_, *this) ; # endif /* Now we come to the meat of the loop. To create the active subproblem, we'll pop the most promising node in the live set, rebuild the subproblem it represents, and then execute the current arm of the branch to create the active subproblem. */ CbcNode * node = NULL; #ifdef CBC_THREAD if (!parallelMode() || parallelMode() == -1) { #endif node = tree_->bestNode(cutoff) ; // Possible one on tree worse than cutoff // Weird comparison function can leave ineligible nodes on tree if (!node || node->objectiveValue() > cutoff) continue; // Do main work of solving node here doOneNode(this, node, createdNode); #ifdef JJF_ZERO if (node) { if (createdNode) { printf("Node %d depth %d, created %d depth %d\n", node->nodeNumber(), node->depth(), createdNode->nodeNumber(), createdNode->depth()); } else { printf("Node %d depth %d, no created node\n", node->nodeNumber(), node->depth()); } } else if (createdNode) { printf("Node exhausted, created %d depth %d\n", createdNode->nodeNumber(), createdNode->depth()); } else { printf("Node exhausted, no created node\n"); numberConsecutiveInfeasible = 2; } #endif //if (createdNode) //numberConsecutiveInfeasible=0; //else //numberConsecutiveInfeasible++; #ifdef CBC_THREAD } else if (parallelMode() > 0) { //lockThread(); //node = tree_->bestNode(cutoff) ; // Possible one on tree worse than cutoff if (true || !node || node->objectiveValue() > cutoff) { assert (master_); if (master_) { int anyLeft = master_->waitForThreadsInTree(1); // may need to go round again if (anyLeft) { continue; } else { master_->stopThreads(-1); } } } //unlockThread(); } else { // Deterministic parallel if (tree_->size() < CoinMax(numberThreads_, 8) && !goneParallel) { node = tree_->bestNode(cutoff) ; // Possible one on tree worse than cutoff if (!node || node->objectiveValue() > cutoff) continue; // Do main work of solving node here doOneNode(this, node, createdNode); assert (createdNode); if (!createdNode->active()) { delete createdNode; createdNode = NULL; } else { // Say one more pointing to this node->nodeInfo()->increment() ; tree_->push(createdNode) ; } if (node->active()) { assert (node->nodeInfo()); if (node->nodeInfo()->numberBranchesLeft()) { tree_->push(node) ; } else { node->setActive(false); } } else { if (node->nodeInfo()) { if (!node->nodeInfo()->numberBranchesLeft()) node->nodeInfo()->allBranchesGone(); // can clean up // So will delete underlying stuff node->setActive(true); } delNode[nDeleteNode++] = node; node = NULL; } if (nDeleteNode >= MAX_DEL_NODE) { for (int i = 0; i < nDeleteNode; i++) { //printf("trying to del %d %x\n",i,delNode[i]); delete delNode[i]; //printf("done to del %d %x\n",i,delNode[i]); } nDeleteNode = 0; } } else { // Split and solve master_->deterministicParallel(); goneParallel = true; } } #endif } if (nDeleteNode) { for (int i = 0; i < nDeleteNode; i++) { delete delNode[i]; } nDeleteNode = 0; } #ifdef CBC_THREAD if (master_) { master_->stopThreads(-1); master_->waitForThreadsInTree(2); delete master_; master_ = NULL; masterThread_ = NULL; // adjust time to allow for children on some systems //dblParam_[CbcStartSeconds] -= CoinCpuTimeJustChildren(); } #endif /* End of the non-abort actions. The next block of code is executed if we've aborted because we hit one of the limits. Clean up by deleting the live set and break out of the node processing loop. Note that on an abort, node may have been pushed back onto the tree for further processing, in which case it'll be deleted in cleanTree. We need to check. */ if (!(numberNodes_ < intParam_[CbcMaxNumNode] && numberSolutions_ < intParam_[CbcMaxNumSol] && !maximumSecondsReached() && !stoppedOnGap_ && !eventHappened_ && (maximumNumberIterations_ < 0 || numberIterations_ < maximumNumberIterations_)) ) { if (tree_->size()) { double dummyBest; tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ; } delete nextRowCut_; /* order is important here: * maximumSecondsReached() should be checked before eventHappened_ and * isNodeLimitReached() should be checked after eventHappened_ * reason is, that at timelimit, eventHappened_ is set to true to make Cbc stop fast * and if Ctrl+C is hit, then the nodelimit is set to -1 to make Cbc stop */ if (stoppedOnGap_) { messageHandler()->message(CBC_GAP, messages()) << bestObjective_ - bestPossibleObjective_ << dblParam_[CbcAllowableGap] << dblParam_[CbcAllowableFractionGap]*100.0 << CoinMessageEol ; secondaryStatus_ = 2; status_ = 0 ; } else if (maximumSecondsReached()) { handler_->message(CBC_MAXTIME, messages_) << CoinMessageEol ; secondaryStatus_ = 4; status_ = 1 ; } else if (numberSolutions_ >= intParam_[CbcMaxNumSol]) { handler_->message(CBC_MAXSOLS, messages_) << CoinMessageEol ; secondaryStatus_ = 6; status_ = 1 ; } else if (isNodeLimitReached()) { handler_->message(CBC_MAXNODES, messages_) << CoinMessageEol ; secondaryStatus_ = 3; status_ = 1 ; } else if (maximumNumberIterations_ >= 0 && numberIterations_ >= maximumNumberIterations_) { handler_->message(CBC_MAXITERS, messages_) << CoinMessageEol ; secondaryStatus_ = 8; status_ = 1 ; } else { handler_->message(CBC_EVENT, messages_) << CoinMessageEol ; secondaryStatus_ = 5; status_ = 5 ; } } /* That's it, we've exhausted the search tree, or broken out of the loop because we hit some limit on evaluation. We may have got an intelligent tree so give it one more chance */ // Tell solver we are not in Branch and Cut solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL) ; tree_->endSearch(); // If we did any sub trees - did we give up on any? if ( numberStoppedSubTrees_) status_ = 1; numberNodes_ += numberExtraNodes_; numberIterations_ += numberExtraIterations_; if (eventHandler) { eventHandler->event(CbcEventHandler::endSearch); } if (!status_) { // Set best possible unless stopped on gap if (secondaryStatus_ != 2) bestPossibleObjective_ = bestObjective_; handler_->message(CBC_END_GOOD, messages_) << bestObjective_ << numberIterations_ << numberNodes_ << getCurrentSeconds() << CoinMessageEol ; } else { handler_->message(CBC_END, messages_) << bestObjective_ << bestPossibleObjective_ << numberIterations_ << numberNodes_ << getCurrentSeconds() << CoinMessageEol ; } if (numberStrongIterations_) handler_->message(CBC_STRONG_STATS, messages_) << strongInfo_[0] << numberStrongIterations_ << strongInfo_[2] << strongInfo_[1] << CoinMessageEol ; if (!numberExtraNodes_) handler_->message(CBC_OTHER_STATS, messages_) << maximumDepthActual_ << numberDJFixed_ << CoinMessageEol ; else handler_->message(CBC_OTHER_STATS2, messages_) << maximumDepthActual_ << numberDJFixed_ << numberExtraNodes_ << numberExtraIterations_ << CoinMessageEol ; if (doStatistics == 100) { for (int i = 0; i < numberObjects_; i++) { CbcSimpleIntegerDynamicPseudoCost * obj = dynamic_cast (object_[i]) ; if (obj) obj->print(); } } if (statistics_) { // report in some way int * lookup = new int[numberObjects_]; int i; for (i = 0; i < numberObjects_; i++) lookup[i] = -1; bool goodIds = false; //true; for (i = 0; i < numberObjects_; i++) { int iColumn = object_[i]->columnNumber(); if (iColumn >= 0 && iColumn < numberColumns) { if (lookup[i] == -1) { lookup[i] = iColumn; } else { goodIds = false; break; } } else { goodIds = false; break; } } if (!goodIds) { delete [] lookup; lookup = NULL; } if (doStatistics >= 3) { printf(" node parent depth column value obj inf\n"); for ( i = 0; i < numberNodes2_; i++) { statistics_[i]->print(lookup); } } if (doStatistics > 1) { // Find last solution int k; for (k = numberNodes2_ - 1; k >= 0; k--) { if (statistics_[k]->endingObjective() != COIN_DBL_MAX && !statistics_[k]->endingInfeasibility()) break; } if (k >= 0) { int depth = statistics_[k]->depth(); int * which = new int[depth+1]; for (i = depth; i >= 0; i--) { which[i] = k; k = statistics_[k]->parentNode(); } printf(" node parent depth column value obj inf\n"); for (i = 0; i <= depth; i++) { statistics_[which[i]]->print(lookup); } delete [] which; } } // now summary int maxDepth = 0; double averageSolutionDepth = 0.0; int numberSolutions = 0; double averageCutoffDepth = 0.0; double averageSolvedDepth = 0.0; int numberCutoff = 0; int numberDown = 0; int numberFirstDown = 0; double averageInfDown = 0.0; double averageObjDown = 0.0; int numberCutoffDown = 0; int numberUp = 0; int numberFirstUp = 0; double averageInfUp = 0.0; double averageObjUp = 0.0; int numberCutoffUp = 0; double averageNumberIterations1 = 0.0; double averageValue = 0.0; for ( i = 0; i < numberNodes2_; i++) { int depth = statistics_[i]->depth(); int way = statistics_[i]->way(); double value = statistics_[i]->value(); double startingObjective = statistics_[i]->startingObjective(); int startingInfeasibility = statistics_[i]->startingInfeasibility(); double endingObjective = statistics_[i]->endingObjective(); int endingInfeasibility = statistics_[i]->endingInfeasibility(); maxDepth = CoinMax(depth, maxDepth); // Only for completed averageNumberIterations1 += statistics_[i]->numberIterations(); averageValue += value; if (endingObjective != COIN_DBL_MAX && !endingInfeasibility) { numberSolutions++; averageSolutionDepth += depth; } if (endingObjective == COIN_DBL_MAX) { numberCutoff++; averageCutoffDepth += depth; if (way < 0) { numberDown++; numberCutoffDown++; if (way == -1) numberFirstDown++; } else { numberUp++; numberCutoffUp++; if (way == 1) numberFirstUp++; } } else { averageSolvedDepth += depth; if (way < 0) { numberDown++; averageInfDown += startingInfeasibility - endingInfeasibility; averageObjDown += endingObjective - startingObjective; if (way == -1) numberFirstDown++; } else { numberUp++; averageInfUp += startingInfeasibility - endingInfeasibility; averageObjUp += endingObjective - startingObjective; if (way == 1) numberFirstUp++; } } } // Now print if (numberSolutions) averageSolutionDepth /= static_cast (numberSolutions); int numberSolved = numberNodes2_ - numberCutoff; double averageNumberIterations2 = numberIterations_ - averageNumberIterations1 - numberIterationsAtContinuous; if (numberCutoff) { averageCutoffDepth /= static_cast (numberCutoff); averageNumberIterations2 /= static_cast (numberCutoff); } if (numberNodes2_) averageValue /= static_cast (numberNodes2_); if (numberSolved) { averageNumberIterations1 /= static_cast (numberSolved); averageSolvedDepth /= static_cast (numberSolved); } printf("%d solution(s) were found (by branching) at an average depth of %g\n", numberSolutions, averageSolutionDepth); printf("average value of variable being branched on was %g\n", averageValue); printf("%d nodes were cutoff at an average depth of %g with iteration count of %g\n", numberCutoff, averageCutoffDepth, averageNumberIterations2); printf("%d nodes were solved at an average depth of %g with iteration count of %g\n", numberSolved, averageSolvedDepth, averageNumberIterations1); if (numberDown) { averageInfDown /= static_cast (numberDown); averageObjDown /= static_cast (numberDown); } printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n", numberDown, numberFirstDown, numberDown - numberFirstDown, numberCutoffDown, averageInfDown, averageObjDown); if (numberUp) { averageInfUp /= static_cast (numberUp); averageObjUp /= static_cast (numberUp); } printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n", numberUp, numberFirstUp, numberUp - numberFirstUp, numberCutoffUp, averageInfUp, averageObjUp); for ( i = 0; i < numberNodes2_; i++) delete statistics_[i]; delete [] statistics_; statistics_ = NULL; maximumStatistics_ = 0; delete [] lookup; } /* If we think we have a solution, restore and confirm it with a call to setBestSolution(). We need to reset the cutoff value so as not to fathom the solution on bounds. Note that calling setBestSolution( ..., true) leaves the continuousSolver_ bounds vectors fixed at the solution value. Running resolve() here is a failsafe --- setBestSolution has already reoptimised using the continuousSolver_. If for some reason we fail to prove optimality, run the problem again after instructing the solver to tell us more. If all looks good, replace solver_ with continuousSolver_, so that the outside world will be able to obtain information about the solution using public methods. Don't replace if we are trying to save cuts */ if (bestSolution_ && (solverCharacteristics_->solverType() < 2 || solverCharacteristics_->solverType() == 4) && ((specialOptions_&8388608)==0||(specialOptions_&2048)!=0)) { setCutoff(1.0e50) ; // As best solution should be worse than cutoff // change cutoff as constraint if wanted if (cutoffRowNumber_>=0) { if (solver_->getNumRows()>cutoffRowNumber_) solver_->setRowUpper(cutoffRowNumber_,1.0e50); } // also in continuousSolver_ if (continuousSolver_) { // Solvers know about direction double direction = solver_->getObjSense(); continuousSolver_->setDblParam(OsiDualObjectiveLimit, 1.0e50*direction); } phase_ = 5; double increment = getDblParam(CbcModel::CbcCutoffIncrement) ; if ((specialOptions_&4) == 0) bestObjective_ += 100.0 * increment + 1.0e-3; // only set if we are going to solve setBestSolution(CBC_END_SOLUTION, bestObjective_, bestSolution_, 1) ; continuousSolver_->resolve() ; if (!continuousSolver_->isProvenOptimal()) { continuousSolver_->messageHandler()->setLogLevel(2) ; continuousSolver_->initialSolve() ; } delete solver_ ; // above deletes solverCharacteristics_ solverCharacteristics_ = NULL; solver_ = continuousSolver_ ; setPointers(solver_); continuousSolver_ = NULL ; } /* Clean up dangling objects. continuousSolver_ may already be toast. */ delete lastws ; if (saveObjects) { for (int i = 0; i < numberObjects_; i++) delete saveObjects[i]; delete [] saveObjects; } numberStrong_ = saveNumberStrong; numberBeforeTrust_ = saveNumberBeforeTrust; delete [] whichGenerator_ ; whichGenerator_ = NULL; delete [] lowerBefore ; delete [] upperBefore ; delete [] walkback_ ; walkback_ = NULL ; delete [] lastNodeInfo_ ; lastNodeInfo_ = NULL; delete [] lastNumberCuts_ ; lastNumberCuts_ = NULL; delete [] lastCut_; lastCut_ = NULL; delete [] addedCuts_ ; addedCuts_ = NULL ; //delete persistentInfo; // Get rid of characteristics solverCharacteristics_ = NULL; if (continuousSolver_) { delete continuousSolver_ ; continuousSolver_ = NULL ; } /* Destroy global cuts by replacing with an empty OsiCuts object. */ globalCuts_ = CbcRowCuts() ; delete globalConflictCuts_; globalConflictCuts_=NULL; if (!bestSolution_ && (specialOptions_&8388608)==0) { // make sure lp solver is infeasible int numberColumns = solver_->getNumCols(); const double * columnLower = solver_->getColLower(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (solver_->isInteger(iColumn)) solver_->setColUpper(iColumn, columnLower[iColumn]); } solver_->initialSolve(); } #ifdef COIN_HAS_CLP { OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { // Possible restore of pivot method if (savePivotMethod) { // model may have changed savePivotMethod->setModel(NULL); clpSolver->getModelPtr()->setDualRowPivotAlgorithm(*savePivotMethod); delete savePivotMethod; } clpSolver->setLargestAway(-1.0); } } #endif if ((fastNodeDepth_ >= 1000000 || (moreSpecialOptions_&33554432)!=0) && !parentModel_) { // delete object off end delete object_[numberObjects_]; if ((moreSpecialOptions_&33554432)==0) fastNodeDepth_ -= 1000000; } delete saveSolver; // Undo preprocessing performed during BaB. if (strategy_ && strategy_->preProcessState() > 0) { // undo preprocessing CglPreProcess * process = strategy_->process(); assert (process); int n = originalSolver->getNumCols(); if (bestSolution_) { delete [] bestSolution_; bestSolution_ = new double [n]; process->postProcess(*solver_); } strategy_->deletePreProcess(); // Solution now back in originalSolver delete solver_; solver_ = originalSolver; if (bestSolution_) { bestObjective_ = solver_->getObjValue() * solver_->getObjSense(); memcpy(bestSolution_, solver_->getColSolution(), n*sizeof(double)); } // put back original objects if there were any if (originalObject) { int iColumn; assert (ownObjects_); for (iColumn = 0; iColumn < numberObjects_; iColumn++) delete object_[iColumn]; delete [] object_; numberObjects_ = numberOriginalObjects; object_ = originalObject; delete [] integerVariable_; numberIntegers_ = 0; for (iColumn = 0; iColumn < n; iColumn++) { if (solver_->isInteger(iColumn)) numberIntegers_++; } integerVariable_ = new int[numberIntegers_]; numberIntegers_ = 0; for (iColumn = 0; iColumn < n; iColumn++) { if (solver_->isInteger(iColumn)) integerVariable_[numberIntegers_++] = iColumn; } } } if (flipObjective) flipModel(); #ifdef COIN_HAS_CLP { OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) clpSolver->setFakeObjective(reinterpret_cast (NULL)); } #endif moreSpecialOptions_ = saveMoreSpecialOptions; return ; } // Solve the initial LP relaxation void CbcModel::initialSolve() { assert (solver_); // Double check optimization directions line up dblParam_[CbcOptimizationDirection] = solver_->getObjSense(); // Check if bounds are all integral (as may get messed up later) checkModel(); if (!solverCharacteristics_) { OsiBabSolver * solverCharacteristics = dynamic_cast (solver_->getAuxiliaryInfo()); if (solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } else { // replace in solver OsiBabSolver defaultC; solver_->setAuxiliaryInfo(&defaultC); solverCharacteristics_ = dynamic_cast (solver_->getAuxiliaryInfo()); } } solverCharacteristics_->setSolver(solver_); solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; solver_->initialSolve(); solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo, NULL) ; if (!solver_->isProvenOptimal()) solver_->resolve(); // But set up so Jon Lee will be happy status_ = -1; secondaryStatus_ = -1; originalContinuousObjective_ = solver_->getObjValue() * solver_->getObjSense(); bestPossibleObjective_ = originalContinuousObjective_; if (solver_->isProvenDualInfeasible()) originalContinuousObjective_ = -COIN_DBL_MAX; delete [] continuousSolution_; continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(), solver_->getNumCols()); setPointers(solver_); solverCharacteristics_ = NULL; } /*! \brief Get an empty basis object Return an empty CoinWarmStartBasis object with the requested capacity, appropriate for the current solver. The object is cloned from the object cached as emptyWarmStart_. If there is no cached object, the routine queries the solver for a warm start object, empties it, and caches the result. */ CoinWarmStartBasis *CbcModel::getEmptyBasis (int ns, int na) const { CoinWarmStartBasis *emptyBasis ; /* Acquire an empty basis object, if we don't yet have one. */ if (emptyWarmStart_ == 0) { if (solver_ == 0) { throw CoinError("Cannot construct basis without solver!", "getEmptyBasis", "CbcModel") ; } emptyBasis = dynamic_cast(solver_->getEmptyWarmStart()) ; if (emptyBasis == 0) { throw CoinError( "Solver does not appear to use a basis-oriented warm start.", "getEmptyBasis", "CbcModel") ; } emptyBasis->setSize(0, 0) ; emptyWarmStart_ = dynamic_cast(emptyBasis) ; } /* Clone the empty basis object, resize it as requested, and return. */ emptyBasis = dynamic_cast(emptyWarmStart_->clone()) ; assert(emptyBasis) ; if (ns != 0 || na != 0) emptyBasis->setSize(ns, na) ; return (emptyBasis) ; } /** Default Constructor Creates an empty model without an associated solver. */ CbcModel::CbcModel() : solver_(NULL), ownership_(0x80000000), continuousSolver_(NULL), referenceSolver_(NULL), defaultHandler_(true), emptyWarmStart_(NULL), bestObjective_(COIN_DBL_MAX), bestPossibleObjective_(COIN_DBL_MAX), sumChangeObjective1_(0.0), sumChangeObjective2_(0.0), bestSolution_(NULL), savedSolutions_(NULL), currentSolution_(NULL), testSolution_(NULL), globalConflictCuts_(NULL), minimumDrop_(1.0e-4), numberSolutions_(0), numberSavedSolutions_(0), maximumSavedSolutions_(0), stateOfSearch_(0), whenCuts_(-1), hotstartSolution_(NULL), hotstartPriorities_(NULL), numberHeuristicSolutions_(0), numberNodes_(0), numberNodes2_(0), numberIterations_(0), numberSolves_(0), status_(-1), secondaryStatus_(-1), numberIntegers_(0), numberRowsAtContinuous_(0), cutoffRowNumber_(-1), maximumNumberCuts_(0), phase_(0), currentNumberCuts_(0), maximumDepth_(0), walkback_(NULL), lastNodeInfo_(NULL), lastCut_(NULL), lastDepth_(0), lastNumberCuts2_(0), maximumCuts_(0), lastNumberCuts_(NULL), addedCuts_(NULL), nextRowCut_(NULL), currentNode_(NULL), integerVariable_(NULL), integerInfo_(NULL), continuousSolution_(NULL), usedInSolution_(NULL), specialOptions_(0), moreSpecialOptions_(0), topOfTree_(NULL), subTreeModel_(NULL), heuristicModel_(NULL), numberStoppedSubTrees_(0), presolve_(0), numberStrong_(5), numberBeforeTrust_(10), numberPenalties_(20), stopNumberIterations_(-1), penaltyScaleFactor_(3.0), numberAnalyzeIterations_(0), analyzeResults_(NULL), numberInfeasibleNodes_(0), problemType_(0), printFrequency_(0), numberCutGenerators_(0), generator_(NULL), virginGenerator_(NULL), numberHeuristics_(0), heuristic_(NULL), lastHeuristic_(NULL), fastNodeDepth_(-1), eventHandler_(NULL), numberObjects_(0), object_(NULL), ownObjects_(true), originalColumns_(NULL), howOftenGlobalScan_(3), numberGlobalViolations_(0), numberExtraIterations_(0), numberExtraNodes_(0), continuousObjective_(COIN_DBL_MAX), originalContinuousObjective_(COIN_DBL_MAX), continuousInfeasibilities_(COIN_INT_MAX), maximumCutPassesAtRoot_(20), maximumCutPasses_(10), preferredWay_(0), currentPassNumber_(0), maximumWhich_(1000), maximumRows_(0), randomSeed_(-1), multipleRootTries_(0), currentDepth_(0), whichGenerator_(NULL), maximumStatistics_(0), statistics_(NULL), maximumDepthActual_(0), numberDJFixed_(0.0), probingInfo_(NULL), numberFixedAtRoot_(0), numberFixedNow_(0), stoppedOnGap_(false), eventHappened_(false), numberLongStrong_(0), numberOldActiveCuts_(0), numberNewCuts_(0), searchStrategy_(-1), strongStrategy_(0), numberStrongIterations_(0), resolveAfterTakeOffCuts_(true), maximumNumberIterations_(-1), continuousPriority_(COIN_INT_MAX), numberUpdateItems_(0), maximumNumberUpdateItems_(0), updateItems_(NULL), storedRowCuts_(NULL), numberThreads_(0), threadMode_(0), master_(NULL), masterThread_(NULL) { memset(intParam_, 0, sizeof(intParam_)); intParam_[CbcMaxNumNode] = 2147483647; intParam_[CbcMaxNumSol] = 9999999; memset(dblParam_, 0, sizeof(dblParam_)); dblParam_[CbcIntegerTolerance] = 1e-6; dblParam_[CbcCutoffIncrement] = 1e-5; dblParam_[CbcAllowableGap] = 1.0e-10; dblParam_[CbcMaximumSeconds] = 1.0e100; dblParam_[CbcCurrentCutoff] = 1.0e100; dblParam_[CbcOptimizationDirection] = 1.0; dblParam_[CbcCurrentObjectiveValue] = 1.0e100; dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100; strongInfo_[0] = 0; strongInfo_[1] = 0; strongInfo_[2] = 0; strongInfo_[3] = 0; strongInfo_[4] = 0; strongInfo_[5] = 0; strongInfo_[6] = 0; solverCharacteristics_ = NULL; nodeCompare_ = new CbcCompareDefault();; problemFeasibility_ = new CbcFeasibilityBase(); tree_ = new CbcTree(); branchingMethod_ = NULL; cutModifier_ = NULL; strategy_ = NULL; parentModel_ = NULL; cbcColLower_ = NULL; cbcColUpper_ = NULL; cbcRowLower_ = NULL; cbcRowUpper_ = NULL; cbcColSolution_ = NULL; cbcRowPrice_ = NULL; cbcReducedCost_ = NULL; cbcRowActivity_ = NULL; appData_ = NULL; handler_ = new CoinMessageHandler(); handler_->setLogLevel(2); messages_ = CbcMessage(); //eventHandler_ = new CbcEventHandler() ; } /** Constructor from solver. Creates a model complete with a clone of the solver passed as a parameter. */ CbcModel::CbcModel(const OsiSolverInterface &rhs) : continuousSolver_(NULL), referenceSolver_(NULL), defaultHandler_(true), emptyWarmStart_(NULL), bestObjective_(COIN_DBL_MAX), bestPossibleObjective_(COIN_DBL_MAX), sumChangeObjective1_(0.0), sumChangeObjective2_(0.0), globalConflictCuts_(NULL), minimumDrop_(1.0e-4), numberSolutions_(0), numberSavedSolutions_(0), maximumSavedSolutions_(0), stateOfSearch_(0), whenCuts_(-1), hotstartSolution_(NULL), hotstartPriorities_(NULL), numberHeuristicSolutions_(0), numberNodes_(0), numberNodes2_(0), numberIterations_(0), numberSolves_(0), status_(-1), secondaryStatus_(-1), numberRowsAtContinuous_(0), cutoffRowNumber_(-1), maximumNumberCuts_(0), phase_(0), currentNumberCuts_(0), maximumDepth_(0), walkback_(NULL), lastNodeInfo_(NULL), lastCut_(NULL), lastDepth_(0), lastNumberCuts2_(0), maximumCuts_(0), lastNumberCuts_(NULL), addedCuts_(NULL), nextRowCut_(NULL), currentNode_(NULL), integerInfo_(NULL), specialOptions_(0), moreSpecialOptions_(0), topOfTree_(NULL), subTreeModel_(NULL), heuristicModel_(NULL), numberStoppedSubTrees_(0), presolve_(0), numberStrong_(5), numberBeforeTrust_(10), numberPenalties_(20), stopNumberIterations_(-1), penaltyScaleFactor_(3.0), numberAnalyzeIterations_(0), analyzeResults_(NULL), numberInfeasibleNodes_(0), problemType_(0), printFrequency_(0), numberCutGenerators_(0), generator_(NULL), virginGenerator_(NULL), numberHeuristics_(0), heuristic_(NULL), lastHeuristic_(NULL), fastNodeDepth_(-1), eventHandler_(NULL), numberObjects_(0), object_(NULL), ownObjects_(true), originalColumns_(NULL), howOftenGlobalScan_(3), numberGlobalViolations_(0), numberExtraIterations_(0), numberExtraNodes_(0), continuousObjective_(COIN_DBL_MAX), originalContinuousObjective_(COIN_DBL_MAX), continuousInfeasibilities_(COIN_INT_MAX), maximumCutPassesAtRoot_(20), maximumCutPasses_(10), preferredWay_(0), currentPassNumber_(0), maximumWhich_(1000), maximumRows_(0), randomSeed_(-1), multipleRootTries_(0), currentDepth_(0), whichGenerator_(NULL), maximumStatistics_(0), statistics_(NULL), maximumDepthActual_(0), numberDJFixed_(0.0), probingInfo_(NULL), numberFixedAtRoot_(0), numberFixedNow_(0), stoppedOnGap_(false), eventHappened_(false), numberLongStrong_(0), numberOldActiveCuts_(0), numberNewCuts_(0), searchStrategy_(-1), strongStrategy_(0), numberStrongIterations_(0), resolveAfterTakeOffCuts_(true), maximumNumberIterations_(-1), continuousPriority_(COIN_INT_MAX), numberUpdateItems_(0), maximumNumberUpdateItems_(0), updateItems_(NULL), storedRowCuts_(NULL), numberThreads_(0), threadMode_(0), master_(NULL), masterThread_(NULL) { memset(intParam_, 0, sizeof(intParam_)); intParam_[CbcMaxNumNode] = 2147483647; intParam_[CbcMaxNumSol] = 9999999; memset(dblParam_, 0, sizeof(dblParam_)); dblParam_[CbcIntegerTolerance] = 1e-6; dblParam_[CbcCutoffIncrement] = 1e-5; dblParam_[CbcAllowableGap] = 1.0e-10; dblParam_[CbcMaximumSeconds] = 1.0e100; dblParam_[CbcCurrentCutoff] = 1.0e100; dblParam_[CbcOptimizationDirection] = 1.0; dblParam_[CbcCurrentObjectiveValue] = 1.0e100; dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100; strongInfo_[0] = 0; strongInfo_[1] = 0; strongInfo_[2] = 0; strongInfo_[3] = 0; strongInfo_[4] = 0; strongInfo_[5] = 0; strongInfo_[6] = 0; solverCharacteristics_ = NULL; nodeCompare_ = new CbcCompareDefault();; problemFeasibility_ = new CbcFeasibilityBase(); tree_ = new CbcTree(); branchingMethod_ = NULL; cutModifier_ = NULL; strategy_ = NULL; parentModel_ = NULL; appData_ = NULL; solver_ = rhs.clone(); handler_ = new CoinMessageHandler(); if (!solver_->defaultHandler()&& solver_->messageHandler()->logLevel(0)!=-1000) passInMessageHandler(solver_->messageHandler()); handler_->setLogLevel(2); messages_ = CbcMessage(); //eventHandler_ = new CbcEventHandler() ; referenceSolver_ = solver_->clone(); ownership_ = 0x80000000; cbcColLower_ = NULL; cbcColUpper_ = NULL; cbcRowLower_ = NULL; cbcRowUpper_ = NULL; cbcColSolution_ = NULL; cbcRowPrice_ = NULL; cbcReducedCost_ = NULL; cbcRowActivity_ = NULL; // Initialize solution and integer variable vectors bestSolution_ = NULL; // to say no solution found savedSolutions_ = NULL; numberIntegers_ = 0; int numberColumns = solver_->getNumCols(); int iColumn; if (numberColumns) { // Space for current solution currentSolution_ = new double[numberColumns]; continuousSolution_ = new double[numberColumns]; usedInSolution_ = new int[numberColumns]; CoinZeroN(usedInSolution_, numberColumns); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if ( solver_->isInteger(iColumn)) numberIntegers_++; } } else { // empty model currentSolution_ = NULL; continuousSolution_ = NULL; usedInSolution_ = NULL; } testSolution_ = currentSolution_; if (numberIntegers_) { integerVariable_ = new int [numberIntegers_]; numberIntegers_ = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if ( solver_->isInteger(iColumn)) integerVariable_[numberIntegers_++] = iColumn; } } else { integerVariable_ = NULL; } } static int * resizeInt(int * array,int oldLength, int newLength) { if (!array) return NULL; assert (newLength>oldLength); int * newArray = new int [newLength]; memcpy(newArray,array,oldLength*sizeof(int)); delete [] array; memset(newArray+oldLength,0,(newLength-oldLength)*sizeof(int)); return newArray; } static double * resizeDouble(double * array,int oldLength, int newLength) { if (!array) return NULL; assert (newLength>oldLength); double * newArray = new double [newLength]; memcpy(newArray,array,oldLength*sizeof(double)); delete [] array; memset(newArray+oldLength,0,(newLength-oldLength)*sizeof(double)); return newArray; } /* Assign a solver to the model (model assumes ownership) The integer variable vector is initialized if it's not already present. If deleteSolver then current solver deleted (if model owned) Assuming ownership matches usage in OsiSolverInterface (cf. assignProblem, loadProblem). TODO: What to do about solver parameters? A simple copy likely won't do it, because the SI must push the settings into the underlying solver. In the context of switching solvers in cbc, this means that command line settings will get lost. Stash the command line somewhere and reread it here, maybe? TODO: More generally, how much state should be transferred from the old solver to the new solver? Best perhaps to see how usage develops. What's done here mimics the CbcModel(OsiSolverInterface) constructor. */ void CbcModel::assignSolver(OsiSolverInterface *&solver, bool deleteSolver) { // resize stuff if exists if (solver && solver_) { int nOld = solver_->getNumCols(); int nNew = solver->getNumCols(); if (nNew > nOld) { originalColumns_ = resizeInt(originalColumns_,nOld,nNew); usedInSolution_ = resizeInt(usedInSolution_,nOld,nNew); continuousSolution_ = resizeDouble(continuousSolution_,nOld,nNew); hotstartSolution_ = resizeDouble(hotstartSolution_,nOld,nNew); bestSolution_ = resizeDouble(bestSolution_,nOld,nNew); currentSolution_ = resizeDouble(currentSolution_,nOld,nNew); if (savedSolutions_) { for (int i = 0; i < maximumSavedSolutions_; i++) savedSolutions_[i] = resizeDouble(savedSolutions_[i],nOld,nNew); } } } // Keep the current message level for solver (if solver exists) if (solver_) solver->messageHandler()->setLogLevel(solver_->messageHandler()->logLevel()) ; if (modelOwnsSolver() && deleteSolver) { solverCharacteristics_ = NULL; delete solver_ ; } solver_ = solver; solver = NULL ; setModelOwnsSolver(true) ; /* Basis information is solver-specific. */ if (emptyWarmStart_) { delete emptyWarmStart_ ; emptyWarmStart_ = 0 ; } bestSolutionBasis_ = CoinWarmStartBasis(); /* Initialize integer variable vector. */ numberIntegers_ = 0; int numberColumns = solver_->getNumCols(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if ( solver_->isInteger(iColumn)) numberIntegers_++; } delete [] integerVariable_; if (numberIntegers_) { integerVariable_ = new int [numberIntegers_]; numberIntegers_ = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if ( solver_->isInteger(iColumn)) integerVariable_[numberIntegers_++] = iColumn; } } else { integerVariable_ = NULL; } return ; } // Cloning method CbcModel *CbcModel::clone (bool cloneHandler) { return new CbcModel (*this, cloneHandler); } // Copy constructor. CbcModel::CbcModel(const CbcModel & rhs, bool cloneHandler) : continuousSolver_(NULL), referenceSolver_(NULL), defaultHandler_(rhs.defaultHandler_), emptyWarmStart_(NULL), bestObjective_(rhs.bestObjective_), bestPossibleObjective_(rhs.bestPossibleObjective_), sumChangeObjective1_(rhs.sumChangeObjective1_), sumChangeObjective2_(rhs.sumChangeObjective2_), globalConflictCuts_(NULL), minimumDrop_(rhs.minimumDrop_), numberSolutions_(rhs.numberSolutions_), numberSavedSolutions_(rhs.numberSavedSolutions_), maximumSavedSolutions_(rhs.maximumSavedSolutions_), stateOfSearch_(rhs.stateOfSearch_), whenCuts_(rhs.whenCuts_), numberHeuristicSolutions_(rhs.numberHeuristicSolutions_), numberNodes_(rhs.numberNodes_), numberNodes2_(rhs.numberNodes2_), numberIterations_(rhs.numberIterations_), numberSolves_(rhs.numberSolves_), status_(rhs.status_), secondaryStatus_(rhs.secondaryStatus_), specialOptions_(rhs.specialOptions_), moreSpecialOptions_(rhs.moreSpecialOptions_), topOfTree_(NULL), subTreeModel_(rhs.subTreeModel_), heuristicModel_(NULL), numberStoppedSubTrees_(rhs.numberStoppedSubTrees_), presolve_(rhs.presolve_), numberStrong_(rhs.numberStrong_), numberBeforeTrust_(rhs.numberBeforeTrust_), numberPenalties_(rhs.numberPenalties_), stopNumberIterations_(rhs.stopNumberIterations_), penaltyScaleFactor_(rhs.penaltyScaleFactor_), numberAnalyzeIterations_(rhs.numberAnalyzeIterations_), analyzeResults_(NULL), numberInfeasibleNodes_(rhs.numberInfeasibleNodes_), problemType_(rhs.problemType_), printFrequency_(rhs.printFrequency_), fastNodeDepth_(rhs.fastNodeDepth_), howOftenGlobalScan_(rhs.howOftenGlobalScan_), numberGlobalViolations_(rhs.numberGlobalViolations_), numberExtraIterations_(rhs.numberExtraIterations_), numberExtraNodes_(rhs.numberExtraNodes_), continuousObjective_(rhs.continuousObjective_), originalContinuousObjective_(rhs.originalContinuousObjective_), continuousInfeasibilities_(rhs.continuousInfeasibilities_), maximumCutPassesAtRoot_(rhs.maximumCutPassesAtRoot_), maximumCutPasses_( rhs.maximumCutPasses_), preferredWay_(rhs.preferredWay_), currentPassNumber_(rhs.currentPassNumber_), maximumWhich_(rhs.maximumWhich_), maximumRows_(0), randomSeed_(rhs.randomSeed_), multipleRootTries_(rhs.multipleRootTries_), currentDepth_(0), whichGenerator_(NULL), maximumStatistics_(0), statistics_(NULL), maximumDepthActual_(0), numberDJFixed_(0.0), probingInfo_(NULL), numberFixedAtRoot_(rhs.numberFixedAtRoot_), numberFixedNow_(rhs.numberFixedNow_), stoppedOnGap_(rhs.stoppedOnGap_), eventHappened_(rhs.eventHappened_), numberLongStrong_(rhs.numberLongStrong_), numberOldActiveCuts_(rhs.numberOldActiveCuts_), numberNewCuts_(rhs.numberNewCuts_), searchStrategy_(rhs.searchStrategy_), strongStrategy_(rhs.strongStrategy_), numberStrongIterations_(rhs.numberStrongIterations_), resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_), maximumNumberIterations_(rhs.maximumNumberIterations_), continuousPriority_(rhs.continuousPriority_), numberUpdateItems_(rhs.numberUpdateItems_), maximumNumberUpdateItems_(rhs.maximumNumberUpdateItems_), updateItems_(NULL), storedRowCuts_(NULL), numberThreads_(rhs.numberThreads_), threadMode_(rhs.threadMode_), master_(NULL), masterThread_(NULL) { memcpy(intParam_, rhs.intParam_, sizeof(intParam_)); memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_)); strongInfo_[0] = rhs.strongInfo_[0]; strongInfo_[1] = rhs.strongInfo_[1]; strongInfo_[2] = rhs.strongInfo_[2]; strongInfo_[3] = rhs.strongInfo_[3]; strongInfo_[4] = rhs.strongInfo_[4]; strongInfo_[5] = rhs.strongInfo_[5]; strongInfo_[6] = rhs.strongInfo_[6]; solverCharacteristics_ = NULL; if (rhs.emptyWarmStart_) emptyWarmStart_ = rhs.emptyWarmStart_->clone() ; if (defaultHandler_ || cloneHandler) { handler_ = new CoinMessageHandler(); handler_->setLogLevel(2); } else { handler_ = rhs.handler_; } messageHandler()->setLogLevel(rhs.messageHandler()->logLevel()); numberCutGenerators_ = rhs.numberCutGenerators_; if (numberCutGenerators_) { generator_ = new CbcCutGenerator * [numberCutGenerators_]; virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_]; int i; for (i = 0; i < numberCutGenerators_; i++) { generator_[i] = new CbcCutGenerator(*rhs.generator_[i]); virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]); } } else { generator_ = NULL; virginGenerator_ = NULL; } globalCuts_ = rhs.globalCuts_; numberHeuristics_ = rhs.numberHeuristics_; if (numberHeuristics_) { heuristic_ = new CbcHeuristic * [numberHeuristics_]; int i; for (i = 0; i < numberHeuristics_; i++) { heuristic_[i] = rhs.heuristic_[i]->clone(); } } else { heuristic_ = NULL; } lastHeuristic_ = NULL; if (rhs.eventHandler_) { eventHandler_ = rhs.eventHandler_->clone() ; } else { eventHandler_ = NULL ; } ownObjects_ = rhs.ownObjects_; if (ownObjects_) { numberObjects_ = rhs.numberObjects_; if (numberObjects_) { object_ = new OsiObject * [numberObjects_]; int i; for (i = 0; i < numberObjects_; i++) { object_[i] = (rhs.object_[i])->clone(); CbcObject * obj = dynamic_cast (object_[i]) ; // Could be OsiObjects if (obj) obj->setModel(this); } } else { object_ = NULL; } } else { // assume will be redone numberObjects_ = 0; object_ = NULL; } if (rhs.referenceSolver_) referenceSolver_ = rhs.referenceSolver_->clone(); else referenceSolver_ = NULL; solver_ = rhs.solver_->clone(); if (rhs.originalColumns_) { int numberColumns = solver_->getNumCols(); originalColumns_ = new int [numberColumns]; memcpy(originalColumns_, rhs.originalColumns_, numberColumns*sizeof(int)); } else { originalColumns_ = NULL; } if (maximumNumberUpdateItems_) { updateItems_ = new CbcObjectUpdateData [maximumNumberUpdateItems_]; for (int i = 0; i < maximumNumberUpdateItems_; i++) updateItems_[i] = rhs.updateItems_[i]; } if (maximumWhich_ && rhs.whichGenerator_) whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_, maximumWhich_); nodeCompare_ = rhs.nodeCompare_->clone(); problemFeasibility_ = rhs.problemFeasibility_->clone(); tree_ = rhs.tree_->clone(); if (rhs.branchingMethod_) branchingMethod_ = rhs.branchingMethod_->clone(); else branchingMethod_ = NULL; if (rhs.cutModifier_) cutModifier_ = rhs.cutModifier_->clone(); else cutModifier_ = NULL; cbcColLower_ = NULL; cbcColUpper_ = NULL; cbcRowLower_ = NULL; cbcRowUpper_ = NULL; cbcColSolution_ = NULL; cbcRowPrice_ = NULL; cbcReducedCost_ = NULL; cbcRowActivity_ = NULL; if (rhs.strategy_) strategy_ = rhs.strategy_->clone(); else strategy_ = NULL; parentModel_ = rhs.parentModel_; appData_ = rhs.appData_; messages_ = rhs.messages_; ownership_ = rhs.ownership_ | 0x80000000; messageHandler()->setLogLevel(rhs.messageHandler()->logLevel()); numberIntegers_ = rhs.numberIntegers_; randomNumberGenerator_ = rhs.randomNumberGenerator_; if (numberIntegers_) { integerVariable_ = new int [numberIntegers_]; memcpy(integerVariable_, rhs.integerVariable_, numberIntegers_*sizeof(int)); integerInfo_ = CoinCopyOfArray(rhs.integerInfo_, solver_->getNumCols()); } else { integerVariable_ = NULL; integerInfo_ = NULL; } if (rhs.hotstartSolution_) { int numberColumns = solver_->getNumCols(); hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_, numberColumns); hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns); } else { hotstartSolution_ = NULL; hotstartPriorities_ = NULL; } if (rhs.bestSolution_) { int numberColumns = solver_->getNumCols(); bestSolution_ = new double[numberColumns]; memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double)); } else { bestSolution_ = NULL; } int numberColumns = solver_->getNumCols(); if (maximumSavedSolutions_ && rhs.savedSolutions_) { savedSolutions_ = new double * [maximumSavedSolutions_]; for (int i = 0; i < maximumSavedSolutions_; i++) savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2); } else { savedSolutions_ = NULL; } // Space for current solution currentSolution_ = new double[numberColumns]; continuousSolution_ = new double[numberColumns]; usedInSolution_ = new int[numberColumns]; CoinZeroN(usedInSolution_, numberColumns); testSolution_ = currentSolution_; numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_; cutoffRowNumber_ = rhs.cutoffRowNumber_; maximumNumberCuts_ = rhs.maximumNumberCuts_; phase_ = rhs.phase_; currentNumberCuts_ = rhs.currentNumberCuts_; maximumDepth_ = rhs.maximumDepth_; // These are only used as temporary arrays so need not be filled if (maximumNumberCuts_) { addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_]; } else { addedCuts_ = NULL; } bestSolutionBasis_ = rhs.bestSolutionBasis_; nextRowCut_ = NULL; currentNode_ = NULL; if (maximumDepth_) { walkback_ = new CbcNodeInfo * [maximumDepth_]; lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ; lastNumberCuts_ = new int [maximumDepth_] ; } else { walkback_ = NULL; lastNodeInfo_ = NULL; lastNumberCuts_ = NULL; } maximumCuts_ = rhs.maximumCuts_; if (maximumCuts_) { lastCut_ = new const OsiRowCut * [maximumCuts_] ; } else { lastCut_ = NULL; } synchronizeModel(); if (cloneHandler && !defaultHandler_) { delete handler_; CoinMessageHandler * handler = rhs.handler_->clone(); passInMessageHandler(handler); } } // Assignment operator CbcModel & CbcModel::operator=(const CbcModel & rhs) { if (this != &rhs) { if (modelOwnsSolver()) { solverCharacteristics_ = NULL; delete solver_; solver_ = NULL; } gutsOfDestructor(); if (defaultHandler_) { delete handler_; handler_ = NULL; } defaultHandler_ = rhs.defaultHandler_; if (defaultHandler_) { handler_ = new CoinMessageHandler(); handler_->setLogLevel(2); } else { handler_ = rhs.handler_; } messages_ = rhs.messages_; messageHandler()->setLogLevel(rhs.messageHandler()->logLevel()); if (rhs.solver_) { solver_ = rhs.solver_->clone() ; } else { solver_ = 0 ; } ownership_ = 0x80000000; delete continuousSolver_ ; if (rhs.continuousSolver_) { continuousSolver_ = rhs.continuousSolver_->clone() ; } else { continuousSolver_ = 0 ; } delete referenceSolver_; if (rhs.referenceSolver_) { referenceSolver_ = rhs.referenceSolver_->clone() ; } else { referenceSolver_ = NULL ; } delete emptyWarmStart_ ; if (rhs.emptyWarmStart_) { emptyWarmStart_ = rhs.emptyWarmStart_->clone() ; } else { emptyWarmStart_ = 0 ; } bestObjective_ = rhs.bestObjective_; bestPossibleObjective_ = rhs.bestPossibleObjective_; sumChangeObjective1_ = rhs.sumChangeObjective1_; sumChangeObjective2_ = rhs.sumChangeObjective2_; delete [] bestSolution_; if (rhs.bestSolution_) { int numberColumns = rhs.getNumCols(); bestSolution_ = new double[numberColumns]; memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double)); } else { bestSolution_ = NULL; } for (int i = 0; i < maximumSavedSolutions_; i++) delete [] savedSolutions_[i]; delete [] savedSolutions_; savedSolutions_ = NULL; int numberColumns = rhs.getNumCols(); if (numberColumns) { // Space for current solution currentSolution_ = new double[numberColumns]; continuousSolution_ = new double[numberColumns]; usedInSolution_ = new int[numberColumns]; CoinZeroN(usedInSolution_, numberColumns); } else { currentSolution_ = NULL; continuousSolution_ = NULL; usedInSolution_ = NULL; } if (maximumSavedSolutions_) { savedSolutions_ = new double * [maximumSavedSolutions_]; for (int i = 0; i < maximumSavedSolutions_; i++) savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], numberColumns + 2); } else { savedSolutions_ = NULL; } testSolution_ = currentSolution_; minimumDrop_ = rhs.minimumDrop_; numberSolutions_ = rhs.numberSolutions_; numberSavedSolutions_ = rhs.numberSavedSolutions_; maximumSavedSolutions_ = rhs.maximumSavedSolutions_; stateOfSearch_ = rhs.stateOfSearch_; whenCuts_ = rhs.whenCuts_; numberHeuristicSolutions_ = rhs.numberHeuristicSolutions_; numberNodes_ = rhs.numberNodes_; numberNodes2_ = rhs.numberNodes2_; numberIterations_ = rhs.numberIterations_; numberSolves_ = rhs.numberSolves_; status_ = rhs.status_; secondaryStatus_ = rhs.secondaryStatus_; specialOptions_ = rhs.specialOptions_; moreSpecialOptions_ = rhs.moreSpecialOptions_; subTreeModel_ = rhs.subTreeModel_; heuristicModel_ = NULL; numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_; presolve_ = rhs.presolve_; numberStrong_ = rhs.numberStrong_; numberBeforeTrust_ = rhs.numberBeforeTrust_; numberPenalties_ = rhs.numberPenalties_; stopNumberIterations_ = rhs.stopNumberIterations_; penaltyScaleFactor_ = rhs.penaltyScaleFactor_; numberAnalyzeIterations_ = rhs.numberAnalyzeIterations_; delete [] analyzeResults_; analyzeResults_ = NULL; numberInfeasibleNodes_ = rhs.numberInfeasibleNodes_; problemType_ = rhs.problemType_; printFrequency_ = rhs.printFrequency_; howOftenGlobalScan_ = rhs.howOftenGlobalScan_; numberGlobalViolations_ = rhs.numberGlobalViolations_; numberExtraIterations_ = rhs.numberExtraIterations_; numberExtraNodes_ = rhs.numberExtraNodes_; continuousObjective_ = rhs.continuousObjective_; originalContinuousObjective_ = rhs.originalContinuousObjective_; continuousInfeasibilities_ = rhs.continuousInfeasibilities_; maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_; maximumCutPasses_ = rhs.maximumCutPasses_; randomSeed_ = rhs.randomSeed_; multipleRootTries_ = rhs.multipleRootTries_; preferredWay_ = rhs.preferredWay_; currentPassNumber_ = rhs.currentPassNumber_; memcpy(intParam_, rhs.intParam_, sizeof(intParam_)); memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_)); globalCuts_ = rhs.globalCuts_; delete globalConflictCuts_; globalConflictCuts_=NULL; int i; for (i = 0; i < numberCutGenerators_; i++) { delete generator_[i]; delete virginGenerator_[i]; } delete [] generator_; delete [] virginGenerator_; delete [] heuristic_; maximumWhich_ = rhs.maximumWhich_; delete [] whichGenerator_; whichGenerator_ = NULL; if (maximumWhich_ && rhs.whichGenerator_) whichGenerator_ = CoinCopyOfArray(rhs.whichGenerator_, maximumWhich_); maximumRows_ = 0; currentDepth_ = 0; randomNumberGenerator_ = rhs.randomNumberGenerator_; workingBasis_ = CoinWarmStartBasis(); for (i = 0; i < maximumStatistics_; i++) delete statistics_[i]; delete [] statistics_; maximumStatistics_ = 0; statistics_ = NULL; delete probingInfo_; probingInfo_ = NULL; numberFixedAtRoot_ = rhs.numberFixedAtRoot_; numberFixedNow_ = rhs.numberFixedNow_; stoppedOnGap_ = rhs.stoppedOnGap_; eventHappened_ = rhs.eventHappened_; numberLongStrong_ = rhs.numberLongStrong_; numberOldActiveCuts_ = rhs.numberOldActiveCuts_; numberNewCuts_ = rhs.numberNewCuts_; resolveAfterTakeOffCuts_ = rhs.resolveAfterTakeOffCuts_; maximumNumberIterations_ = rhs.maximumNumberIterations_; continuousPriority_ = rhs.continuousPriority_; numberUpdateItems_ = rhs.numberUpdateItems_; maximumNumberUpdateItems_ = rhs.maximumNumberUpdateItems_; delete [] updateItems_; if (maximumNumberUpdateItems_) { updateItems_ = new CbcObjectUpdateData [maximumNumberUpdateItems_]; for (i = 0; i < maximumNumberUpdateItems_; i++) updateItems_[i] = rhs.updateItems_[i]; } else { updateItems_ = NULL; } numberThreads_ = rhs.numberThreads_; threadMode_ = rhs.threadMode_; delete master_; master_ = NULL; masterThread_ = NULL; searchStrategy_ = rhs.searchStrategy_; strongStrategy_ = rhs.strongStrategy_; numberStrongIterations_ = rhs.numberStrongIterations_; strongInfo_[0] = rhs.strongInfo_[0]; strongInfo_[1] = rhs.strongInfo_[1]; strongInfo_[2] = rhs.strongInfo_[2]; strongInfo_[3] = rhs.strongInfo_[3]; strongInfo_[4] = rhs.strongInfo_[4]; strongInfo_[5] = rhs.strongInfo_[5]; strongInfo_[6] = rhs.strongInfo_[6]; solverCharacteristics_ = NULL; lastHeuristic_ = NULL; numberCutGenerators_ = rhs.numberCutGenerators_; if (numberCutGenerators_) { generator_ = new CbcCutGenerator * [numberCutGenerators_]; virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_]; int i; for (i = 0; i < numberCutGenerators_; i++) { generator_[i] = new CbcCutGenerator(*rhs.generator_[i]); virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]); } } else { generator_ = NULL; virginGenerator_ = NULL; } numberHeuristics_ = rhs.numberHeuristics_; if (numberHeuristics_) { heuristic_ = new CbcHeuristic * [numberHeuristics_]; memcpy(heuristic_, rhs.heuristic_, numberHeuristics_*sizeof(CbcHeuristic *)); } else { heuristic_ = NULL; } lastHeuristic_ = NULL; if (eventHandler_) delete eventHandler_ ; if (rhs.eventHandler_) { eventHandler_ = rhs.eventHandler_->clone() ; } else { eventHandler_ = NULL ; } fastNodeDepth_ = rhs.fastNodeDepth_; if (ownObjects_) { for (i = 0; i < numberObjects_; i++) delete object_[i]; delete [] object_; numberObjects_ = rhs.numberObjects_; if (numberObjects_) { object_ = new OsiObject * [numberObjects_]; int i; for (i = 0; i < numberObjects_; i++) object_[i] = (rhs.object_[i])->clone(); } else { object_ = NULL; } } else { // assume will be redone numberObjects_ = 0; object_ = NULL; } delete [] originalColumns_; if (rhs.originalColumns_) { int numberColumns = rhs.getNumCols(); originalColumns_ = new int [numberColumns]; memcpy(originalColumns_, rhs.originalColumns_, numberColumns*sizeof(int)); } else { originalColumns_ = NULL; } nodeCompare_ = rhs.nodeCompare_->clone(); problemFeasibility_ = rhs.problemFeasibility_->clone(); delete tree_; tree_ = rhs.tree_->clone(); if (rhs.branchingMethod_) branchingMethod_ = rhs.branchingMethod_->clone(); else branchingMethod_ = NULL; if (rhs.cutModifier_) cutModifier_ = rhs.cutModifier_->clone(); else cutModifier_ = NULL; delete strategy_; if (rhs.strategy_) strategy_ = rhs.strategy_->clone(); else strategy_ = NULL; parentModel_ = rhs.parentModel_; appData_ = rhs.appData_; delete [] integerVariable_; numberIntegers_ = rhs.numberIntegers_; if (numberIntegers_) { integerVariable_ = new int [numberIntegers_]; memcpy(integerVariable_, rhs.integerVariable_, numberIntegers_*sizeof(int)); integerInfo_ = CoinCopyOfArray(rhs.integerInfo_, rhs.getNumCols()); } else { integerVariable_ = NULL; integerInfo_ = NULL; } if (rhs.hotstartSolution_) { int numberColumns = solver_->getNumCols(); hotstartSolution_ = CoinCopyOfArray(rhs.hotstartSolution_, numberColumns); hotstartPriorities_ = CoinCopyOfArray(rhs.hotstartPriorities_, numberColumns); } else { hotstartSolution_ = NULL; hotstartPriorities_ = NULL; } numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_; cutoffRowNumber_ = rhs.cutoffRowNumber_; maximumNumberCuts_ = rhs.maximumNumberCuts_; phase_ = rhs.phase_; currentNumberCuts_ = rhs.currentNumberCuts_; maximumDepth_ = rhs.maximumDepth_; delete [] addedCuts_; delete [] walkback_; // These are only used as temporary arrays so need not be filled if (maximumNumberCuts_) { addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_]; } else { addedCuts_ = NULL; } delete [] lastNodeInfo_ ; delete [] lastNumberCuts_ ; delete [] lastCut_; bestSolutionBasis_ = rhs.bestSolutionBasis_; nextRowCut_ = NULL; currentNode_ = NULL; if (maximumDepth_) { walkback_ = new CbcNodeInfo * [maximumDepth_]; lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ; lastNumberCuts_ = new int [maximumDepth_] ; } else { walkback_ = NULL; lastNodeInfo_ = NULL; lastNumberCuts_ = NULL; } maximumCuts_ = rhs.maximumCuts_; if (maximumCuts_) { lastCut_ = new const OsiRowCut * [maximumCuts_] ; } else { lastCut_ = NULL; } synchronizeModel(); cbcColLower_ = NULL; cbcColUpper_ = NULL; cbcRowLower_ = NULL; cbcRowUpper_ = NULL; cbcColSolution_ = NULL; cbcRowPrice_ = NULL; cbcReducedCost_ = NULL; cbcRowActivity_ = NULL; } return *this; } // Destructor CbcModel::~CbcModel () { if (defaultHandler_) { delete handler_; handler_ = NULL; } delete tree_; tree_ = NULL; if (modelOwnsSolver()) { delete solver_; solver_ = NULL; } gutsOfDestructor(); delete eventHandler_ ; eventHandler_ = NULL ; #ifdef CBC_THREAD // Get rid of all threaded stuff delete master_; #endif } // Clears out as much as possible (except solver) void CbcModel::gutsOfDestructor() { delete referenceSolver_; referenceSolver_ = NULL; int i; for (i = 0; i < numberCutGenerators_; i++) { delete generator_[i]; delete virginGenerator_[i]; } delete [] generator_; delete [] virginGenerator_; generator_ = NULL; virginGenerator_ = NULL; for (i = 0; i < numberHeuristics_; i++) delete heuristic_[i]; delete [] heuristic_; heuristic_ = NULL; delete nodeCompare_; nodeCompare_ = NULL; delete problemFeasibility_; problemFeasibility_ = NULL; delete [] originalColumns_; originalColumns_ = NULL; delete strategy_; delete [] updateItems_; updateItems_ = NULL; numberUpdateItems_ = 0; maximumNumberUpdateItems_ = 0; gutsOfDestructor2(); } // Clears out enough to reset CbcModel void CbcModel::gutsOfDestructor2() { delete [] integerInfo_; integerInfo_ = NULL; delete [] integerVariable_; integerVariable_ = NULL; int i; if (ownObjects_) { for (i = 0; i < numberObjects_; i++) delete object_[i]; delete [] object_; } ownObjects_ = true; object_ = NULL; numberIntegers_ = 0; numberObjects_ = 0; // Below here is whatever consensus is ownership_ = 0x80000000; delete branchingMethod_; branchingMethod_ = NULL; delete cutModifier_; cutModifier_ = NULL; topOfTree_ = NULL; resetModel(); } // Clears out enough to reset CbcModel void CbcModel::resetModel() { delete emptyWarmStart_ ; emptyWarmStart_ = NULL; delete continuousSolver_; continuousSolver_ = NULL; numberSavedSolutions_ = 0; delete [] bestSolution_; bestSolution_ = NULL; if (savedSolutions_) { for (int i = 0; i < maximumSavedSolutions_; i++) delete [] savedSolutions_[i]; delete [] savedSolutions_; savedSolutions_ = NULL; } delete [] currentSolution_; currentSolution_ = NULL; delete [] continuousSolution_; continuousSolution_ = NULL; solverCharacteristics_ = NULL; delete [] usedInSolution_; usedInSolution_ = NULL; testSolution_ = NULL; lastHeuristic_ = NULL; delete [] addedCuts_; addedCuts_ = NULL; nextRowCut_ = NULL; currentNode_ = NULL; delete [] walkback_; walkback_ = NULL; delete [] lastNodeInfo_ ; lastNodeInfo_ = NULL; delete [] lastNumberCuts_ ; lastNumberCuts_ = NULL; delete [] lastCut_; lastCut_ = NULL; delete [] whichGenerator_; whichGenerator_ = NULL; for (int i = 0; i < maximumStatistics_; i++) delete statistics_[i]; delete [] statistics_; statistics_ = NULL; maximumDepthActual_ = 0; numberDJFixed_ = 0.0; if (probingInfo_) { delete probingInfo_; probingInfo_ = NULL; if (!generator_) numberCutGenerators_=0; // also get rid of cut generator int n=0; for (int i = 0; i < numberCutGenerators_; i++) { CglImplication * cutGen; cutGen = dynamic_cast(generator_[i]->generator()); if (!cutGen) { generator_[n]=generator_[i]; virginGenerator_[n]=virginGenerator_[i]; n++; } else { cutGen->setProbingInfo(NULL); delete generator_[i]; cutGen = dynamic_cast(virginGenerator_[i]->generator()); assert (cutGen); cutGen->setProbingInfo(NULL); delete virginGenerator_[i]; } } numberCutGenerators_=n; } maximumStatistics_ = 0; delete [] analyzeResults_; analyzeResults_ = NULL; bestObjective_ = COIN_DBL_MAX; bestPossibleObjective_ = COIN_DBL_MAX; sumChangeObjective1_ = 0.0; sumChangeObjective2_ = 0.0; numberSolutions_ = 0; stateOfSearch_ = 0; delete [] hotstartSolution_; hotstartSolution_ = NULL; delete [] hotstartPriorities_; hotstartPriorities_ = NULL; numberHeuristicSolutions_ = 0; numberNodes_ = 0; numberNodes2_ = 0; numberIterations_ = 0; numberSolves_ = 0; status_ = -1; secondaryStatus_ = -1; maximumNumberCuts_ = 0; phase_ = 0; currentNumberCuts_ = 0; maximumDepth_ = 0; nextRowCut_ = NULL; currentNode_ = NULL; // clear out tree if (tree_ && tree_->size()) tree_->cleanTree(this, -1.0e100, bestPossibleObjective_) ; subTreeModel_ = NULL; heuristicModel_ = NULL; numberStoppedSubTrees_ = 0; numberInfeasibleNodes_ = 0; numberGlobalViolations_ = 0; numberExtraIterations_ = 0; numberExtraNodes_ = 0; continuousObjective_ = 0.0; originalContinuousObjective_ = 0.0; continuousInfeasibilities_ = 0; numberFixedAtRoot_ = 0; numberFixedNow_ = 0; stoppedOnGap_ = false; eventHappened_ = false; numberLongStrong_ = 0; numberOldActiveCuts_ = 0; numberNewCuts_ = 0; searchStrategy_ = -1; strongStrategy_ = 0; numberStrongIterations_ = 0; // Parameters which need to be reset setCutoff(COIN_DBL_MAX); dblParam_[CbcCutoffIncrement] = 1e-5; dblParam_[CbcCurrentCutoff] = 1.0e100; dblParam_[CbcCurrentObjectiveValue] = 1.0e100; dblParam_[CbcCurrentMinimizationObjectiveValue] = 1.0e100; delete globalConflictCuts_; globalConflictCuts_=NULL; } /* Most of copy constructor mode - 0 copy but don't delete before 1 copy and delete before 2 copy and delete before (but use virgin generators) */ void CbcModel::gutsOfCopy(const CbcModel & rhs, int mode) { minimumDrop_ = rhs.minimumDrop_; specialOptions_ = rhs.specialOptions_; moreSpecialOptions_ = rhs.moreSpecialOptions_; numberStrong_ = rhs.numberStrong_; numberBeforeTrust_ = rhs.numberBeforeTrust_; numberPenalties_ = rhs.numberPenalties_; printFrequency_ = rhs.printFrequency_; fastNodeDepth_ = rhs.fastNodeDepth_; howOftenGlobalScan_ = rhs.howOftenGlobalScan_; maximumCutPassesAtRoot_ = rhs.maximumCutPassesAtRoot_; maximumCutPasses_ = rhs.maximumCutPasses_; randomSeed_ = rhs.randomSeed_; multipleRootTries_ = rhs.multipleRootTries_; preferredWay_ = rhs.preferredWay_; resolveAfterTakeOffCuts_ = rhs.resolveAfterTakeOffCuts_; maximumNumberIterations_ = rhs.maximumNumberIterations_; numberSavedSolutions_ = rhs.numberSavedSolutions_; maximumSavedSolutions_ = rhs.maximumSavedSolutions_; if (maximumSavedSolutions_) { int n = solver_->getNumCols(); savedSolutions_ = new double * [maximumSavedSolutions_]; for (int i = 0; i < maximumSavedSolutions_; i++) savedSolutions_[i] = CoinCopyOfArray(rhs.savedSolutions_[i], n + 2); } continuousPriority_ = rhs.continuousPriority_; numberThreads_ = rhs.numberThreads_; threadMode_ = rhs.threadMode_; delete master_; master_ = NULL; masterThread_ = NULL; memcpy(intParam_, rhs.intParam_, sizeof(intParam_)); memcpy(dblParam_, rhs.dblParam_, sizeof(dblParam_)); int i; if (mode) { for (i = 0; i < numberCutGenerators_; i++) { delete generator_[i]; delete virginGenerator_[i]; } delete [] generator_; delete [] virginGenerator_; for (i = 0; i < numberHeuristics_; i++) { delete heuristic_[i]; } delete [] heuristic_; delete eventHandler_; delete branchingMethod_; } numberCutGenerators_ = rhs.numberCutGenerators_; if (numberCutGenerators_) { generator_ = new CbcCutGenerator * [numberCutGenerators_]; virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_]; int i; for (i = 0; i < numberCutGenerators_; i++) { if (mode < 2) { generator_[i] = new CbcCutGenerator(*rhs.generator_[i]); } else { generator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]); // But copy across maximumTries generator_[i]->setMaximumTries(rhs.generator_[i]->maximumTries()); } virginGenerator_[i] = new CbcCutGenerator(*rhs.virginGenerator_[i]); } } else { generator_ = NULL; virginGenerator_ = NULL; } numberHeuristics_ = rhs.numberHeuristics_; if (numberHeuristics_) { heuristic_ = new CbcHeuristic * [numberHeuristics_]; int i; for (i = 0; i < numberHeuristics_; i++) { heuristic_[i] = rhs.heuristic_[i]->clone(); } } else { heuristic_ = NULL; } if (rhs.eventHandler_) eventHandler_ = rhs.eventHandler_->clone() ; else eventHandler_ = NULL ; if (rhs.branchingMethod_) branchingMethod_ = rhs.branchingMethod_->clone(); else branchingMethod_ = NULL; messageHandler()->setLogLevel(rhs.messageHandler()->logLevel()); whenCuts_ = rhs.whenCuts_; synchronizeModel(); } // Move status, nodes etc etc across void CbcModel::moveInfo(const CbcModel & rhs) { bestObjective_ = rhs.bestObjective_; bestPossibleObjective_ = rhs.bestPossibleObjective_; numberSolutions_ = rhs.numberSolutions_; numberHeuristicSolutions_ = rhs.numberHeuristicSolutions_; numberNodes_ = rhs.numberNodes_; numberNodes2_ = rhs.numberNodes2_; numberIterations_ = rhs.numberIterations_; numberSolves_ = rhs.numberSolves_; status_ = rhs.status_; secondaryStatus_ = rhs.secondaryStatus_; numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_; numberInfeasibleNodes_ = rhs.numberInfeasibleNodes_; continuousObjective_ = rhs.continuousObjective_; originalContinuousObjective_ = rhs.originalContinuousObjective_; continuousInfeasibilities_ = rhs.continuousInfeasibilities_; numberFixedAtRoot_ = rhs.numberFixedAtRoot_; numberFixedNow_ = rhs.numberFixedNow_; stoppedOnGap_ = rhs.stoppedOnGap_; eventHappened_ = rhs.eventHappened_; numberLongStrong_ = rhs.numberLongStrong_; numberStrongIterations_ = rhs.numberStrongIterations_; strongInfo_[0] = rhs.strongInfo_[0]; strongInfo_[1] = rhs.strongInfo_[1]; strongInfo_[2] = rhs.strongInfo_[2]; strongInfo_[3] = rhs.strongInfo_[3]; strongInfo_[4] = rhs.strongInfo_[4]; strongInfo_[5] = rhs.strongInfo_[5]; strongInfo_[6] = rhs.strongInfo_[6]; numberRowsAtContinuous_ = rhs.numberRowsAtContinuous_; cutoffRowNumber_ = rhs.cutoffRowNumber_; maximumDepth_ = rhs.maximumDepth_; } // Save a copy of the current solver so can be reset to void CbcModel::saveReferenceSolver() { delete referenceSolver_; referenceSolver_ = solver_->clone(); } // Uses a copy of reference solver to be current solver void CbcModel::resetToReferenceSolver() { delete solver_; solver_ = referenceSolver_->clone(); // clear many things gutsOfDestructor2(); // Reset cutoff // Solvers know about direction double direction = solver_->getObjSense(); double value; solver_->getDblParam(OsiDualObjectiveLimit, value); setCutoff(value*direction); } // Are there a numerical difficulties? bool CbcModel::isAbandoned() const { return status_ == 2; } // Is optimality proven? bool CbcModel::isProvenOptimal() const { if (!status_ && bestObjective_ < 1.0e30) return true; else return false; } // Is infeasiblity proven (or none better than cutoff)? bool CbcModel::isProvenInfeasible() const { if (!status_ && (bestObjective_ >= 1.0e30 && (secondaryStatus_==0||secondaryStatus_==1))) return true; else return false; } // Was continuous solution unbounded bool CbcModel::isContinuousUnbounded() const { if (!status_ && secondaryStatus_ == 7) return true; else return false; } // Was continuous solution unbounded bool CbcModel::isProvenDualInfeasible() const { if (!status_ && secondaryStatus_ == 7) return true; else return false; } // Node limit reached? bool CbcModel::isNodeLimitReached() const { return numberNodes_ >= intParam_[CbcMaxNumNode]; } // Time limit reached? bool CbcModel::isSecondsLimitReached() const { if (status_ == 1 && secondaryStatus_ == 4) return true; else return false; } // Solution limit reached? bool CbcModel::isSolutionLimitReached() const { return numberSolutions_ >= intParam_[CbcMaxNumSol]; } // Set language void CbcModel::newLanguage(CoinMessages::Language language) { messages_ = CbcMessage(language); } void CbcModel::setNumberStrong(int number) { if (number < 0) numberStrong_ = 0; else numberStrong_ = number; } void CbcModel::setNumberBeforeTrust(int number) { if (number < -3) { numberBeforeTrust_ = 0; } else { numberBeforeTrust_ = number; //numberStrong_ = CoinMax(numberStrong_,1); } } void CbcModel::setNumberPenalties(int number) { if (number <= 0) { numberPenalties_ = 0; } else { numberPenalties_ = number; } } void CbcModel::setPenaltyScaleFactor(double value) { if (value <= 0) { penaltyScaleFactor_ = 3.0; } else { penaltyScaleFactor_ = value; } } void CbcModel::setHowOftenGlobalScan(int number) { if (number < -1) howOftenGlobalScan_ = 0; else howOftenGlobalScan_ = number; } // Add one generator void CbcModel::addCutGenerator(CglCutGenerator * generator, int howOften, const char * name, bool normal, bool atSolution, bool whenInfeasible, int howOftenInSub, int whatDepth, int whatDepthInSub) { CbcCutGenerator ** temp = generator_; generator_ = new CbcCutGenerator * [numberCutGenerators_+1]; memcpy(generator_, temp, numberCutGenerators_*sizeof(CbcCutGenerator *)); delete[] temp ; generator_[numberCutGenerators_] = new CbcCutGenerator(this, generator, howOften, name, normal, atSolution, whenInfeasible, howOftenInSub, whatDepth, whatDepthInSub); // and before any changes temp = virginGenerator_; virginGenerator_ = new CbcCutGenerator * [numberCutGenerators_+1]; memcpy(virginGenerator_, temp, numberCutGenerators_*sizeof(CbcCutGenerator *)); delete[] temp ; virginGenerator_[numberCutGenerators_++] = new CbcCutGenerator(this, generator, howOften, name, normal, atSolution, whenInfeasible, howOftenInSub, whatDepth, whatDepthInSub); } // Add one heuristic void CbcModel::addHeuristic(CbcHeuristic * generator, const char *name, int before) { CbcHeuristic ** temp = heuristic_; heuristic_ = new CbcHeuristic * [numberHeuristics_+1]; memcpy(heuristic_, temp, numberHeuristics_*sizeof(CbcHeuristic *)); delete [] temp; int where; if (before < 0 || before >= numberHeuristics_) { where = numberHeuristics_; } else { // move up for (int i = numberHeuristics_; i > before; i--) heuristic_[i] = heuristic_[i-1]; where = before; } heuristic_[where] = generator->clone(); if (name) heuristic_[where]->setHeuristicName(name) ; heuristic_[where]->setSeed(987654321 + where); numberHeuristics_++ ; } /* The last subproblem handled by the solver is not necessarily related to the one being recreated, so the first action is to remove all cuts from the constraint system. Next, traverse the tree from node to the root to determine the basis size required for this subproblem and create an empty basis with the right capacity. Finally, traverse the tree from root to node, adjusting bounds in the constraint system, adjusting the basis, and collecting the cuts that must be added to the constraint system. applyToModel does the heavy lifting. addCuts1 is used in contexts where all that's desired is the list of cuts: the node is already fathomed, and we're collecting cuts so that we can adjust reference counts as we prune nodes. Arguably the two functions should be separated. The culprit is applyToModel, which performs cut collection and model adjustment. Certainly in the contexts where all we need is a list of cuts, there's no point in passing in a valid basis --- an empty basis will do just fine. */ bool CbcModel::addCuts1 (CbcNode * node, CoinWarmStartBasis *&lastws) { int nNode = 0; CbcNodeInfo * nodeInfo = node->nodeInfo(); int numberColumns = getNumCols(); /* Accumulate the path from node to the root in walkback_, and accumulate a cut count in currentNumberCuts. original comment: when working then just unwind until where new node joins old node (for cuts?) */ int currentNumberCuts = 0; while (nodeInfo) { //printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo); walkback_[nNode++] = nodeInfo; currentNumberCuts += nodeInfo->numberCuts() ; nodeInfo = nodeInfo->parent() ; if (nNode == maximumDepth_) { redoWalkBack(); } } currentNumberCuts_ = currentNumberCuts; if (currentNumberCuts > maximumNumberCuts_) { maximumNumberCuts_ = currentNumberCuts; delete [] addedCuts_; addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_]; } /* This last bit of code traverses the path collected in walkback_ from the root back to node. At the end of the loop, * lastws will be an appropriate basis for node; * variable bounds in the constraint system will be set to be correct for node; and * addedCuts_ will be set to a list of cuts that need to be added to the constraint system at node. applyToModel does all the heavy lifting. */ bool sameProblem = false; if ((specialOptions_&4096) == 0) { #if 0 { int n1 = numberRowsAtContinuous_; for (int i = 0; i < lastDepth_; i++) n1 += lastNumberCuts_[i]; int n2 = numberRowsAtContinuous_; for (int i = 0; i < nNode; i++) n2 += walkback_[i]->numberCuts(); //printf("ROWS a %d - old thinks %d new %d\n",solver_->getNumRows(),n1,n2); } #endif int nDel = 0; int nAdd = 0; int n = CoinMin(lastDepth_, nNode); int i; int difference = lastDepth_ - nNode; int iZ = lastDepth_; int iN = 0; // Last is reversed to minimize copying if (difference > 0) { for (i = 0; i < difference; i++) { // delete rows nDel += lastNumberCuts_[--iZ]; } } else if (difference < 0) { for (i = 0; i < -difference; i++) { // add rows nAdd += walkback_[i]->numberCuts(); } iN = -difference; } for (i = 0; i < n; i++) { iZ--; if (lastNodeInfo_[iZ] == walkback_[iN]) { break; } else { // delete rows nDel += lastNumberCuts_[iZ]; // add rows nAdd += walkback_[iN++]->numberCuts(); } } assert (i < n || lastDepth_ == 0); //printf("lastDepth %d thisDepth %d match at %d, rows+-= %d %d\n", // lastDepth_,nNode,n-i,nAdd,nDel); sameProblem = (!nAdd) && (!nDel); if (lastDepth_) { while (iN >= 0) { lastNumberCuts_[iZ] = walkback_[iN]->numberCuts(); lastNodeInfo_[iZ++] = walkback_[iN--]; } } else { lastNumberCuts_[0] = walkback_[0]->numberCuts(); lastNodeInfo_[0] = walkback_[0]; } lastDepth_ = nNode; } currentDepth_ = nNode; /* Remove all cuts from the constraint system. (original comment includes ``see note below for later efficiency'', but the reference isn't clear to me). */ /* Create an empty basis with sufficient capacity for the constraint system we'll construct: original system plus cuts. Make sure we have capacity to record those cuts in addedCuts_. The method of adjusting the basis at a FullNodeInfo object (the root, for example) is to use a copy constructor to duplicate the basis held in the nodeInfo, then resize it and return the new basis object. Guaranteed, lastws will point to a different basis when it returns. We pass in a basis because we need the parameter to return the allocated basis, and it's an easy way to pass in the size. But we take a hit for memory allocation. */ lastws->setSize(numberColumns, numberRowsAtContinuous_ + currentNumberCuts); currentNumberCuts = 0; while (nNode) { --nNode; walkback_[nNode]->applyToModel(this, lastws, addedCuts_, currentNumberCuts); } #ifndef NDEBUG if (!lastws->fullBasis()) { #ifdef COIN_DEVELOP printf("******* bad basis\n"); #endif int numberRows = lastws->getNumArtificial(); int i; for (i = 0; i < numberRows; i++) lastws->setArtifStatus(i, CoinWarmStartBasis::basic); int numberColumns = lastws->getNumStructural(); for (i = 0; i < numberColumns; i++) { if (lastws->getStructStatus(i) == CoinWarmStartBasis::basic) lastws->setStructStatus(i, CoinWarmStartBasis::atLowerBound); } } #endif return sameProblem; } /* adjustCuts might be a better name: If the node is feasible, we sift through the cuts collected by addCuts1, add the ones that are tight and omit the ones that are loose. If the node is infeasible, we just adjust the reference counts to reflect that we're about to prune this node and its descendants. */ int CbcModel::addCuts (CbcNode *node, CoinWarmStartBasis *&lastws, bool canFix) { /* addCuts1 performs step 1 of restoring the subproblem at this node; see the comments there. */ bool sameProblem = addCuts1(node, lastws); int i; int numberColumns = getNumCols(); if (solver_->getNumRows() > maximumRows_) { maximumRows_ = solver_->getNumRows(); workingBasis_.resize(maximumRows_, numberColumns); } CbcNodeInfo * nodeInfo = node->nodeInfo(); double cutoff = getCutoff() ; int currentNumberCuts = currentNumberCuts_; if (canFix) { bool feasible = true; const double *lower = solver_->getColLower() ; const double *upper = solver_->getColUpper() ; double * newLower = analyzeResults_; double * objLower = newLower + numberIntegers_; double * newUpper = objLower + numberIntegers_; double * objUpper = newUpper + numberIntegers_; int n = 0; for (i = 0; i < numberIntegers_; i++) { int iColumn = integerVariable_[i]; bool changed = false; double lo = 0.0; double up = 0.0; if (objLower[i] > cutoff) { lo = lower[iColumn]; up = upper[iColumn]; if (lo < newLower[i]) { lo = newLower[i]; solver_->setColLower(iColumn, lo); changed = true; n++; } if (objUpper[i] > cutoff) { if (up > newUpper[i]) { up = newUpper[i]; solver_->setColUpper(iColumn, up); changed = true; n++; } } } else if (objUpper[i] > cutoff) { lo = lower[iColumn]; up = upper[iColumn]; if (up > newUpper[i]) { up = newUpper[i]; solver_->setColUpper(iColumn, up); changed = true; n++; } } if (changed && lo > up) { feasible = false; break; } } if (!feasible) { COIN_DETAIL_PRINT(printf("analysis says node infeas\n")); cutoff = -COIN_DBL_MAX; } } /* If the node can't be fathomed by bound, reinstall tight cuts in the constraint system. Even if there are no cuts, we'll want to set the reconstructed basis in the solver. */ if (node->objectiveValue() < cutoff || numberThreads_) { //# define CBC_CHECK_BASIS # ifdef CBC_CHECK_BASIS printf("addCuts: expanded basis; rows %d+%d\n", numberRowsAtContinuous_, currentNumberCuts); lastws->print(); # endif /* Adjust the basis and constraint system so that we retain only active cuts. There are three steps: 1) Scan the basis. Sort the cuts into effective cuts to be kept and loose cuts to be dropped. 2) Drop the loose cuts and resize the basis to fit. 3) Install the tight cuts in the constraint system (applyRowCuts) and and install the basis (setWarmStart). Use of compressRows conveys we're compressing the basis and not just tweaking the artificialStatus_ array. */ if (currentNumberCuts > 0) { int numberToAdd = 0; const OsiRowCut **addCuts; int numberToDrop = 0 ; int *cutsToDrop ; addCuts = new const OsiRowCut* [currentNumberCuts]; cutsToDrop = new int[currentNumberCuts] ; assert (currentNumberCuts + numberRowsAtContinuous_ <= lastws->getNumArtificial()); for (i = 0; i < currentNumberCuts; i++) { CoinWarmStartBasis::Status status = lastws->getArtifStatus(i + numberRowsAtContinuous_); if (addedCuts_[i] && (status != CoinWarmStartBasis::basic || (addedCuts_[i]->effectiveness() > 1.0e10 && !addedCuts_[i]->canDropCut(solver_, i + numberRowsAtContinuous_)))) { # ifdef CHECK_CUT_COUNTS printf("Using cut %d %x as row %d\n", i, addedCuts_[i], numberRowsAtContinuous_ + numberToAdd); # endif addCuts[numberToAdd++] = addedCuts_[i]; #if 1 if ((specialOptions_&1) != 0) { const OsiRowCutDebugger * debugger = solver_->getRowCutDebugger() ; if (debugger) CoinAssert (!debugger->invalidCut(*addedCuts_[i])); } #endif } else { # ifdef CHECK_CUT_COUNTS printf("Dropping cut %d %x\n", i, addedCuts_[i]); # endif addedCuts_[i] = NULL; cutsToDrop[numberToDrop++] = numberRowsAtContinuous_ + i ; } } assert (lastws->fullBasis()); int numberRowsNow = numberRowsAtContinuous_ + numberToAdd; lastws->compressRows(numberToDrop, cutsToDrop) ; lastws->resize(numberRowsNow, numberColumns); // Take out as local search can give bad basisassert (lastws->fullBasis()); bool canMissStuff = false; if ((specialOptions_&4096) == 0) { bool redoCuts = true; if (CoinAbs(lastNumberCuts2_ - numberToAdd) < 5) { int numberToCheck = CoinMin(lastNumberCuts2_, numberToAdd); int i1 = 0; int i2 = 0; int nDiff = 0; int nSame = 0; if (lastNumberCuts2_ == numberToAdd) { for (int i = 0; i < numberToCheck; i++) { if (lastCut_[i1++] != addCuts[i2++]) { nDiff++; } else { nSame++; } } } else if (lastNumberCuts2_ > numberToAdd) { int nDiff2 = lastNumberCuts2_ - numberToAdd; for (int i = 0; i < numberToCheck; i++) { if (lastCut_[i1] != addCuts[i2]) { nDiff++; while (nDiff2) { i1++; nDiff2--; if (lastCut_[i1] == addCuts[i2]) { nSame++; break; } else { nDiff++; } } } else { nSame++; } } nDiff += nDiff2; } else { int nDiff2 = numberToAdd - lastNumberCuts2_; for (int i = 0; i < numberToCheck; i++) { if (lastCut_[i1] != addCuts[i2]) { nDiff++; while (nDiff2) { i2++; nDiff2--; if (lastCut_[i1] == addCuts[i2]) { nSame++; break; } else { nDiff++; } } } else { nSame++; } } nDiff += nDiff2; } canMissStuff = !nDiff && sameProblem; // But only if number of rows looks OK if (numberRowsAtContinuous_ + numberToAdd != solver_->getNumRows()) canMissStuff = false; } else { //printf("add now %d add last %d NO2\n",numberToAdd,lastNumberCuts2_); } assert (lastws->fullBasis() && numberRowsAtContinuous_ + numberToAdd == numberRowsNow); if (redoCuts) { if (numberToAdd > maximumCuts_) { delete [] lastCut_; maximumCuts_ = 2 * numberToAdd + 10; lastCut_ = new const OsiRowCut * [maximumCuts_]; } lastNumberCuts2_ = numberToAdd; for (int i = 0; i < numberToAdd; i++) lastCut_[i] = addCuts[i]; } } if (!canMissStuff) { //if (canMissStuff) //solver_->writeMps("before"); //printf("Not Skipped\n"); //int n1=solver_->getNumRows(); if ((specialOptions_&4096) == 0) { solver_->restoreBaseModel(numberRowsAtContinuous_); } else { // *** Fix later int numberCuts = solver_->getNumRows() - numberRowsAtContinuous_; int *which = new int[numberCuts]; for (i = 0 ; i < numberCuts ; i++) which[i] = i + numberRowsAtContinuous_; solver_->deleteRows(numberCuts, which); delete [] which; } //#define CHECK_DEBUGGER #ifdef CHECK_DEBUGGER if ((specialOptions_&1) != 0 ) { const OsiRowCutDebugger * debugger = solver_->getRowCutDebugger(); if (debugger) { for (int j=0;jinvalidCut(*addCuts[j])); //addCuts[j]->print(); } } #endif //int n2=solver_->getNumRows(); //for (int j=0;jprint(); solver_->applyRowCuts(numberToAdd, addCuts); //int n3=solver_->getNumRows(); //printf("NBefore %d, after del %d, now %d\n",n1,n2,n3); } # ifdef CBC_CHECK_BASIS printf("addCuts: stripped basis; rows %d + %d\n", numberRowsAtContinuous_, numberToAdd); lastws->print(); # endif //for (i=0;isetWarmStart(lastws); /* Clean up and we're out of here. */ numberNodes_++; return 0; } /* This node has been fathomed by bound as we try to revive it out of the live set. Adjust the cut reference counts to reflect that we no longer need to explore the remaining branch arms, hence they will no longer reference any cuts. Cuts whose reference count falls to zero are deleted. */ else { int i; if (currentNumberCuts) { lockThread(); int numberLeft = nodeInfo->numberBranchesLeft(); for (i = 0 ; i < currentNumberCuts ; i++) { if (addedCuts_[i]) { if (!addedCuts_[i]->decrement(numberLeft)) { delete addedCuts_[i]; addedCuts_[i] = NULL; } } } unlockThread(); } return 1 ; } } /* Makes all handlers same. If makeDefault 1 then makes top level default and rest point to that. If 2 then each is copy */ void CbcModel::synchronizeHandlers(int /*makeDefault*/) { bool defaultHandler = defaultHandler_; if (!defaultHandler_) { // Must have clone handler_ = handler_->clone(); defaultHandler_ = true; } #ifdef COIN_HAS_CLP if (!defaultHandler) { OsiClpSolverInterface * solver; solver = dynamic_cast(solver_) ; if (solver) { solver->passInMessageHandler(handler_); solver->getModelPtr()->passInMessageHandler(handler_); } solver = dynamic_cast(continuousSolver_) ; if (solver) { solver->passInMessageHandler(handler_); solver->getModelPtr()->passInMessageHandler(handler_); } } #endif } /* Perform reduced cost fixing on integer variables. The variables in question are already nonbasic at bound. We're just nailing down the current situation. */ int CbcModel::reducedCostFix () { if (!solverCharacteristics_->reducedCostsAccurate()) return 0; //NLP double cutoff = getCutoff() ; double direction = solver_->getObjSense() ; double gap = cutoff - solver_->getObjValue() * direction ; double tolerance; solver_->getDblParam(OsiDualTolerance, tolerance) ; if (gap <= 0.0) gap = tolerance; //return 0; gap += 100.0 * tolerance; double integerTolerance = getDblParam(CbcIntegerTolerance) ; const double *lower = solver_->getColLower() ; const double *upper = solver_->getColUpper() ; const double *solution = solver_->getColSolution() ; const double *reducedCost = solver_->getReducedCost() ; int numberFixed = 0 ; int numberTightened = 0 ; # ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); ClpSimplex * clpSimplex = NULL; if (clpSolver) clpSimplex = clpSolver->getModelPtr(); # endif for (int i = 0 ; i < numberIntegers_ ; i++) { int iColumn = integerVariable_[i] ; double djValue = direction * reducedCost[iColumn] ; double boundGap = upper[iColumn] - lower[iColumn]; if (boundGap > integerTolerance) { if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue*boundGap > gap) { #ifdef COIN_HAS_CLP // may just have been fixed before if (clpSimplex) { if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) { #ifdef COIN_DEVELOP printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n", iColumn, clpSimplex->getColumnStatus(iColumn), djValue, gap, lower[iColumn], upper[iColumn]); #endif } else { assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atLowerBound || clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed); } } #endif double newBound = lower[iColumn]; if (boundGap > 1.99) { boundGap = gap / djValue + 1.0e-4 * boundGap; newBound = lower[iColumn] + floor(boundGap); numberTightened++; //if (newBound) //printf("tighter - gap %g dj %g newBound %g\n", // gap,djValue,newBound); } solver_->setColUpper(iColumn, newBound) ; numberFixed++ ; } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > boundGap*gap) { #ifdef COIN_HAS_CLP // may just have been fixed before if (clpSimplex) { if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) { #ifdef COIN_DEVELOP printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n", iColumn, clpSimplex->getColumnStatus(iColumn), djValue, gap, lower[iColumn], upper[iColumn]); #endif } else { assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atUpperBound || clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed); } } #endif double newBound = upper[iColumn]; if (boundGap > 1.99) { boundGap = -gap / djValue + 1.0e-4 * boundGap; newBound = upper[iColumn] - floor(boundGap); //if (newBound) //printf("tighter - gap %g dj %g newBound %g\n", // gap,djValue,newBound); numberTightened++; } solver_->setColLower(iColumn, newBound) ; numberFixed++ ; } } } numberDJFixed_ += numberFixed - numberTightened; return numberFixed; } // Collect coding to replace whichGenerator void CbcModel::resizeWhichGenerator(int numberNow, int numberAfter) { if (numberAfter > maximumWhich_) { maximumWhich_ = CoinMax(maximumWhich_ * 2 + 100, numberAfter) ; int * temp = new int[2*maximumWhich_] ; memcpy(temp, whichGenerator_, numberNow*sizeof(int)) ; delete [] whichGenerator_ ; whichGenerator_ = temp ; memset(whichGenerator_ + numberNow, 0, (maximumWhich_ - numberNow)*sizeof(int)); } } /** Solve the model using cuts This version takes off redundant cuts from node. Returns true if feasible. \todo Why do I need to resolve the problem? What has been done between the last relaxation and calling solveWithCuts? If numberTries == 0 then user did not want any cuts. */ bool CbcModel::solveWithCuts (OsiCuts &cuts, int numberTries, CbcNode *node) /* Parameters: numberTries: (i) the maximum number of iterations for this round of cut generation; if negative then we don't mind if drop is tiny. cuts: (o) all cuts generated in this round of cut generation node: (i) So we can update dynamic pseudo costs */ { #ifdef JJF_ZERO if (node && numberTries > 1) { if (currentDepth_ < 5) numberTries *= 4; // boost else if (currentDepth_ < 10) numberTries *= 2; // boost } #endif #define CUT_HISTORY 7 double cut_obj[CUT_HISTORY]; for (int j = 0; j < CUT_HISTORY; j++) cut_obj[j] = -COIN_DBL_MAX; # ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); int saveClpOptions = 0; if (clpSolver) saveClpOptions = clpSolver->specialOptions(); # endif //solver_->writeMps("saved"); #ifdef CBC_THREAD /* Thread mode makes a difference here only when it specifies using separate threads to generate cuts at the root (bit 2^1 set in threadMode_). In which case we'll create an array of empty CbcModels (!). Solvers will be cloned later. Don't start up threads here if we're already threaded. */ CbcBaseModel * master = NULL; if (numberThreads_ && (threadMode_&2) != 0 && !numberNodes_) { master = new CbcBaseModel(*this, -1); } #endif bool feasible = true ; int violated = 0 ; int numberRowsAtStart = solver_->getNumRows() ; //printf("solver had %d rows\n",numberRowsAtStart); int numberColumns = solver_->getNumCols() ; CoinBigIndex numberElementsAtStart = solver_->getNumElements(); numberOldActiveCuts_ = numberRowsAtStart - numberRowsAtContinuous_ ; numberNewCuts_ = cuts.sizeRowCuts(); int lastNumberCuts = numberNewCuts_ ; if (numberNewCuts_) { // from multiple root passes const OsiRowCut **addCuts = new const OsiRowCut* [numberNewCuts_]; for (int i = 0; i < numberNewCuts_; i++) { addCuts[i] = cuts.rowCutPtr(i); } solver_->applyRowCuts(numberNewCuts_, addCuts); delete [] addCuts; } bool onOptimalPath = false ; const OsiRowCutDebugger *debugger = NULL; if ((specialOptions_&1) != 0) { /* See OsiRowCutDebugger for details. In a nutshell, make sure that current variable values do not conflict with a known optimal solution. (Obviously this can be fooled when there are multiple solutions.) */ debugger = solver_->getRowCutDebugger() ; if (debugger) onOptimalPath = (debugger->onOptimalPath(*solver_)) ; } /* As the final action in each round of cut generation (the numberTries loop), we'll call takeOffCuts to remove slack cuts. These are saved into slackCuts and rechecked immediately after the cut generation phase of the loop. */ OsiCuts slackCuts; /* lh: Resolve the problem The resolve will also refresh cached copies of the solver solution (cbcColLower_, ...) held by CbcModel. This resolve looks like the best point to capture a warm start for use in the case where cut generation proves ineffective and we need to back out a few tight cuts. I've always maintained that this resolve is unnecessary. Let's put in a hook to report if it's every nontrivial. -lh Resolve the problem. If we've lost feasibility, might as well bail out right after the debug stuff. The resolve will also refresh cached copies of the solver solution (cbcColLower_, ...) held by CbcModel. */ double objectiveValue = solver_->getObjValue() * solver_->getObjSense(); if (node) { objectiveValue = node->objectiveValue(); } int save = moreSpecialOptions_; if ((moreSpecialOptions_&4194304)!=0) moreSpecialOptions_ |= 8388608; int returnCode = resolve(node ? node->nodeInfo() : NULL, 1); moreSpecialOptions_=save; #ifdef CONFLICT_CUTS #ifdef COIN_HAS_CLP // if infeasible conflict analysis if (solver_->isProvenPrimalInfeasible()&&!parentModel_&& (moreSpecialOptions_&4194304)!=0&&clpSolver) { //printf("infeasible - do conflict analysis\n"); assert (topOfTree_); int iType=1; OsiRowCut * cut = clpSolver->modelCut(topOfTree_->lower(), topOfTree_->upper(), numberRowsAtContinuous_,whichGenerator_,iType); if (cut) { printf("XXXXXX cut\n"); //cut->print(); if (!iType) { makeGlobalCut(cut) ; if ((specialOptions_&1) != 0) { debugger = continuousSolver_->getRowCutDebugger() ; if (debugger) { if (debugger->invalidCut(*cut)) { continuousSolver_->applyRowCuts(1,cut); continuousSolver_->writeMps("bad"); } CoinAssert (!debugger->invalidCut(*cut)); } } } else { makePartialCut(cut); } delete cut; } } if ((moreSpecialOptions_&4194304)!=0&&solver_->isProvenPrimalInfeasible() &&clpSolver&&clpSolver->lastAlgorithm()==2&& clpSolver->getModelPtr()->infeasibilityRay()&& !parentModel_) { printf("ray exists\n"); } #endif #endif #if COIN_DEVELOP>1 //if (!solver_->getIterationCount()&&solver_->isProvenOptimal()) //printf("zero iterations on first solve of branch\n"); #endif double lastObjective = solver_->getObjValue() * solver_->getObjSense(); cut_obj[CUT_HISTORY-1] = lastObjective; //double firstObjective = lastObjective+1.0e-8+1.0e-12*fabs(lastObjective); /* Contemplate the result of the resolve. - CbcModel::resolve() has a hook that calls CbcStrategy::status to look over the solution. The net result is that resolve can return 0 (infeasible), 1 (feasible), or -1 (feasible, but do no further work). - CbcFeasbililityBase::feasible() can return 0 (no comment), 1 (pretend this is an integer solution), or -1 (pretend this is infeasible). As of 080104, this seems to be a stub to allow overrides, with a default implementation that always returns 0. Setting numberTries = 0 for `do no more work' is problematic. The main cut generation loop will still execute once, so we do not observe the `no further work' semantics. As best I can see, allBranchesGone is a null function as of 071220. */ if (node && node->nodeInfo() && !node->nodeInfo()->numberBranchesLeft()) node->nodeInfo()->allBranchesGone(); // can clean up feasible = returnCode != 0 ; if (returnCode < 0) numberTries = 0; if (problemFeasibility_->feasible(this, 0) < 0) { feasible = false; // pretend infeasible } /* NEW_UPDATE_OBJECT is defined to 0 when unthreaded (CBC_THREAD undefined), 2 when threaded. No sign of 1 as of 071220. At present, there are two sets of hierarchies for branching classes. Call them CbcHier and OsiHier. For example, we have OsiBranchingObject, with children CbcBranchingObject and OsiTwoWayBranchingObject. All specialisations descend from one of these two children. Similarly, there is OsiObject, with children CbcObject and OsiObject2. In the original setup, there's a single CbcBranchDecision object attached to CbcModel (branchingMethod_). It has a field to hold the current CbcHier branching object, and the updateInformation routine reaches through the branching object to update the underlying CbcHier object. NEW_UPDATE_OBJECT = 0 would seem to assume the original setup. But, if we're using the OSI hierarchy for objects and branching, a call to a nontrivial branchingMethod_->updateInformation would have no effect (it would expect a CbcObject to work on) or perhaps crash. For the default CbcBranchDefaultDecision, updateInformation is a noop (actually defined in the base CbcBranchDecision class). NEW_UPDATE_OBJECT = 2 looks like it's prepared to cope with either CbcHier or OsiHier, but it'll be executed only when threads are activated. See the comments below. The setup is scary. But ... if the OsiHier update actually reaches right through to the object list in the solver, it should work just fine in unthreaded mode. It would seem that the appropriate thing to do in unthreaded mode would be to choose between the existing code for NEW_UPDATE_OBJECT = 0 and the OsiHier code for NEW_UPDATE_OBJECT = 2. But I'm going to let John hash that out. The worst that can happen is inefficiency because I'm not properly updating an object. */ // Update branching information if wanted if (node && branchingMethod_) { OsiBranchingObject * bobj = node->modifiableBranchingObject(); CbcBranchingObject * cbcobj = dynamic_cast (bobj); if (cbcobj && cbcobj->object()) { CbcObject * object = cbcobj->object(); CbcObjectUpdateData update = object->createUpdateInformation(solver_, node, cbcobj); // have to compute object number as not saved CbcSimpleInteger * simpleObject = static_cast (object) ; int iObject = simpleObject->position(); #ifndef NDEBUG int iColumn = simpleObject->columnNumber(); int jObject; for (jObject = 0 ; jObject < numberObjects_ ; jObject++) { simpleObject = static_cast (object_[jObject]) ; if (simpleObject->columnNumber() == iColumn) break; } assert (jObject < numberObjects_ && iObject == jObject); #else #ifdef CBCMODEL_TIGHTEN_BOUNDS int iColumn = simpleObject->columnNumber(); #endif #endif update.objectNumber_ = iObject; // Care! We must be careful not to update the same variable in parallel threads. addUpdateInformation(update); //#define CBCMODEL_TIGHTEN_BOUNDS #ifdef CBCMODEL_TIGHTEN_BOUNDS double cutoff = getCutoff() ; if (feasible && cutoff < 1.0e20) { int way = cbcobj->way(); // way is what will be taken next way = -way; double value = cbcobj->value(); //const double * lower = solver_->getColLower(); //const double * upper = solver_->getColUpper(); double objectiveChange = lastObjective - objectiveValue; if (objectiveChange > 1.0e-5) { CbcIntegerBranchingObject * branch = dynamic_cast (cbcobj) ; assert (branch); if (way < 0) { double down = value - floor(value); double changePer = objectiveChange / (down + 1.0e-7); double distance = (cutoff - objectiveValue) / changePer; distance += 1.0e-3; if (distance < 5.0) { double newLower = ceil(value - distance); const double * downBounds = branch->downBounds(); if (newLower > downBounds[0]) { //printf("%d way %d bounds %g %g value %g\n", // iColumn,way,lower[iColumn],upper[iColumn],value); //printf("B Could increase lower bound on %d from %g to %g\n", // iColumn,downBounds[0],newLower); solver_->setColLower(iColumn, newLower); } } } else { double up = ceil(value) - value; double changePer = objectiveChange / (up + 1.0e-7); double distance = (cutoff - objectiveValue) / changePer; distance += 1.0e-3; if (distance < 5.0) { double newUpper = floor(value + distance); const double * upBounds = branch->upBounds(); if (newUpper < upBounds[1]) { //printf("%d way %d bounds %g %g value %g\n", // iColumn,way,lower[iColumn],upper[iColumn],value); //printf("B Could decrease upper bound on %d from %g to %g\n", // iColumn,upBounds[1],newUpper); solver_->setColUpper(iColumn, newUpper); } } } } } #endif } else { OsiIntegerBranchingObject * obj = dynamic_cast (bobj); if (obj) { const OsiObject * object = obj->originalObject(); // have to compute object number as not saved int iObject; int iColumn = object->columnNumber(); for (iObject = 0 ; iObject < numberObjects_ ; iObject++) { if (object_[iObject]->columnNumber() == iColumn) break; } assert (iObject < numberObjects_); int branch = obj->firstBranch(); if (obj->branchIndex() == 2) branch = 1 - branch; assert (branch == 0 || branch == 1); double originalValue = node->objectiveValue(); double objectiveValue = solver_->getObjValue() * solver_->getObjSense(); double changeInObjective = CoinMax(0.0, objectiveValue - originalValue); int iStatus = (feasible) ? 0 : 0; double value = obj->value(); double movement; if (branch) movement = ceil(value) - value; else movement = value - floor(value); branchingMethod_->chooseMethod()->updateInformation(iObject, branch, changeInObjective, movement, iStatus); } } } #ifdef CBC_DEBUG if (feasible) { printf("Obj value %g (%s) %d rows\n", solver_->getObjValue(), (solver_->isProvenOptimal()) ? "proven" : "unproven", solver_->getNumRows()) ; } else { printf("Infeasible %d rows\n", solver_->getNumRows()) ; } #endif if ((specialOptions_&1) != 0) { /* If the RowCutDebugger said we were compatible with the optimal solution, and now we're suddenly infeasible, we might be confused. Then again, we may have fathomed by bound, heading for a rediscovery of an optimal solution. */ if (onOptimalPath && !solver_->isDualObjectiveLimitReached()) { if (!feasible) { solver_->writeMpsNative("infeas.mps", NULL, NULL, 2); solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); CoinWarmStartBasis *slack = dynamic_cast(solver_->getEmptyWarmStart()) ; solver_->setWarmStart(slack); delete slack ; solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0) ; solver_->initialSolve(); } assert(feasible) ; } } if (!feasible) { numberInfeasibleNodes_++; # ifdef COIN_HAS_CLP if (clpSolver) clpSolver->setSpecialOptions(saveClpOptions); # endif return (false) ; } double change = lastObjective - objectiveValue; if (change > 1.0e-10) { dblParam_[CbcSmallestChange] = CoinMin(dblParam_[CbcSmallestChange], change); dblParam_[CbcSumChange] += change; dblParam_[CbcLargestChange] = CoinMax(dblParam_[CbcLargestChange], change); intParam_[CbcNumberBranches]++; } sumChangeObjective1_ += solver_->getObjValue() * solver_->getObjSense() - objectiveValue ; if ( maximumSecondsReached() ) numberTries = 0; // exit //if ((numberNodes_%100)==0) //printf("XXa sum obj changed by %g\n",sumChangeObjective1_); objectiveValue = solver_->getObjValue() * solver_->getObjSense(); // Return at once if numberTries zero if (!numberTries) { cuts = OsiCuts(); numberNewCuts_ = 0; # ifdef COIN_HAS_CLP if (clpSolver) clpSolver->setSpecialOptions(saveClpOptions); # endif setPointers(solver_); return true; } /* Do reduced cost fixing. */ int xxxxxx = 0; if (xxxxxx) solver_->resolve(); reducedCostFix() ; /* Set up for at most numberTries rounds of cut generation. If numberTries is negative, we'll ignore the minimumDrop_ cutoff and keep generating cuts for the specified number of rounds. */ double minimumDrop = minimumDrop_ ; bool allowZeroIterations = false; int maximumBadPasses = 0; if (numberTries < 0) { numberTries = -numberTries ; // minimumDrop *= 1.0e-5 ; // if (numberTries >= -1000000) { //numberTries=100; minimumDrop = -1.0; // } //numberTries=CoinMax(numberTries,100); allowZeroIterations = true; } int saveNumberTries=numberTries; /* Is it time to scan the cuts in order to remove redundant cuts? If so, set up to do it. */ int fullScan = 0 ; if ((numberNodes_ % SCANCUTS) == 0 || (specialOptions_&256) != 0) { fullScan = 1 ; if (!numberNodes_ || (specialOptions_&256) != 0) fullScan = 2; specialOptions_ &= ~256; // mark as full scan done } double direction = solver_->getObjSense() ; double startObjective = solver_->getObjValue() * direction ; currentPassNumber_ = 0 ; // Really primalIntegerTolerance; relates to an illposed problem with various // integer solutions depending on integer tolerance. //double primalTolerance = 1.0e-7 ; // We may need to keep going on bool keepGoing = false; // Say we have not tried one last time int numberLastAttempts = 0; /* Get experimental option as to when to stop adding cuts 0 - old style 1 - new style 2 - new style plus don't break if zero cuts first time 3 - as 2 but last drop has to be >0.1*min to say OK */ int experimentBreak = (moreSpecialOptions_ >> 11) & 3; // Whether to increase minimum drop bool increaseDrop = (moreSpecialOptions_ & 8192) != 0; for (int i = 0; i < numberCutGenerators_; i++) generator_[i]->setWhetherInMustCallAgainMode(false); /* Begin cut generation loop. Cuts generated during each iteration are collected in theseCuts. The loop can be divided into four phases: 1) Prep: Fix variables using reduced cost. In the first iteration only, consider scanning globalCuts_ and activating any applicable cuts. 2) Cut Generation: Call each generator and heuristic registered in the generator_ and heuristic_ arrays. Newly generated global cuts are copied to globalCuts_ at this time. 3) Cut Installation and Reoptimisation: Install column and row cuts in the solver. Copy row cuts to cuts (parameter). Reoptimise. 4) Cut Purging: takeOffCuts() removes inactive cuts from the solver, and does the necessary bookkeeping in the model. */ do { currentPassNumber_++ ; numberTries-- ; if (numberTries < 0 && keepGoing) { // switch off all normal generators (by the generator's opinion of normal) // Intended for situations where the primal problem really isn't complete, // and there are `not normal' cut generators that will augment. for (int i = 0; i < numberCutGenerators_; i++) { if (!generator_[i]->mustCallAgain()) generator_[i]->setSwitchedOff(true); else generator_[i]->setWhetherInMustCallAgainMode(true); } } keepGoing = false; OsiCuts theseCuts ; /* Scan previously generated global column and row cuts to see if any are useful. */ int numberViolated = 0; if ((currentPassNumber_ == 1 ||!numberNodes_) && howOftenGlobalScan_ > 0 && (numberNodes_ % howOftenGlobalScan_) == 0 && (doCutsNow(1) || true)) { // global column cuts now done in node at top of tree int numberCuts = numberCutGenerators_ ? globalCuts_.sizeRowCuts() : 0; if (numberCuts) { // possibly extend whichGenerator resizeWhichGenerator(numberViolated, numberViolated + numberCuts); // only add new cuts up to 10% of current elements int numberElements = solver_->getNumElements(); int numberColumns = solver_->getNumCols(); int maximumAdd = CoinMax(numberElements/10,2*numberColumns)+100; double * violations = new double[numberCuts]; int * which = new int[numberCuts]; int numberPossible=0; for (int i = 0; i < numberCuts; i++) { OsiRowCut * thisCut = globalCuts_.rowCutPtr(i) ; double violation = thisCut->violated(cbcColSolution_); if(thisCut->effectiveness() == COIN_DBL_MAX) { // see if already there int j; for (j = 0; j < currentNumberCuts_; j++) { if (addedCuts_[j]==thisCut) break; } if (j==currentNumberCuts_) violation = COIN_DBL_MAX; //else //printf("already done??\n"); } if (violation > 0.005) { violations[numberPossible]=-violation; which[numberPossible++]=i; } } CoinSort_2(violations,violations+numberPossible,which); for (int i = 0; i < numberPossible; i++) { int k=which[i]; OsiRowCut * thisCut = globalCuts_.rowCutPtr(k) ; assert (thisCut->violated(cbcColSolution_) > 0.005/*primalTolerance*/ || thisCut->effectiveness() == COIN_DBL_MAX); #define CHECK_DEBUGGER #ifdef CHECK_DEBUGGER if ((specialOptions_&1) != 0 ) { CoinAssert (!solver_->getRowCutDebuggerAlways()->invalidCut(*thisCut)); } #endif #if 0 //ndef NDEBUG printf("Global cut added - violation %g\n", thisCut->violated(cbcColSolution_)) ; #endif whichGenerator_[numberViolated++] = -1; #ifndef GLOBAL_CUTS_JUST_POINTERS theseCuts.insert(*thisCut) ; #else theseCuts.insert(thisCut) ; #endif if (violations[i]!=-COIN_DBL_MAX) maximumAdd -= thisCut->row().getNumElements(); if (maximumAdd<0) break; } delete [] which; delete [] violations; numberGlobalViolations_ += numberViolated; } } /* Generate new cuts (global and/or local) and/or apply heuristics. If CglProbing is used, then it should be first as it can fix continuous variables. At present, CglProbing is the only case where generateCuts will return true. generateCuts actually modifies variable bounds in the solver when CglProbing indicates that it can fix a variable. Reoptimisation is required to take full advantage. The need to resolve here should only happen after a heuristic solution. optimalBasisIsAvailable resolves to basisIsAvailable, which seems to be part of the old OsiSimplex API. Doc'n says `Returns true if a basis is available and the problem is optimal. Should be used to see if the BinvARow type operations are possible and meaningful.' Which means any solver other the clp is probably doing a lot of unnecessary resolves right here. (Note default OSI implementation of optimalBasisIsAvailable always returns false.) */ if (solverCharacteristics_->warmStart() && !solver_->optimalBasisIsAvailable()) { //printf("XXXXYY no opt basis\n"); #ifdef JJF_ZERO//def COIN_HAS_CLP //OsiClpSolverInterface * clpSolver //= dynamic_cast (solver_); int save = 0; if (clpSolver) { save = clpSolver->specialOptions(); clpSolver->setSpecialOptions(save | 2048/*4096*/); // Bonmin } #endif resolve(node ? node->nodeInfo() : NULL, 3); #ifdef JJF_ZERO//def COIN_HAS_CLP if (clpSolver) clpSolver->setSpecialOptions(save); #ifdef CLP_INVESTIGATE if (clpSolver->getModelPtr()->numberIterations()) printf("ITS %d pass %d\n", clpSolver->getModelPtr()->numberIterations(), currentPassNumber_); #endif #endif } if (nextRowCut_) { // branch was a cut - add it theseCuts.insert(*nextRowCut_); if (handler_->logLevel() > 1) nextRowCut_->print(); const OsiRowCut * cut = nextRowCut_; double lb = cut->lb(); double ub = cut->ub(); int n = cut->row().getNumElements(); const int * column = cut->row().getIndices(); const double * element = cut->row().getElements(); double sum = 0.0; for (int i = 0; i < n; i++) { int iColumn = column[i]; double value = element[i]; //if (cbcColSolution_[iColumn]>1.0e-7) //printf("value of %d is %g\n",iColumn,cbcColSolution_[iColumn]); sum += value * cbcColSolution_[iColumn]; } delete nextRowCut_; nextRowCut_ = NULL; if (handler_->logLevel() > 1) printf("applying branch cut, sum is %g, bounds %g %g\n", sum, lb, ub); // possibly extend whichGenerator resizeWhichGenerator(numberViolated, numberViolated + 1); // set whichgenerator (also serves as marker to say don't delete0 whichGenerator_[numberViolated++] = -2; } // reset probing info //if (probingInfo_) //probingInfo_->initializeFixing(); int i; // If necessary make cut generators work harder bool strongCuts = (!node && cut_obj[CUT_HISTORY-1] != -COIN_DBL_MAX && fabs(cut_obj[CUT_HISTORY-1] - cut_obj[CUT_HISTORY-2]) < 1.0e-7 + 1.0e-6 * fabs(cut_obj[CUT_HISTORY-1])); for (i = 0; i < numberCutGenerators_; i++) generator_[i]->setIneffectualCuts(strongCuts); // Print details if (!node) { handler_->message(CBC_ROOT_DETAIL, messages_) << currentPassNumber_ << solver_->getNumRows() << solver_->getNumRows() - numberRowsAtContinuous_ << solver_->getObjValue() << CoinMessageEol ; } //Is Necessary for Bonmin? Always keepGoing if cuts have been generated in last iteration (taken from similar code in Cbc-2.4) if (solverCharacteristics_->solutionAddsCuts()&&numberViolated) { for (i = 0;imustCallAgain()) { keepGoing=true; // say must go round break; } } } if(!keepGoing){ // Status for single pass of cut generation int status = 0; /* threadMode with bit 2^1 set indicates we should use threads for root cut generation. */ if ((threadMode_&2) == 0 || numberNodes_) { status = serialCuts(theseCuts, node, slackCuts, lastNumberCuts); } else { // do cuts independently #ifdef CBC_THREAD status = parallelCuts(master, theseCuts, node, slackCuts, lastNumberCuts); #endif } // Do we need feasible and violated? feasible = (status >= 0); if (status == 1) keepGoing = true; else if (status == 2) numberTries = 0; if (!feasible) violated = -2; } //if (!feasible) //break; /* End of the loop to exercise each generator - try heuristics - unless at root node and first pass */ if ((numberNodes_ || currentPassNumber_ != 1) && true) { double * newSolution = new double [numberColumns] ; double heuristicValue = getCutoff() ; int found = -1; // no solution found int whereFrom = numberNodes_ ? 4 : 1; for (i = 0; i < numberHeuristics_; i++) { // skip if can't run here if (!heuristic_[i]->shouldHeurRun(whereFrom)) continue; // see if heuristic will do anything double saveValue = heuristicValue ; int ifSol = heuristic_[i]->solution(heuristicValue, newSolution); //theseCuts) ; if (ifSol > 0) { // better solution found heuristic_[i]->incrementNumberSolutionsFound(); found = i ; incrementUsed(newSolution); lastHeuristic_ = heuristic_[found]; #ifdef CLP_INVESTIGATE printf("HEUR %s where %d A\n", lastHeuristic_->heuristicName(), whereFrom); #endif // CBC_ROUNDING is symbolic; just says found by heuristic setBestSolution(CBC_ROUNDING, heuristicValue, newSolution) ; whereFrom |= 8; // say solution found } else if (ifSol < 0) { heuristicValue = saveValue ; } } /* Did any of the heuristics turn up a new solution? Record it before we free the vector. */ if (found >= 0) { phase_ = 4; CbcTreeLocal * tree = dynamic_cast (tree_); if (tree) tree->passInSolution(bestSolution_, heuristicValue); } delete [] newSolution ; } #ifdef JJF_ZERO // switch on to get all cuts printed theseCuts.printCuts() ; #endif int numberColumnCuts = theseCuts.sizeColCuts() ; int numberRowCuts = theseCuts.sizeRowCuts() ; if (violated >= 0) violated = numberRowCuts + numberColumnCuts ; /* Apply column cuts (aka bound tightening). This may be partially redundant for column cuts returned by CglProbing, as generateCuts installs bounds from CglProbing when it determines it can fix a variable. TODO: Looks like the use of violated has evolved. The value set above is completely ignored. All that's left is violated == -1 indicates some cut is violated, violated == -2 indicates infeasibility. Only infeasibility warrants exceptional action. TODO: Strikes me that this code will fail to detect infeasibility, because the breaks escape the inner loops but the outer loop keeps going. Infeasibility in an early cut will be overwritten if a later cut is merely violated. */ if (numberColumnCuts) { #ifdef CBC_DEBUG double * oldLower = new double [numberColumns] ; double * oldUpper = new double [numberColumns] ; memcpy(oldLower, cbcColLower_, numberColumns*sizeof(double)) ; memcpy(oldUpper, cbcColUpper_, numberColumns*sizeof(double)) ; #endif double integerTolerance = getDblParam(CbcIntegerTolerance) ; for (int i = 0; i < numberColumnCuts; i++) { const OsiColCut * thisCut = theseCuts.colCutPtr(i) ; const CoinPackedVector & lbs = thisCut->lbs() ; const CoinPackedVector & ubs = thisCut->ubs() ; int j ; int n ; const int * which ; const double * values ; n = lbs.getNumElements() ; which = lbs.getIndices() ; values = lbs.getElements() ; for (j = 0; j < n; j++) { int iColumn = which[j] ; double value = cbcColSolution_[iColumn] ; #if CBC_DEBUG>1 printf("%d %g %g %g %g\n", iColumn, oldLower[iColumn], cbcColSolution_[iColumn], oldUpper[iColumn], values[j]) ; #endif solver_->setColLower(iColumn, values[j]) ; if (value < values[j] - integerTolerance) violated = -1 ; if (values[j] > cbcColUpper_[iColumn] + integerTolerance) { // infeasible violated = -2 ; break ; } } n = ubs.getNumElements() ; which = ubs.getIndices() ; values = ubs.getElements() ; for (j = 0; j < n; j++) { int iColumn = which[j] ; double value = cbcColSolution_[iColumn] ; #if CBC_DEBUG>1 printf("%d %g %g %g %g\n", iColumn, oldLower[iColumn], cbcColSolution_[iColumn], oldUpper[iColumn], values[j]) ; #endif solver_->setColUpper(iColumn, values[j]) ; if (value > values[j] + integerTolerance) violated = -1 ; if (values[j] < cbcColLower_[iColumn] - integerTolerance) { // infeasible violated = -2 ; break ; } } } #ifdef CBC_DEBUG delete [] oldLower ; delete [] oldUpper ; #endif } /* End installation of column cuts. The break here escapes the numberTries loop. */ if (violated == -2 || !feasible) { // infeasible feasible = false ; violated = -2; if (!numberNodes_) messageHandler()->message(CBC_INFEAS, messages()) << CoinMessageEol ; break ; } /* Now apply the row (constraint) cuts. This is a bit more work because we need to obtain and augment the current basis. TODO: Why do this work, if there are no row cuts? The current basis will do just fine. */ int numberRowsNow = solver_->getNumRows() ; #ifndef NDEBUG assert(numberRowsNow == numberRowsAtStart + lastNumberCuts) ; #else // ? maybe clue to threaded problems if (numberRowsNow != numberRowsAtStart + lastNumberCuts) { fprintf(stderr, "*** threaded error - numberRowsNow(%d) != numberRowsAtStart(%d)+lastNumberCuts(%d)\n", numberRowsNow, numberRowsAtStart, lastNumberCuts); fprintf(stdout, "*** threaded error - numberRowsNow(%d) != numberRowsAtStart(%d)+lastNumberCuts(%d)\n", numberRowsNow, numberRowsAtStart, lastNumberCuts); abort(); } #endif int numberToAdd = theseCuts.sizeRowCuts() ; numberNewCuts_ = lastNumberCuts + numberToAdd ; /* Now actually add the row cuts and reoptimise. Install the cuts in the solver using applyRowCuts and augment the basis with the corresponding slack. We also add each row cut to the set of row cuts (cuts.insert()) supplied as a parameter. The new basis must be set with setWarmStart(). TODO: Seems to me the original code could allocate addCuts with size 0, if numberRowCuts was 0 and numberColumnCuts was nonzero. That might explain the memory fault noted in the comment by AJK. Unfortunately, just commenting out the delete[] results in massive memory leaks. Try a revision to separate the row cut case. Why do we need addCuts at all? A typing issue, apparently: OsiCut vs. OsiRowCut. TODO: It looks to me as if numberToAdd and numberRowCuts are identical at this point. Confirm & get rid of one of them. TODO: Any reason why the three loops can't be consolidated? */ const OsiRowCut ** addCuts = NULL; if (numberRowCuts > 0 || numberColumnCuts > 0) { if (numberToAdd > 0) { int i ; // Faster to add all at once addCuts = new const OsiRowCut * [numberToAdd] ; for (i = 0 ; i < numberToAdd ; i++) { addCuts[i] = &theseCuts.rowCut(i) ; } if ((specialOptions_&262144) != 0 && !parentModel_) { //save for (i = 0 ; i < numberToAdd ; i++) storedRowCuts_->addCut(*addCuts[i]); } solver_->applyRowCuts(numberToAdd, addCuts) ; CoinWarmStartBasis * basis = dynamic_cast(solver_->getWarmStart()) ; assert(basis != NULL); // make sure not volume /* dylp bug Consistent size used by OsiDylp as sanity check. Implicit resize seen as an error. Hence this call to resize is necessary. */ basis->resize(numberRowsAtStart + numberNewCuts_, numberColumns) ; for (i = 0 ; i < numberToAdd ; i++) { basis->setArtifStatus(numberRowsNow + i, CoinWarmStartBasis::basic) ; } if (solver_->setWarmStart(basis) == false) { throw CoinError("Fail setWarmStart() after cut installation.", "solveWithCuts", "CbcModel") ; } delete basis; } //solver_->setHintParam(OsiDoDualInResolve,false,OsiHintTry); feasible = ( resolve(node ? node->nodeInfo() : NULL, 2) != 0) ; //solver_->setHintParam(OsiDoDualInResolve,true,OsiHintTry); if ( maximumSecondsReached() ) { numberTries = -1000; // exit feasible = false; break; } # ifdef CBC_DEBUG printf("Obj value after cuts %g %d rows\n", solver_->getObjValue(), solver_->getNumRows()) ; if (onOptimalPath && !solver_->isDualObjectiveLimitReached()) assert(feasible) ; # endif } /* No cuts. Cut short the cut generation (numberTries) loop. */ else if (numberLastAttempts > 2 || experimentBreak < 2) { numberTries = 0 ; } /* If the problem is still feasible, first, call takeOffCuts() to remove cuts that are now slack. takeOffCuts() will call the solver to reoptimise if that's needed to restore a valid solution. Next, see if we should quit due to diminishing returns: * we've tried three rounds of cut generation and we're getting insufficient improvement in the objective; or * we generated no cuts; or * the solver declared optimality with 0 iterations after we added the cuts generated in this round. If we decide to keep going, prep for the next iteration. It just seems more safe to tell takeOffCuts() to call resolve(), even if we're not continuing cut generation. Otherwise code executed between here and final disposition of the node will need to be careful not to access the lp solution. It can happen that we lose feasibility in takeOffCuts --- numerical jitters when the cutoff bound is epsilon less than the current best, and we're evaluating an alternative optimum. TODO: After successive rounds of code motion, there seems no need to distinguish between the two checks for aborting the cut generation loop. Confirm and clean up. */ if (feasible) { int cutIterations = solver_->getIterationCount() ; if (numberOldActiveCuts_ + numberNewCuts_ && (numberNewCuts_ || doCutsNow(1)) ) { OsiCuts * saveCuts = node ? NULL : &slackCuts; int nDel = takeOffCuts(cuts, resolveAfterTakeOffCuts_, saveCuts, numberToAdd, addCuts) ; if (nDel) lastNumberCuts2_ = 0; if (solver_->isDualObjectiveLimitReached() && resolveAfterTakeOffCuts_) { feasible = false ; # ifdef CBC_DEBUG double z = solver_->getObjValue() ; double cut = getCutoff() ; printf("Lost feasibility by %g in takeOffCuts; z = %g, cutoff = %g\n", z - cut, z, cut) ; # endif } } delete [] addCuts ; if (feasible) { numberRowsAtStart = numberOldActiveCuts_ + numberRowsAtContinuous_ ; lastNumberCuts = numberNewCuts_ ; double thisObj = direction * solver_->getObjValue(); bool badObj = (allowZeroIterations) ? thisObj < cut_obj[0] + minimumDrop : thisObj < cut_obj[CUT_HISTORY-1] + minimumDrop; #ifdef JJF_ZERO // probably not a good idea if (!badObj) numberLastAttempts = CoinMax(0, numberLastAttempts - 1); #endif // Compute maximum number of bad passes if (minimumDrop > 0.0) { if (increaseDrop) { // slowly increase minimumDrop; breakpoints are rule-of-thumb if (currentPassNumber_ == 13) minimumDrop = CoinMax(1.5 * minimumDrop, 1.0e-5 * fabs(thisObj)); else if (currentPassNumber_ > 20 && (currentPassNumber_ % 5) == 0) minimumDrop = CoinMax(1.1 * minimumDrop, 1.0e-5 * fabs(thisObj)); else if (currentPassNumber_ > 50) minimumDrop = CoinMax(1.1 * minimumDrop, 1.0e-5 * fabs(thisObj)); } int nBadPasses = 0; // The standard way of determining escape if (!experimentBreak) { double test = 0.01 * minimumDrop; double goodDrop = COIN_DBL_MAX; for (int j = CUT_HISTORY - 1; j >= 0; j--) { if (thisObj - cut_obj[j] < test) { nBadPasses++; } else { goodDrop = (thisObj - cut_obj[j]) / static_cast(nBadPasses + 1); break; } } maximumBadPasses = CoinMax(maximumBadPasses, nBadPasses); if (nBadPasses < maximumBadPasses && goodDrop > minimumDrop) badObj = false; // carry on } else { // Experimental escape calculations //if (currentPassNumber_==13||currentPassNumber_>50) //minimumDrop = CoinMax(1.5*minimumDrop,1.0e-5*fabs(thisObj)); double test = 0.1 * minimumDrop; double goodDrop = (thisObj - cut_obj[0]) / static_cast(CUT_HISTORY); double objValue = thisObj; for (int j = CUT_HISTORY - 1; j >= 0; j--) { if (objValue - cut_obj[j] < test) { nBadPasses++; objValue = cut_obj[j]; } else { break; } } #ifdef CLP_INVESTIGATE2 if (!parentModel_ && !numberNodes_) printf("badObj %s nBad %d maxBad %d goodDrop %g minDrop %g thisDrop %g obj %g\n", badObj ? "true" : "false", nBadPasses, maximumBadPasses, goodDrop, minimumDrop, thisObj - cut_obj[CUT_HISTORY-1], solver_->getObjValue()); #endif maximumBadPasses = CoinMax(maximumBadPasses, nBadPasses); if (nBadPasses < 2 || goodDrop > 2.0*minimumDrop) { if (experimentBreak <= 2 || goodDrop > 0.1*minimumDrop) badObj = false; // carry on } if (experimentBreak > 1 && goodDrop < minimumDrop) numberLastAttempts++; } } // magic numbers, they seemed reasonable; there's a possibility here of going more than // nominal number of passes if we're doing really well. if (numberTries == 1 && currentDepth_ < 12 && currentPassNumber_ < 10) { double drop[12] = {1.0, 2.0, 3.0, 10.0, 10.0, 10.0, 10.0, 20.0, 100.0, 100.0, 1000.0, 1000.0}; if (thisObj - lastObjective > drop[currentDepth_]*minimumDrop) { numberTries++; #ifdef CLP_INVESTIGATE //printf("drop %g %g %d\n",thisObj,lastObjective,currentPassNumber_); #endif } } for (int j = 0; j < CUT_HISTORY - 1; j++) cut_obj[j] = cut_obj[j+1]; cut_obj[CUT_HISTORY-1] = thisObj; bool allowEarlyTermination = currentPassNumber_ >= 10; if (currentDepth_ > 10 || (currentDepth_ > 5 && numberColumns > 200)) allowEarlyTermination = true; //if (badObj && (currentPassNumber_ >= 10 || (currentDepth_>10)) if (badObj && allowEarlyTermination //&&(currentPassNumber_>=10||lastObjective>firstObjective) && !keepGoing) { numberTries = 0 ; } if (numberRowCuts + numberColumnCuts == 0 || (cutIterations == 0 && !allowZeroIterations) ) { // maybe give it one more try if (numberLastAttempts > 2 || currentDepth_ || experimentBreak < 2) numberTries=0 ; else numberLastAttempts++; } if (numberTries > 0) { reducedCostFix() ; lastObjective = direction * solver_->getObjValue() ; } } } else { // not feasible delete [] addCuts ; } /* We've lost feasibility --- this node won't be referencing the cuts we've been collecting, so decrement the reference counts. */ if (!feasible) { int i ; if (currentNumberCuts_) { lockThread(); for (i = 0; i < currentNumberCuts_; i++) { // take off node if (addedCuts_[i]) { if (!addedCuts_[i]->decrement()) delete addedCuts_[i] ; addedCuts_[i] = NULL ; } } unlockThread(); } numberTries = 0 ; keepGoing=false; } if (numberTries ==0 && feasible && !keepGoing && !parentModel_ && !numberNodes_) { for (int i = 0; i < numberCutGenerators_; i++) { if (generator_[i]->whetherCallAtEnd() &&!generator_[i]->whetherInMustCallAgainMode()) { // give it some goes and switch off numberTries=(saveNumberTries+4)/5; generator_[i]->setWhetherCallAtEnd(false); } } } } while (numberTries > 0 || keepGoing) ; /* End cut generation loop. */ { // switch on for (int i = 0; i < numberCutGenerators_; i++) generator_[i]->setSwitchedOff(false); } //check feasibility. //If solution seems to be integer feasible calling setBestSolution //will eventually add extra global cuts which we need to install at //the nodes if (feasible && solverCharacteristics_->solutionAddsCuts()) { //check integer feasibility bool integerFeasible = true; const double * save = testSolution_; testSolution_ = solver_->getColSolution(); // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); for (int i = 0; i < numberObjects_ && integerFeasible; i++) { int preferredWay; double infeasibility = object_[i]->infeasibility(&usefulInfo, preferredWay); if (infeasibility) integerFeasible = false; } testSolution_ = save; // Consider the possibility that some alternatives here only make sense in context // of bonmin. if (integerFeasible) { //update double objValue = solver_->getObjValue(); int numberGlobalBefore = globalCuts_.sizeRowCuts(); // SOLUTION2 so won't up cutoff or print message setBestSolution(CBC_SOLUTION2, objValue, solver_->getColSolution(), 0); int numberGlobalAfter = globalCuts_.sizeRowCuts(); int numberToAdd = numberGlobalAfter - numberGlobalBefore; if (numberToAdd > 0) //We have added some cuts say they are tight at that node //Basis and lp should already have been updated { feasible = (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached()) ; if (feasible) { int numberCuts = numberNewCuts_ = cuts.sizeRowCuts(); // possibly extend whichGenerator resizeWhichGenerator(numberCuts, numberToAdd + numberCuts); for (int i = numberGlobalBefore ; i < numberGlobalAfter ; i++) { whichGenerator_[numberNewCuts_++] = -1; #ifndef GLOBAL_CUTS_JUST_POINTERS cuts.insert(*globalCuts_.rowCutPtr(i)) ; #else OsiRowCut * rowCutPointer = globalCuts_.rowCutPtr(i); cuts.insert(rowCutPointer) ; #endif } numberNewCuts_ = lastNumberCuts + numberToAdd; //now take off the cuts which are not tight anymore takeOffCuts(cuts, resolveAfterTakeOffCuts_, NULL) ; if (solver_->isDualObjectiveLimitReached() && resolveAfterTakeOffCuts_) { feasible = false ; } } if (!feasible) { //node will be fathomed lockThread(); for (int i = 0; i < currentNumberCuts_; i++) { // take off node if (addedCuts_[i]) { if (!addedCuts_[i]->decrement()) delete addedCuts_[i] ; addedCuts_[i] = NULL ; } } unlockThread(); } } } } /* End of code block to check for a solution, when cuts may be added as a result of a feasible solution. Reduced cost fix at end. Must also check feasible, in case we've popped out because a generator indicated we're infeasible. */ if (feasible && solver_->isProvenOptimal()) reducedCostFix() ; // If at root node do heuristics if (!numberNodes_ && !maximumSecondsReached()) { // First see if any cuts are slack int numberRows = solver_->getNumRows(); int numberAdded = numberRows - numberRowsAtContinuous_; if (numberAdded) { CoinWarmStartBasis * basis = dynamic_cast(solver_->getWarmStart()) ; assert(basis != NULL); int * added = new int[numberAdded]; int nDelete = 0; for (int j = numberRowsAtContinuous_; j < numberRows; j++) { if (basis->getArtifStatus(j) == CoinWarmStartBasis::basic) { //printf("%d slack!\n",j); added[nDelete++] = j; } } if (nDelete) { solver_->deleteRows(nDelete, added); } delete [] added; delete basis ; } // mark so heuristics can tell int savePass = currentPassNumber_; currentPassNumber_ = 999999; double * newSolution = new double [numberColumns] ; double heuristicValue = getCutoff() ; int found = -1; // no solution found if (feasible) { int whereFrom = node ? 3 : 2; for (int i = 0; i < numberHeuristics_; i++) { // skip if can't run here if (!heuristic_[i]->shouldHeurRun(whereFrom)) continue; // see if heuristic will do anything double saveValue = heuristicValue ; int ifSol = heuristic_[i]->solution(heuristicValue, newSolution); if (ifSol > 0) { // better solution found heuristic_[i]->incrementNumberSolutionsFound(); found = i ; incrementUsed(newSolution); lastHeuristic_ = heuristic_[found]; #ifdef CLP_INVESTIGATE printf("HEUR %s where %d B\n", lastHeuristic_->heuristicName(), whereFrom); #endif setBestSolution(CBC_ROUNDING, heuristicValue, newSolution) ; whereFrom |= 8; // say solution found } else { heuristicValue = saveValue ; } } } currentPassNumber_ = savePass; if (found >= 0) { phase_ = 4; } delete [] newSolution ; } // Up change due to cuts if (feasible) sumChangeObjective2_ += solver_->getObjValue() * solver_->getObjSense() - objectiveValue ; //if ((numberNodes_%100)==0) //printf("XXb sum obj changed by %g\n",sumChangeObjective2_); /* End of cut generation loop. Now, consider if we want to disable or adjust the frequency of use for any of the cut generators. If the client specified a positive number for howOften, it will never change. If the original value was negative, it'll be converted to 1000000+|howOften|, and this value will be adjusted each time fullScan is true. Actual cut generation is performed every howOften%1000000 nodes; the 1000000 offset is just a convenient way to specify that the frequency is adjustable. During cut generation, we recorded the number of cuts produced by each generator for this node. For all cuts, whichGenerator records the generator that produced a cut. TODO: All this should probably be hidden in a method of the CbcCutGenerator class. lh: TODO: Can the loop that scans over whichGenerator to accumulate per generator counts be replaced by values in countRowCuts and countColumnCuts? << I think the answer is yes, but not the other way 'round. Row and column cuts are block interleaved in whichGenerator. >> The root is automatically a full scan interval. At the root, decide if we're going to do cuts in the tree, and whether we should keep the cuts we have. Codes for willBeCutsInTree: -1: no cuts in tree and currently active cuts seem ineffective; delete them 0: no cuts in tree but currently active cuts seem effective; make them into architecturals (faster than treating them as cuts) 1: cuts will be generated in the tree; currently active cuts remain as cuts -lh */ #ifdef NODE_LOG int fatherNum = (node == NULL) ? -1 : node->nodeNumber(); double value = (node == NULL) ? -1 : node->branchingObject()->value(); string bigOne = (solver_->getIterationCount() > 30) ? "*******" : ""; string way = (node == NULL) ? "" : (node->branchingObject()->way()) == 1 ? "Down" : "Up"; std::cout << "Node " << numberNodes_ << ", father " << fatherNum << ", #iterations " << solver_->getIterationCount() << ", sol value : " << solver_->getObjValue() << std::endl; #endif if (fullScan && numberCutGenerators_) { /* If cuts just at root node then it will probably be faster to update matrix and leave all in */ int willBeCutsInTree = 0; double thisObjective = solver_->getObjValue() * direction ; // get sizes int numberRowsAdded = solver_->getNumRows() - numberRowsAtStart; CoinBigIndex numberElementsAdded = solver_->getNumElements() - numberElementsAtStart ; double densityOld = static_cast (numberElementsAtStart) / static_cast (numberRowsAtStart); double densityNew = numberRowsAdded ? (static_cast (numberElementsAdded)) / static_cast (numberRowsAdded) : 0.0; /* If we're at the root, and we added cuts, and the cuts haven't changed the objective, and the cuts resulted in a significant increase (> 20%) in nonzero coefficients, do no cuts in the tree and ditch the current cuts. They're not cost-effective. */ if (!numberNodes_) { if (!parentModel_) { //printf("%d global cuts\n",globalCuts_.sizeRowCuts()) ; if ((specialOptions_&1) != 0) { //specialOptions_ &= ~1; int numberCuts = globalCuts_.sizeRowCuts(); const OsiRowCutDebugger *debugger = continuousSolver_->getRowCutDebugger() ; if (debugger) { for (int i = 0; i < numberCuts; i++) { OsiRowCut * cut = globalCuts_.rowCutPtr(i) ; if (debugger->invalidCut(*cut)) { continuousSolver_->applyRowCuts(1,cut); continuousSolver_->writeMps("bad"); printf("BAD cut\n"); } //CoinAssert (!debugger->invalidCut(*cut)); } } } } //solver_->writeMps("second"); if (numberRowsAdded) handler_->message(CBC_CUTS_STATS, messages_) << numberRowsAdded << densityNew << CoinMessageEol ; if (thisObjective - startObjective < 1.0e-5 && numberElementsAdded > 0.2*numberElementsAtStart) willBeCutsInTree = -1; int whenC = whenCuts_; if (whenC == 999999 || whenC == 999998) { int size = continuousSolver_->getNumRows() + continuousSolver_->getNumCols(); bool smallProblem = size <= 550; smallProblem = false; #ifdef CLP_INVESTIGATE int maxPass = maximumCutPasses_; #endif if (thisObjective - startObjective < 1.0e-5) { // No change in objective function if (numberElementsAdded > 0.2*numberElementsAtStart) { if (whenCuts_ == 999999) { whenCuts_ = 5000010; if (!smallProblem) maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1); } else if (whenCuts_ == 999998) { whenCuts_ = 5000010; if (!smallProblem) maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1); } #ifdef JJF_ZERO } else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; maximumCutPasses_ = 1; } else if (whenCuts_ == 999998) { whenCuts_ = 10000008; maximumCutPasses_ = 1; } } else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; maximumCutPasses_ = 1; } else if (whenCuts_ == 999998) { whenCuts_ = 10000006; maximumCutPasses_ = 1; } } else if (currentPassNumber_ < CoinAbs(maximumCutPassesAtRoot_)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; maximumCutPasses_ = 1; } else if (whenCuts_ == 999998) { whenCuts_ = 10000004; maximumCutPasses_ = 1; } #endif } else { if (whenCuts_ == 999999) { whenCuts_ = 8000008; if (!smallProblem) maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1); } else if (whenCuts_ == 999998) { whenCuts_ = 10000004; if (!smallProblem) maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1); } } } else { // Objective changed #ifdef JJF_ZERO if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 8)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; maximumCutPasses_ = 1; } else if (whenCuts_ == 999998) { whenCuts_ = 10000008; maximumCutPasses_ = 1; } } else if (currentPassNumber_ < CoinMin(CoinAbs(maximumCutPassesAtRoot_), 50)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; maximumCutPasses_ = 1; } else if (whenCuts_ == 999998) { whenCuts_ = 10000004; maximumCutPasses_ = 1; } } else #endif if (currentPassNumber_ < CoinAbs(maximumCutPassesAtRoot_)) { if (whenCuts_ == 999999) { whenCuts_ = 8000008; if (!smallProblem) maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1); } else if (whenCuts_ == 999998) { whenCuts_ = 10000004; if (!smallProblem) maximumCutPasses_ = CoinMax(maximumCutPasses_ >> 1, 1); } } else { if (whenCuts_ == 999999) { whenCuts_ = 10000004; maximumCutPasses_ = CoinMax(maximumCutPasses_, 2); } else if (whenCuts_ == 999998) { whenCuts_ = 11000002; maximumCutPasses_ = CoinMax(maximumCutPasses_, 2); } } } // Set bit to say don't try too hard if seems reasonable if (maximumCutPasses_ <= 5) whenCuts_ += 100000; //// end #ifdef CLP_INVESTIGATE printf("changing whenCuts from %d to %d and cutPasses from %d to %d objchange %g\n", whenC, whenCuts_, maxPass, maximumCutPasses_, thisObjective - startObjective); #endif } } /* Noop block 071219. */ if ((numberRowsAdded > 100 + 0.5*numberRowsAtStart || numberElementsAdded > 0.5*numberElementsAtStart) && (densityNew > 200.0 && numberRowsAdded > 100 && densityNew > 2.0*densityOld)) { // much bigger //if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5) //willBeCutsInTree=-1; //printf("Cuts will be taken off , %d rows added with density %g\n", // numberRowsAdded,densityNew); } /* Noop block 071219. */ if (densityNew > 100.0 && numberRowsAdded > 2 && densityNew > 2.0*densityOld) { //if (thisObjective-startObjective<0.1*fabs(startObjective)+1.0e-5) //willBeCutsInTree=-2; //printf("Density says no cuts ? , %d rows added with density %g\n", // numberRowsAdded,densityNew); } // Root node or every so often - see what to turn off /* Hmmm ... > -90 for any generator will overrule previous decision to do no cuts in tree and delete existing cuts. */ int i ; for (i = 0; i < numberCutGenerators_; i++) { int howOften = generator_[i]->howOften() ; if (howOften > -90) willBeCutsInTree = 0; } if (!numberNodes_) { handler_->message(CBC_ROOT, messages_) << numberNewCuts_ << startObjective << thisObjective << currentPassNumber_ << CoinMessageEol ; } /* Count the number of cuts produced by each cut generator on this call. Not clear to me that the accounting is equivalent here. whichGenerator_ records the generator for column and row cuts. So unless numberNewCuts is row cuts only, we're double counting for JUST_ACTIVE. Note too the multiplier applied to column cuts. */ if (!numberNodes_) { double value = CoinMax(minimumDrop_, 0.005 * (thisObjective - startObjective) / static_cast (currentPassNumber_)); if (numberColumns < 200) value = CoinMax(minimumDrop_, 0.1 * value); #ifdef CLP_INVESTIGATE printf("Minimum drop for cuts was %g, now is %g\n", minimumDrop_, value); #endif minimumDrop_ = value; } int * count = new int[numberCutGenerators_] ; memset(count, 0, numberCutGenerators_*sizeof(int)) ; int numberActiveGenerators = 0; for (i = 0; i < numberNewCuts_; i++) { int iGenerator = whichGenerator_[i]; if (iGenerator>=0) iGenerator=iGenerator%10000; if (iGenerator >= 0 && iGenerator < numberCutGenerators_) count[iGenerator]++ ; } // add in any active cuts if at root node (for multiple solvers) if (!numberNodes_) { for (i = 0; i < numberCutGenerators_; i++) count[i] += generator_[i]->numberCutsActive(); } double totalCuts = 0.0 ; //#define JUST_ACTIVE for (i = 0; i < numberCutGenerators_; i++) { if (generator_[i]->numberCutsInTotal() || generator_[i]->numberColumnCuts()) numberActiveGenerators++; #ifdef JUST_ACTIVE double value = count[i] ; #else double value = generator_[i]->numberCutsInTotal() ; #endif totalCuts += value; } /* Open up a loop to step through the cut generators and decide what (if any) adjustment should be made for calling frequency. */ int iProbing = -1; double smallProblem = (0.2 * totalCuts) / static_cast (numberActiveGenerators) ; for (i = 0; i < numberCutGenerators_; i++) { int howOften = generator_[i]->howOften() ; /* Probing can be set to just do column cuts in treee. But if doing good then leave as on Ok, let me try to explain this. rowCuts = 3 says do disaggregation (1<<0) and coefficient (1<<1) cuts. But if the value is negative, there's code at the entry to generateCuts, and generateCutsAndModify, that temporarily changes the value to 4 (1<<2) if we're in a search tree. Which does nothing to explain this next bit. We set a boolean, convert howOften to the code for `generate while objective is improving', and change over to `do everywhere'. Hmmm ... now I write it out, this makes sense in the context of the original comment. If we're doing well (objective improving) we'll keep probing fully active. */ bool probingWasOnBut = false; CglProbing * probing = dynamic_cast(generator_[i]->generator()); if (probing && !numberNodes_) { if (generator_[i]->numberCutsInTotal()) { // If large number of probing - can be biased smallProblem = (0.2 * (totalCuts - generator_[i]->numberCutsInTotal())) / static_cast (numberActiveGenerators - 1) ; } iProbing = i; if (probing->rowCuts() == -3) { probingWasOnBut = true; howOften = -98; probing->setRowCuts(3); } } /* Convert `as long as objective is improving' into `only at root' if we've decided cuts just aren't worth it. */ if (willBeCutsInTree < 0 && howOften == -98) howOften = -99; /* And check to see if the objective is improving. But don't do the check if the user has specified some minimum number of cuts. This exclusion seems bogus, or at least counterintuitive. Why would a user suspect that setting a minimum cut limit would invalidate the objective check? Nor do I see the point in comparing the number of rows and columns in the second test. */ if (!probing && howOften == -98 && !generator_[i]->numberShortCutsAtRoot() && generator_[i]->numberCutsInTotal()) { // switch off as no short cuts generated //printf("Switch off %s?\n",generator_[i]->cutGeneratorName()); howOften = -99; } if (howOften == -98 && generator_[i]->switchOffIfLessThan() > 0) { if (thisObjective - startObjective < 0.005*fabs(startObjective) + 1.0e-5) howOften = -99; // switch off if (thisObjective - startObjective < 0.1*fabs(startObjective) + 1.0e-5 && 5*solver_->getNumRows() < solver_->getNumCols()) howOften = -99; // switch off } if (generator_[i]->maximumTries()!=-1) howOften = CoinMin(howOften,-99); // switch off /* Below -99, this generator is switched off. There's no need to consider further. Then again, there was no point in persisting this far! */ if (howOften < -99) { // may have been switched off - report if (!numberNodes_) { int n = generator_[i]->numberCutsInTotal(); if (n) { double average = 0.0; average = generator_[i]->numberElementsInTotal(); average /= n; handler_->message(CBC_GENERATOR, messages_) << i << generator_[i]->cutGeneratorName() << n << average << generator_[i]->numberColumnCuts() << generator_[i]->numberCutsActive() + generator_[i]->numberColumnCuts(); handler_->printing(generator_[i]->timing()) << generator_[i]->timeInCutGenerator(); handler_->message() << -100 << CoinMessageEol ; } } continue ; } /* Adjust, if howOften is adjustable. */ if (howOften < 0 || howOften >= 1000000) { if ( !numberNodes_) { /* If root only, or objective improvement but no cuts generated, switch off. If it's just that the generator found no cuts at the root, give it one more chance. */ // If small number switch mostly off #ifdef JUST_ACTIVE double thisCuts = count[i] + 5.0 * generator_[i]->numberColumnCuts() ; #else double thisCuts = generator_[i]->numberCutsInTotal() + 5.0 * generator_[i]->numberColumnCuts() ; #endif // Allow on smaller number if <-1 if (generator_[i]->switchOffIfLessThan() < 0) { double multiplier[] = {2.0, 5.0}; int iSwitch = -generator_[i]->switchOffIfLessThan() - 1; assert (iSwitch >= 0 && iSwitch < 2); thisCuts *= multiplier[iSwitch]; } if (!thisCuts || howOften == -99) { if (howOften == -99 || howOften == -98) { howOften = -100 ; } else { howOften = 1000000 + SCANCUTS; // wait until next time if (probing) { // not quite so drastic howOften = 1000000 + 1; probing->setMaxLook(1); probing->setMaxProbe(123); } } /* Not productive, but not zero either. */ } else if ((thisCuts + generator_[i]->numberColumnCuts() < smallProblem) && !generator_[i] ->whetherToUse()) { /* Not unadjustable every node, and not strong probing. */ if (howOften != 1 && !probingWasOnBut) { /* No depth spec, or not adjustable every node. */ if (generator_[i]->whatDepth() < 0 || howOften != -1) { int k = static_cast (sqrt(smallProblem / thisCuts)) ; /* Not objective improvement, set to new frequency, otherwise turn off. */ if (howOften != -98) howOften = k + 1000000 ; else howOften = -100; /* Depth spec, or adjustable every node. Force to unadjustable every node. */ } else { howOften = 1; } /* Unadjustable every node, or strong probing. Force unadjustable every node and force not strong probing? I don't understand. */ } else { howOften = 1; // allow cuts probingWasOnBut = false; } /* Productive cut generator. Say we'll do it every node, adjustable. But if the objective isn't improving, restrict that to every fifth depth level (whatDepth overrides howOften in generateCuts). */ } else { if (thisObjective - startObjective < 0.1*fabs(startObjective) + 1.0e-5 && generator_[i]->whatDepth() < 0) generator_[i]->setWhatDepth(5); howOften = 1 + 1000000 ; } } /* End root actions. sumChangeObjective2_ is the objective change due to cuts. If we're getting much better results from branching over a large number of nodes, switch off cuts. Except it doesn't, really --- it just puts off the decision 'til the next full scan, when it'll put it off again unless cuts look better. */ // If cuts useless switch off if (numberNodes_ >= 100000 && sumChangeObjective1_ > 2.0e2*(sumChangeObjective2_ + 1.0e-12)) { howOften = 1000000 + SCANCUTS; // wait until next time //printf("switch off cut %d due to lack of use\n",i); } } /* Ok, that's the frequency adjustment bit. Now, if we're at the root, force probing back on at every node, for column cuts at least, even if it looks useless for row cuts. Notice that if it looked useful, the values set above mean we'll be doing strong probing in the tree subject to objective improvement. */ if (!numberNodes_) { if (probingWasOnBut && howOften == -100) { probing->setRowCuts(-3); howOften = 1; } if (howOften == 1) generator_[i]->setWhatDepth(1); if (howOften >= 0 && generator_[i]->generator()->mayGenerateRowCutsInTree()) willBeCutsInTree = 1; } /* Set the new frequency in the generator. If this is an adjustable frequency, use the value to set whatDepth. Hey! Seems like this could override the user's depth setting. */ generator_[i]->setHowOften(howOften) ; if (howOften >= 1000000 && howOften < 2000000 && 0) { // Go to depth int bias = 1; if (howOften == 1 + 1000000) generator_[i]->setWhatDepth(bias + 1); else if (howOften <= 10 + 1000000) generator_[i]->setWhatDepth(bias + 2); else generator_[i]->setWhatDepth(bias + 1000); } int newFrequency = generator_[i]->howOften() % 1000000 ; // increment cut counts generator_[i]->incrementNumberCutsActive(count[i]); CglStored * stored = dynamic_cast(generator_[i]->generator()); if (stored && !generator_[i]->numberCutsInTotal()) continue; double average = 0.0; int n = generator_[i]->numberCutsInTotal(); if (n) { average = generator_[i]->numberElementsInTotal(); average /= n; } if (handler_->logLevel() > 1 || !numberNodes_) { handler_->message(CBC_GENERATOR, messages_) << i << generator_[i]->cutGeneratorName() //<numberCutsInTotal()<numberColumnCuts() << generator_[i]->numberCutsActive() + generator_[i]->numberColumnCuts(); handler_->printing(!numberNodes_ && generator_[i]->timing()) << generator_[i]->timeInCutGenerator(); handler_->message() << newFrequency << CoinMessageEol ; } } /* End loop to adjust cut generator frequency of use. */ delete [] count ; if ( !numberNodes_) { // save statistics for (i = 0; i < numberCutGenerators_; i++) { generator_[i]->setNumberCutsAtRoot(generator_[i]->numberCutsInTotal()); generator_[i]->setNumberActiveCutsAtRoot(generator_[i]->numberCutsActive()); } /* Garbage code 071219 */ // decide on pseudo cost strategy int howOften = iProbing >= 0 ? generator_[iProbing]->howOften() : 0; if ((howOften % 1000000) != 1) howOften = 0; //if (howOften) { //CglProbing * probing = dynamic_cast(generator_[iProbing]->generator()); //} howOften = 0; if (howOften) { COIN_DETAIL_PRINT(printf("** method 1\n")); //CglProbing * probing = dynamic_cast(generator_[iProbing]->generator()); generator_[iProbing]->setWhatDepth(1); // could set no row cuts //if (thisObjective-startObjective<0.001*fabs(startObjective)+1.0e-5) // probing->setRowCuts(0); for (int i = 0; i < numberObjects_; i++) { CbcSimpleIntegerDynamicPseudoCost * obj = dynamic_cast (object_[i]) ; if (obj) obj->setMethod(1); } } if (willBeCutsInTree == -2) willBeCutsInTree = 0; /* End garbage code. Now I've reached the problem area. This is a problem only at the root node, so that should simplify the issue of finding a workable basis? Or maybe not. */ if ( willBeCutsInTree <= 0) { // Take off cuts cuts = OsiCuts(); numberNewCuts_ = 0; if (!willBeCutsInTree) { // update size of problem numberRowsAtContinuous_ = solver_->getNumRows() ; } else { // take off cuts int numberRows = solver_->getNumRows(); int numberAdded = numberRows - numberRowsAtContinuous_; if (numberAdded) { int * added = new int[numberAdded]; for (int i = 0; i < numberAdded; i++) added[i] = i + numberRowsAtContinuous_; solver_->deleteRows(numberAdded, added); delete [] added; // resolve so optimal resolve(solver_); } } #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { // Maybe solver might like to know only column bounds will change //int options = clpSolver->specialOptions(); //clpSolver->setSpecialOptions(options|128); clpSolver->synchronizeModel(); } #endif } else { #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { // make sure factorization can't carry over int options = clpSolver->specialOptions(); clpSolver->setSpecialOptions(options&(~8)); } #endif } } } else { #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { // Maybe solver might like to know only column bounds will change //int options = clpSolver->specialOptions(); //clpSolver->setSpecialOptions(options|128); clpSolver->synchronizeModel(); } #endif if (numberCutGenerators_) { int i; // What if not feasible as cuts may have helped if (feasible) { for (i = 0; i < numberNewCuts_; i++) { int iGenerator = whichGenerator_[i]; if (iGenerator>=0) iGenerator=iGenerator%10000; if (iGenerator >= 0) generator_[iGenerator]->incrementNumberCutsActive(); } } } } #ifdef CHECK_CUT_COUNTS if (feasible) { CoinWarmStartBasis * basis = dynamic_cast(solver_->getWarmStart()) ; printf("solveWithCuts: Number of rows at end (only active cuts) %d\n", numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_) ; basis->print() ; delete basis; } #endif #ifdef CBC_DEBUG if (onOptimalPath && !solver_->isDualObjectiveLimitReached()) assert(feasible) ; #endif # ifdef COIN_HAS_CLP if (clpSolver) clpSolver->setSpecialOptions(saveClpOptions); # endif #ifdef CBC_THREAD // Get rid of all threaded stuff if (master) { master->stopThreads(0); delete master; } #endif // make sure pointers are up to date setPointers(solver_); return feasible ; } // Generate one round of cuts - serial mode int CbcModel::serialCuts(OsiCuts & theseCuts, CbcNode * node, OsiCuts & slackCuts, int lastNumberCuts) { /* Is it time to scan the cuts in order to remove redundant cuts? If so, set up to do it. */ int fullScan = 0 ; if ((numberNodes_ % SCANCUTS) == 0 || (specialOptions_&256) != 0) { fullScan = 1 ; if (!numberNodes_ || (specialOptions_&256) != 0) fullScan = 2; specialOptions_ &= ~256; // mark as full scan done } # if 0 //def COIN_HAS_CLP // check basis OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { ClpSimplex * simplex = clpSolver->getModelPtr(); int numberTotal=simplex->numberRows()+simplex->numberColumns(); int superbasic=0; for (int i=0;igetStatus(i)==ClpSimplex::superBasic) superbasic++; } if (superbasic) { printf("%d superbasic!\n",superbasic); clpSolver->resolve(); superbasic=0; for (int i=0;igetStatus(i)==ClpSimplex::superBasic) superbasic++; } assert (!superbasic); } } # endif int switchOff = (!doCutsNow(1) && !fullScan) ? 1 : 0; int status = 0; int i; for (i = 0; i < numberCutGenerators_; i++) { int numberRowCutsBefore = theseCuts.sizeRowCuts() ; int numberColumnCutsBefore = theseCuts.sizeColCuts() ; int numberRowCutsAfter = numberRowCutsBefore; int numberColumnCutsAfter = numberColumnCutsBefore; /*printf("GEN %d %s switches %d\n", i,generator_[i]->cutGeneratorName(), generator_[i]->switches());*/ bool generate = generator_[i]->normal(); // skip if not optimal and should be (maybe a cut generator has fixed variables) if (generator_[i]->howOften() == -100 || (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable()) || generator_[i]->switchedOff()) generate = false; if (switchOff&&!generator_[i]->mustCallAgain()) { // switch off if default if (generator_[i]->howOften() == 1 && generator_[i]->whatDepth() < 0) { generate = false; } else if (currentDepth_ > -10 && switchOff == 2) { generate = false; } } if (generator_[i]->whetherCallAtEnd()) generate=false; const OsiRowCutDebugger * debugger = NULL; bool onOptimalPath = false; if (generate) { bool mustResolve = generator_[i]->generateCuts(theseCuts, fullScan, solver_, node) ; numberRowCutsAfter = theseCuts.sizeRowCuts() ; if (fullScan && generator_[i]->howOften() == 1000000 + SCANCUTS_PROBING) { CglProbing * probing = dynamic_cast(generator_[i]->generator()); if (probing && (numberRowCutsBefore < numberRowCutsAfter || numberColumnCutsBefore < theseCuts.sizeColCuts())) { // switch on generator_[i]->setHowOften(1); } } if (numberRowCutsBefore < numberRowCutsAfter && generator_[i]->mustCallAgain() && status >= 0) /*printf("%s before %d after %d must %c atend %c off %c endmode %c\n", generator_[i]->cutGeneratorName(), numberRowCutsBefore,numberRowCutsAfter, generator_[i]->mustCallAgain() ? 'Y': 'N', generator_[i]->whetherCallAtEnd() ? 'Y': 'N', generator_[i]->switchedOff() ? 'Y': 'N', generator_[i]->whetherInMustCallAgainMode() ? 'Y': 'N');*/ if (numberRowCutsBefore < numberRowCutsAfter && generator_[i]->mustCallAgain() && status >= 0) status = 1 ; // say must go round // Check last cut to see if infeasible /* The convention is that if the generator proves infeasibility, it should return as its last cut something with lb > ub. */ if (numberRowCutsBefore < numberRowCutsAfter) { const OsiRowCut * thisCut = theseCuts.rowCutPtr(numberRowCutsAfter - 1) ; if (thisCut->lb() > thisCut->ub()) { status = -1; // sub-problem is infeasible break; } } #ifdef CBC_DEBUG { int k ; for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { OsiRowCut thisCut = theseCuts.rowCut(k) ; /* check size of elements. We can allow smaller but this helps debug generators as it is unsafe to have small elements */ int n = thisCut.row().getNumElements(); const int * column = thisCut.row().getIndices(); const double * element = thisCut.row().getElements(); //assert (n); for (int i = 0; i < n; i++) { double value = element[i]; assert(fabs(value) > 1.0e-12 && fabs(value) < 1.0e20); } } } #endif if (mustResolve || (specialOptions_&1) != 0) { int returnCode = resolve(node ? node->nodeInfo() : NULL, 2); if (returnCode == 0) status = -1; if (returnCode < 0 && !status) status = 2; if ((specialOptions_&1) != 0) { debugger = solver_->getRowCutDebugger() ; if (debugger) onOptimalPath = (debugger->onOptimalPath(*solver_)) ; else onOptimalPath = false; if (onOptimalPath && !solver_->isDualObjectiveLimitReached()) assert(status >= 0) ; } if (status < 0) break ; } } numberRowCutsAfter = theseCuts.sizeRowCuts() ; numberColumnCutsAfter = theseCuts.sizeColCuts() ; if ((specialOptions_&1) != 0) { if (onOptimalPath) { int k ; for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) { OsiRowCut thisCut = theseCuts.rowCut(k) ; if (debugger->invalidCut(thisCut)) { solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); solver_->writeMpsNative("badCut.mps", NULL, NULL, 2); printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n", i, generator_[i]->cutGeneratorName(), k - numberRowCutsBefore); const double *lower = getColLower() ; const double *upper = getColUpper() ; int numberColumns = solver_->getNumCols(); if (numberColumns < 200) { for (int i = 0; i < numberColumns; i++) printf("%d bounds %g,%g\n", i, lower[i], upper[i]); } abort(); } assert(!debugger->invalidCut(thisCut)) ; } } } /* The cut generator has done its thing, and maybe it generated some cuts. Do a bit of bookkeeping: load whichGenerator[i] with the index of the generator responsible for a cut, and place cuts flagged as global in the global cut pool for the model. lastNumberCuts is the sum of cuts added in previous iterations; it's the offset to the proper starting position in whichGenerator. */ int numberBefore = numberRowCutsBefore + lastNumberCuts ; int numberAfter = numberRowCutsAfter + lastNumberCuts ; // possibly extend whichGenerator resizeWhichGenerator(numberBefore, numberAfter); int j ; /* Look for numerically unacceptable cuts. */ bool dodgyCuts = false; for (j = numberRowCutsBefore; j < numberRowCutsAfter; j++) { const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ; if (thisCut->lb() > 1.0e10 || thisCut->ub() < -1.0e10) { dodgyCuts = true; break; } whichGenerator_[numberBefore++] = i ; if (!numberNodes_||generator_[i]->globalCuts()) whichGenerator_[numberBefore-1]=i+10000; if (thisCut->lb() > thisCut->ub()) status = -1; // sub-problem is infeasible if (thisCut->globallyValid()||!numberNodes_) { // add to global list OsiRowCut newCut(*thisCut); newCut.setGloballyValid(true); newCut.mutableRow().setTestForDuplicateIndex(false); globalCuts_.addCutIfNotDuplicate(newCut) ; whichGenerator_[numberBefore-1] = i+10000 ; } } if (dodgyCuts) { for (int k = numberRowCutsAfter - 1; k >= j; k--) { const OsiRowCut * thisCut = theseCuts.rowCutPtr(k) ; if (thisCut->lb() > thisCut->ub()) status = -1; // sub-problem is infeasible if (thisCut->lb() > 1.0e10 || thisCut->ub() < -1.0e10) theseCuts.eraseRowCut(k); } numberRowCutsAfter = theseCuts.sizeRowCuts() ; for (; j < numberRowCutsAfter; j++) { const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ; whichGenerator_[numberBefore++] = i ; if (!numberNodes_||generator_[i]->globalCuts()) whichGenerator_[numberBefore-1]=i+10000; if (thisCut->globallyValid()) { // add to global list OsiRowCut newCut(*thisCut); newCut.setGloballyValid(true); newCut.mutableRow().setTestForDuplicateIndex(false); globalCuts_.addCutIfNotDuplicate(newCut) ; whichGenerator_[numberBefore-1]=i+10000; } } } for (j = numberColumnCutsBefore; j < numberColumnCutsAfter; j++) { //whichGenerator_[numberBefore++] = i ; const OsiColCut * thisCut = theseCuts.colCutPtr(j) ; if (thisCut->globallyValid()) { // fix makeGlobalCut(thisCut); } } } /* End of loop to run each cut generator. */ if (status >= 0) { // delete null cuts int nCuts = theseCuts.sizeRowCuts() ; int k ; for (k = nCuts - 1; k >= 0; k--) { const OsiRowCut * thisCut = theseCuts.rowCutPtr(k) ; int n = thisCut->row().getNumElements(); if (!n) theseCuts.eraseRowCut(k); } } // Add in any violated saved cuts if (!theseCuts.sizeRowCuts() && !theseCuts.sizeColCuts()) { int numberOld = theseCuts.sizeRowCuts() + lastNumberCuts; int numberCuts = slackCuts.sizeRowCuts() ; int i; // possibly extend whichGenerator resizeWhichGenerator(numberOld, numberOld + numberCuts); double primalTolerance; solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ; for ( i = 0; i < numberCuts; i++) { const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ; if (thisCut->violated(cbcColSolution_) > 100.0*primalTolerance) { if (messageHandler()->logLevel() > 2) printf("Old cut added - violation %g\n", thisCut->violated(cbcColSolution_)) ; whichGenerator_[numberOld++] = -3; theseCuts.insert(*thisCut) ; } } } return status; } /* Remove slack cuts. We obtain a basis and scan it. Cuts with basic slacks are purged. If any cuts are purged, resolve() is called to restore the solution held in the solver. If resolve() pivots, there's the possibility that a slack may be pivoted in (trust me :-), so the process iterates. Setting allowResolve to false will suppress reoptimisation (but see note below). At the level of the solver's constraint system, loose cuts are really deleted. There's an implicit assumption that deleteRows will also update the active basis in the solver. At the level of nodes and models, it's more complicated. New cuts exist only in the collection of cuts passed as a parameter. They are deleted from the collection and that's the end of them. Older cuts have made it into addedCuts_. Two separate actions are needed. The reference count for the CbcCountRowCut object is decremented. If this count falls to 0, the node which owns the cut is located, the reference to the cut is removed, and then the cut object is destroyed (courtesy of the CbcCountRowCut destructor). We also need to set the addedCuts_ entry to NULL. This is important so that when it comes time to generate basis edits we can tell this cut was dropped from the basis during processing of the node. NOTE: In general, it's necessary to call resolve() after purging slack cuts. Deleting constraints constitutes a change in the problem, and an OSI is not required to maintain a valid solution when the problem is changed. But ... it's really useful to maintain the active basis, and the OSI is supposed to do that. (Yes, it's splitting hairs.) In some places, it's possible to know that the solution will never be consulted after this call, only the basis. (E.g., this routine is called as a last act before generating info to place the node in the live set.) For such use, set allowResolve to false. TODO: No real harm would be done if we just ignored the rare occasion when the call to resolve() pivoted a slack back into the basis. It's a minor inefficiency, at worst. But it does break assertions which check that there are no loose cuts in the basis. It might be better to remove the assertions. */ int CbcModel::takeOffCuts (OsiCuts &newCuts, bool allowResolve, OsiCuts * saveCuts, int numberNewCuts, const OsiRowCut ** addedCuts) { // int resolveIterations = 0 ; int numberDropped = 0; int firstOldCut = numberRowsAtContinuous_ ; int totalNumberCuts = numberNewCuts_ + numberOldActiveCuts_ ; int *solverCutIndices = new int[totalNumberCuts] ; int *newCutIndices = new int[numberNewCuts_] ; const CoinWarmStartBasis* ws ; CoinWarmStartBasis::Status status ; bool needPurge = true ; /* The outer loop allows repetition of purge in the event that reoptimisation changes the basis. To start an iteration, clear the deletion counts and grab the current basis. */ while (needPurge) { int numberNewToDelete = 0 ; int numberOldToDelete = 0 ; int i ; ws = dynamic_cast(solver_->getWarmStart()) ; /* Scan the basis entries of the old cuts generated prior to this round of cut generation. Loose cuts are `removed' by decrementing their reference count and setting the addedCuts_ entry to NULL. (If the reference count falls to 0, they're really deleted. See CbcModel and CbcCountRowCut doc'n for principles of cut handling.) */ int oldCutIndex = 0 ; if (numberOldActiveCuts_) { lockThread(); for (i = 0 ; i < numberOldActiveCuts_ ; i++) { status = ws->getArtifStatus(i + firstOldCut) ; while (!addedCuts_[oldCutIndex]) oldCutIndex++ ; assert(oldCutIndex < currentNumberCuts_) ; // always leave if from nextRowCut_ if (status == CoinWarmStartBasis::basic && (addedCuts_[oldCutIndex]->effectiveness() <= 1.0e10 || addedCuts_[oldCutIndex]->canDropCut(solver_, i + firstOldCut))) { solverCutIndices[numberOldToDelete++] = i + firstOldCut ; if (saveCuts) { // send to cut pool OsiRowCut * slackCut = addedCuts_[oldCutIndex]; if (slackCut->effectiveness() != -1.234) { slackCut->setEffectiveness(-1.234); saveCuts->insert(*slackCut); } } if (addedCuts_[oldCutIndex]->decrement() == 0) delete addedCuts_[oldCutIndex] ; addedCuts_[oldCutIndex] = NULL ; oldCutIndex++ ; } else { oldCutIndex++ ; } } unlockThread(); } /* Scan the basis entries of the new cuts generated with this round of cut generation. At this point, newCuts is the only record of the new cuts, so when we delete loose cuts from newCuts, they're really gone. newCuts is a vector, so it's most efficient to compress it (eraseRowCut) from back to front. */ int firstNewCut = firstOldCut + numberOldActiveCuts_ ; int k = 0 ; int nCuts = newCuts.sizeRowCuts(); for (i = 0 ; i < nCuts ; i++) { status = ws->getArtifStatus(i + firstNewCut) ; if (status == CoinWarmStartBasis::basic && /*whichGenerator_[i]!=-2*/newCuts.rowCutPtr(i)->effectiveness() < 1.0e20) { solverCutIndices[numberNewToDelete+numberOldToDelete] = i + firstNewCut ; newCutIndices[numberNewToDelete++] = i ; } else { // save which generator did it // -2 means branch cut! assert (whichGenerator_[i]!=-2); // ?? what if it is - memory leak? whichGenerator_[k++] = whichGenerator_[i] ; } } int baseRow = firstNewCut + nCuts; //OsiRowCut ** mutableAdded = const_cast(addedCuts); int numberTotalToDelete = numberNewToDelete + numberOldToDelete; for (i = 0 ; i < numberNewCuts ; i++) { status = ws->getArtifStatus(i + baseRow) ; if (status != CoinWarmStartBasis::basic || /*whichGenerator_[i+nCuts]==-2*/addedCuts[i]->effectiveness() >= 1.0e20) { newCuts.insert(*addedCuts[i]) ; //newCuts.insert(mutableAdded[i]) ; //mutableAdded[i]=NULL; //if (status == CoinWarmStartBasis::basic&&whichGenerator_[i]!=-2) { // save which generator did it //whichGenerator_[k++] = whichGenerator_[i+nCuts] ; //} } else { solverCutIndices[numberTotalToDelete++] = i + baseRow ; } } numberNewCuts = 0; numberNewCuts_ = newCuts.sizeRowCuts(); delete ws ; for (i = numberNewToDelete - 1 ; i >= 0 ; i--) { int iCut = newCutIndices[i] ; if (saveCuts) { // send to cut pool OsiRowCut * slackCut = newCuts.rowCutPtrAndZap(iCut); if (slackCut->effectiveness() != -1.234) { slackCut->setEffectiveness(-1.234); saveCuts->insert(slackCut); } else { delete slackCut; } } else { newCuts.eraseRowCut(iCut) ; } } /* Did we delete anything? If so, delete the cuts from the constraint system held in the solver and reoptimise unless we're forbidden to do so. If the call to resolve() results in pivots, there's the possibility we again have basic slacks. Repeat the purging loop. */ if (numberTotalToDelete > 0 ) { solver_->deleteRows(numberTotalToDelete, solverCutIndices) ; numberDropped += numberTotalToDelete; numberNewCuts_ -= numberNewToDelete ; assert (numberNewCuts_ == newCuts.sizeRowCuts()); numberOldActiveCuts_ -= numberOldToDelete ; # ifdef CBC_DEBUG printf("takeOffCuts: purged %d+%d cuts\n", numberOldToDelete, numberNewToDelete ); # endif if (allowResolve) { phase_ = 3; // can do quick optimality check int easy = 2; solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ; resolve(solver_) ; setPointers(solver_); solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; if (solver_->getIterationCount() == 0) { needPurge = false ; } # ifdef CBC_DEBUG else { printf( "Repeating purging loop. %d iters.\n", solver_->getIterationCount()); } # endif } else { needPurge = false ; } } else { needPurge = false ; } } /* Clean up and return. */ delete [] solverCutIndices ; delete [] newCutIndices ; return numberDropped; } /* Return values: 1: feasible 0: infeasible -1: feasible and finished (do no more work on this subproblem) */ int CbcModel::resolve(CbcNodeInfo * parent, int whereFrom, double * saveSolution, double * saveLower, double * saveUpper) { #ifdef CBC_STATISTICS void cbc_resolve_check(const OsiSolverInterface * solver); cbc_resolve_check(solver_); #endif // We may have deliberately added in violated cuts - check to avoid message int iRow; int numberRows = solver_->getNumRows(); const double * rowLower = solver_->getRowLower(); const double * rowUpper = solver_->getRowUpper(); bool feasible = true; for (iRow = numberRowsAtContinuous_; iRow < numberRows; iRow++) { if (rowLower[iRow] > rowUpper[iRow] + 1.0e-8) feasible = false; } // Can't happen if strong branching as would have been found before if ((!numberStrong_||(moreSpecialOptions_&1073741824)!=0) && numberObjects_ > numberIntegers_) { int iColumn; int numberColumns = solver_->getNumCols(); const double * columnLower = solver_->getColLower(); const double * columnUpper = solver_->getColUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLower[iColumn] > columnUpper[iColumn] + 1.0e-5) feasible = false; } } #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); #endif /* Reoptimize. Consider the possibility that we should fathom on bounds. But be careful --- where the objective takes on integral values, we may want to keep a solution where the objective is right on the cutoff. */ if (feasible) { bool onOptimalPath = false; if ((specialOptions_&1) != 0) { const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ; if (debugger) { onOptimalPath = true; printf("On optimal path d\n") ; } } int nTightened = 0; #ifdef COIN_HAS_CLP // Pierre pointed out that this is not valid for all solvers // so just do if Clp if ((specialOptions_&1) != 0 && onOptimalPath) { solver_->writeMpsNative("before-tighten.mps", NULL, NULL, 2); } if (clpSolver && (!currentNode_ || (currentNode_->depth()&2) != 0) && !solverCharacteristics_->solutionAddsCuts() && (moreSpecialOptions_&1073741824)==0) nTightened = clpSolver->tightenBounds(); if (nTightened) { //printf("%d bounds tightened\n",nTightened); if ((specialOptions_&1) != 0 && onOptimalPath) { const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ; if (!debugger) { // tighten did something??? solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2); printf("Not on optimalpath aaaa\n"); //abort(); onOptimalPath = false; } } } #endif if (nTightened >= 0) { resolve(solver_) ; numberIterations_ += solver_->getIterationCount() ; feasible = (solver_->isProvenOptimal() && !solver_->isDualObjectiveLimitReached()) ; if (feasible) { // double check double testValue = solver_->getObjSense() * solver_->getObjValue(); //double cutoff = getCutoff(); if (bestObjective_ - getCutoffIncrement() < testValue) { #ifdef CLP_INVESTIGATE double value ; solver_->getDblParam(OsiDualObjectiveLimit, value) ; printf("Should cutoff as obj %.18g, best %.18g, inc %.18g - solver cutoff %.18g model cutoff %.18g\n", testValue, bestObjective_, getCutoffIncrement(), value, getCutoff()); #endif feasible = false; } } else if (solver_->isAbandoned()) { setMaximumSeconds(-COIN_DBL_MAX); } #ifdef COIN_HAS_CLP if (clpSolver && feasible && !numberNodes_ && false) { double direction = solver_->getObjSense() ; double tolerance; solver_->getDblParam(OsiDualTolerance, tolerance) ; double primalTolerance; solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ; const double *lower = solver_->getColLower() ; const double *upper = solver_->getColUpper() ; const double *solution = solver_->getColSolution() ; const double *reducedCost = solver_->getReducedCost() ; ClpSimplex * clpSimplex = clpSolver->getModelPtr(); double * rowLower = clpSimplex->rowLower(); double * rowUpper = clpSimplex->rowUpper(); int numberRows = clpSimplex->numberRows(); double * saveRowLower = CoinCopyOfArray(rowLower, numberRows); double * saveRowUpper = CoinCopyOfArray(rowUpper, numberRows); { const double * dual = clpSimplex->dualRowSolution(); const double * rowActivity = clpSimplex->primalRowSolution(); for (int iRow = 0 ; iRow < numberRows ; iRow++) { double djValue = direction * dual[iRow] ; double lowerValue = rowLower[iRow]; double upperValue = rowUpper[iRow]; if (rowActivity[iRow] < lowerValue + primalTolerance && djValue > tolerance) { rowUpper[iRow] = lowerValue; assert (clpSimplex->getRowStatus(iRow) != ClpSimplex::basic); } else if (rowActivity[iRow] > upperValue - primalTolerance && djValue < -tolerance) { rowLower[iRow] = upperValue; assert (clpSimplex->getRowStatus(iRow) != ClpSimplex::basic); } } } int numberColumns = solver_->getNumCols(); double * objective = clpSimplex->objective(); double * saveObj = CoinCopyOfArray(objective, numberColumns); double objValue = 0.01; bool someFree = false; for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) { double djValue = direction * reducedCost[iColumn] ; double lowerValue = lower[iColumn]; double upperValue = upper[iColumn]; if (solution[iColumn] < lowerValue + primalTolerance && djValue > tolerance) { objective[iColumn] = 1.0e8 * direction; assert (clpSimplex->getColumnStatus(iColumn) != ClpSimplex::basic); } else if (solution[iColumn] > upperValue - primalTolerance && djValue < -tolerance) { objective[iColumn] = -1.0e8 * direction; assert (clpSimplex->getColumnStatus(iColumn) != ClpSimplex::basic); } else if (lowerValue > -1.0e20 || upperValue < 1.0e20) { assert (fabs(djValue) <= tolerance); if (fabs(lowerValue) < fabs(upperValue)) objective[iColumn] = objValue * direction; else objective[iColumn] = -objValue * direction; objValue += 0.01; } else { objective[iColumn] = 0.0; someFree = true; } } if (!someFree) clpSimplex->primal(1); memcpy(objective, saveObj, numberColumns*sizeof(double)); delete [] saveObj; memcpy(rowLower, saveRowLower, numberRows*sizeof(double)); delete [] saveRowLower; memcpy(rowUpper, saveRowUpper, numberRows*sizeof(double)); delete [] saveRowUpper; if (!someFree) { clpSimplex->primal(1); //assert (clpSimplex->numberIterations()<10); } //clpSimplex->writeMps("xx"); //clpSimplex->primal(1); clpSolver->setWarmStart(NULL); } #endif if ((specialOptions_&1) != 0 && onOptimalPath) { if (!solver_->getRowCutDebugger()) { // tighten did something??? solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); solver_->writeMpsNative("infeas4.mps", NULL, NULL, 2); //assert (solver_->getRowCutDebugger()) ; printf("Not on optimalpath e\n"); //abort(); } } } else { feasible = false; } } if (0 && feasible) { const double * lb = solver_->getColLower(); const double * ub = solver_->getColUpper(); const double * x = solver_->getColSolution(); const double * dj = solver_->getReducedCost(); int numberColumns = solver_->getNumCols(); for (int i = 0; i < numberColumns; i++) { if (dj[i] > 1.0e-4 && ub[i] - lb[i] > 1.0e-4 && x[i] > lb[i] + 1.0e-4) printf("error %d %g %g %g %g\n", i, dj[i], lb[i], x[i], ub[i]); if (dj[i] < -1.0e-4 && ub[i] - lb[i] > 1.0e-4 && x[i] < ub[i] - 1.0e-4) printf("error %d %g %g %g %g\n", i, dj[i], lb[i], x[i], ub[i]); } } if (false && !feasible && continuousObjective_ < -1.0e30) { // at root node - double double check bool saveTakeHint; OsiHintStrength saveStrength; solver_->getHintParam(OsiDoDualInResolve, saveTakeHint, saveStrength); if (saveTakeHint || saveStrength == OsiHintIgnore) { solver_->setHintParam(OsiDoDualInResolve, false, OsiHintDo) ; resolve(solver_); solver_->setHintParam(OsiDoDualInResolve, saveTakeHint, saveStrength); numberIterations_ += solver_->getIterationCount() ; feasible = solver_->isProvenOptimal(); // solver_->writeMps("infeas"); } } #ifdef JJF_ZERO if (cutModifier_ && feasible && !solverCharacteristics_->solutionAddsCuts()) { //double increment = getDblParam(CbcModel::CbcCutoffIncrement) ; double cutoff ; solver_->getDblParam(OsiDualObjectiveLimit, cutoff) ; double distance = fabs(cutoff - solver_->getObjValue()); if (distance < 10.0*trueIncrement) { double offset; solver_->getDblParam(OsiObjOffset, offset); double objFixedValue = -offset; double objValue = 0.0; double direction = solver_->getObjSense(); const double * solution = solver_->getColSolution(); const double * objective = solver_->getObjCoefficients(); const double * columnLower = solver_->getColLower(); const double * columnUpper = solver_->getColUpper(); int numberColumns = solver_->getNumCols(); int increment = 0 ; double multiplier = 1.0 / trueIncrement; int bigIntegers = 0; // Count of large costs which are integer for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double value = solution[iColumn]; // make sure clean value = CoinMin(value, columnUpper[iColumn]); value = CoinMax(value, columnLower[iColumn]); double cost = direction * objective[iColumn]; if (cost) { if (columnLower[iColumn] < columnUpper[iColumn]) { objValue += value * cost; value = fabs(cost) * multiplier ; if (value < 2.1e9) { int nearest = static_cast (floor(value + 0.5)) ; assert (fabs(value - floor(value + 0.5)) < 1.0e-8); if (!increment) increment = nearest ; else increment = gcd(increment, nearest) ; } else { // large value - may still be multiple of 1.0 value = fabs(objective[iColumn]); assert(fabs(value - floor(value + 0.5)) < 1.0e-8); bigIntegers++; } } else { // fixed objFixedValue += value * cost; } } } if (increment) { double value = increment ; value /= multiplier ; if (value > trueIncrement) { double x = objValue / value; x = ceil(x - 1.0e-5); x *= value; //printf("fixed %g, variable %g -> %g, sum %g - cutoff %g\n", // objFixedValue,objValue,x,x+objFixedValue,cutoff); x += objFixedValue; if (x > cutoff + 1.0e-5*fabs(cutoff) + 1.0e-5) { //printf("Node cutoff\n"); feasible = false; } } else { value = trueIncrement; double x = objValue / value; x = ceil(x - 1.0e-5); x *= value; x += objFixedValue; if (x > cutoff + 1.0e-5*fabs(cutoff) + 1.0e-5) { //printf("Node cutoff\n"); feasible = false; } } } } } #endif setPointers(solver_); if (feasible && saveSolution) { // called from CbcNode assert (saveLower); assert (saveUpper); int numberColumns = solver_->getNumCols(); memcpy(saveSolution, solver_->getColSolution(), numberColumns*sizeof(double)); reserveCurrentSolution(saveSolution); memcpy(saveLower, solver_->getColLower(), numberColumns*sizeof(double)); memcpy(saveUpper, solver_->getColUpper(), numberColumns*sizeof(double)); } #ifdef COIN_HAS_CLP if (clpSolver && !feasible) { // make sure marked infeasible if (!clpSolver->isProvenDualInfeasible()) clpSolver->getModelPtr()->setProblemStatus(1); } #endif int returnStatus = feasible ? 1 : 0; if (strategy_) { /* Possible returns from status: -1: no recommendation 0: treat as optimal 1: treat as optimal and finished (no more resolves, cuts, etc.) 2: treat as infeasible. */ // user can play clever tricks here int status = strategy_->status(this, parent, whereFrom); if (status >= 0) { if (status == 0) returnStatus = 1; else if (status == 1) returnStatus = -1; else returnStatus = 0; } } return returnStatus ; } /* Set up objects. Only do ones whose length is in range. If makeEquality true then a new model may be returned if modifications had to be made, otherwise "this" is returned. Could use Probing at continuous to extend objects */ CbcModel * CbcModel::findCliques(bool makeEquality, int atLeastThisMany, int lessThanThis, int /*defaultValue*/) { // No objects are allowed to exist assert(numberObjects_ == numberIntegers_ || !numberObjects_); CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow()); int numberRows = solver_->getNumRows(); int numberColumns = solver_->getNumCols(); // We may want to add columns int numberSlacks = 0; int * rows = new int[numberRows]; double * element = new double[numberRows]; int iRow; findIntegers(true); numberObjects_ = numberIntegers_; int numberCliques = 0; OsiObject ** object = new OsiObject * [numberRows]; int * which = new int[numberIntegers_]; char * type = new char[numberIntegers_]; int * lookup = new int[numberColumns]; int i; for (i = 0; i < numberColumns; i++) lookup[i] = -1; for (i = 0; i < numberIntegers_; i++) lookup[integerVariable_[i]] = i; // Statistics int totalP1 = 0, totalM1 = 0; int numberBig = 0, totalBig = 0; int numberFixed = 0; // Row copy const double * elementByRow = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); // Column lengths for slacks const int * columnLength = solver_->getMatrixByCol()->getVectorLengths(); const double * lower = getColLower(); const double * upper = getColUpper(); const double * rowLower = getRowLower(); const double * rowUpper = getRowUpper(); /* Scan the rows, looking for individual rows that are clique constraints. */ for (iRow = 0; iRow < numberRows; iRow++) { int numberP1 = 0, numberM1 = 0; int j; double upperValue = rowUpper[iRow]; double lowerValue = rowLower[iRow]; bool good = true; int slack = -1; /* Does this row qualify? All variables must be binary and all coefficients +/- 1.0. Variables with positive coefficients are recorded at the low end of which, variables with negative coefficients the high end. */ for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; int iInteger = lookup[iColumn]; if (upper[iColumn] - lower[iColumn] < 1.0e-8) { // fixed upperValue -= lower[iColumn] * elementByRow[j]; lowerValue -= lower[iColumn] * elementByRow[j]; continue; } else if (upper[iColumn] != 1.0 || lower[iColumn] != 0.0) { good = false; break; } else if (iInteger < 0) { good = false; break; } else { if (columnLength[iColumn] == 1) slack = iInteger; } if (fabs(elementByRow[j]) != 1.0) { good = false; break; } else if (elementByRow[j] > 0.0) { which[numberP1++] = iInteger; } else { numberM1++; which[numberIntegers_-numberM1] = iInteger; } } int iUpper = static_cast (floor(upperValue + 1.0e-5)); int iLower = static_cast (ceil(lowerValue - 1.0e-5)); /* What do we have? If the row upper bound is greater than 1-numberM1, this isn't a clique. If the row upper bound is 1-numberM1, we have the classic clique (an SOS1 on binary variables, if numberM1 = 0). If the upper bound equals numberM1, we can fix all variables. If the upper bound is less than numberM1, we're infeasible. A similar analysis applies using numberP1 against the lower bound. */ int state = 0; if (upperValue < 1.0e6) { if (iUpper == 1 - numberM1) state = 1; else if (iUpper == -numberM1) state = 2; else if (iUpper < -numberM1) state = 3; } if (!state && lowerValue > -1.0e6) { if (-iLower == 1 - numberP1) state = -1; else if (-iLower == -numberP1) state = -2; else if (-iLower < -numberP1) state = -3; } /* What to do? If we learned nothing, move on to the next iteration. If we're infeasible, we're outta here. If we decided we can fix variables, do it. */ if (good && state) { if (abs(state) == 3) { // infeasible numberObjects_ = -1; break; } else if (abs(state) == 2) { // we can fix all numberFixed += numberP1 + numberM1; if (state > 0) { // fix all +1 at 0, -1 at 1 for (i = 0; i < numberP1; i++) solver_->setColUpper(integerVariable_[which[i]], 0.0); for (i = 0; i < numberM1; i++) solver_->setColLower(integerVariable_[which[numberIntegers_-i-1]], 1.0); } else { // fix all +1 at 1, -1 at 0 for (i = 0; i < numberP1; i++) solver_->setColLower(integerVariable_[which[i]], 1.0); for (i = 0; i < numberM1; i++) solver_->setColUpper(integerVariable_[which[numberIntegers_-i-1]], 0.0); } } else { /* And the final case: we have a clique constraint. If it's within the allowed size range, make a clique object. */ int length = numberP1 + numberM1; if (length >= atLeastThisMany && length < lessThanThis) { // create object bool addOne = false; int objectType; /* Choose equality (type 1) or inequality (type 0). If we're forcing equalities, add a slack. */ if (iLower == iUpper) { objectType = 1; } else { if (makeEquality) { objectType = 1; element[numberSlacks] = state; rows[numberSlacks++] = iRow; addOne = true; } else { objectType = 0; } } /* Record the strong values for the variables. Variables with positive coefficients force all others when set to 1; variables with negative coefficients force when set to 0. If the clique is formed against the row lower bound, convert to the canonical form of a clique against the row upper bound. */ if (state > 0) { totalP1 += numberP1; totalM1 += numberM1; for (i = 0; i < numberP1; i++) type[i] = 1; for (i = 0; i < numberM1; i++) { which[numberP1] = which[numberIntegers_-i-1]; type[numberP1++] = 0; } } else { totalP1 += numberM1; totalM1 += numberP1; for (i = 0; i < numberP1; i++) type[i] = 0; for (i = 0; i < numberM1; i++) { which[numberP1] = which[numberIntegers_-i-1]; type[numberP1++] = 1; } } if (addOne) { // add in slack which[numberP1] = numberIntegers_ + numberSlacks - 1; slack = numberP1; type[numberP1++] = 1; } else if (slack >= 0) { for (i = 0; i < numberP1; i++) { if (which[i] == slack) { slack = i; } } } object[numberCliques] = new CbcClique(this, objectType, numberP1, which, type, 1000000 + numberCliques, slack); numberCliques++; } else if (numberP1 + numberM1 >= lessThanThis) { // too big numberBig++; totalBig += numberP1 + numberM1; } } } } delete [] which; delete [] type; delete [] lookup; #if COIN_DEVELOP>1 if (numberCliques < 0) { printf("*** Problem infeasible\n"); } else { if (numberCliques) printf("%d cliques of average size %g found, %d P1, %d M1\n", numberCliques, (static_cast(totalP1 + totalM1)) / (static_cast numberCliques), totalP1, totalM1); else printf("No cliques found\n"); if (numberBig) printf("%d large cliques ( >= %d) found, total %d\n", numberBig, lessThanThis, totalBig); if (numberFixed) printf("%d variables fixed\n", numberFixed); } #endif /* If required, augment the constraint matrix with clique slacks. Seems like we should be able to add the necessary integer objects without a complete rebuild of existing integer objects, but I'd need to look further to confirm that (lh, 071219). Finally, add the clique objects. */ if (numberCliques > 0 && numberSlacks && makeEquality) { COIN_DETAIL_PRINT(printf("adding %d integer slacks\n", numberSlacks)); // add variables to make equality rows int * temp = new int[numberIntegers_+numberSlacks]; memcpy(temp, integerVariable_, numberIntegers_*sizeof(int)); // Get new model CbcModel * newModel = new CbcModel(*this); OsiSolverInterface * newSolver = newModel->solver(); for (i = 0; i < numberSlacks; i++) { temp[i+numberIntegers_] = i + numberColumns; int iRow = rows[i]; double value = element[i]; double lowerValue = 0.0; double upperValue = 1.0; double objValue = 0.0; CoinPackedVector column(1, &iRow, &value); newSolver->addCol(column, lowerValue, upperValue, objValue); // set integer newSolver->setInteger(numberColumns + i); if (value > 0) newSolver->setRowLower(iRow, rowUpper[iRow]); else newSolver->setRowUpper(iRow, rowLower[iRow]); } // replace list of integers for (i = 0; i < newModel->numberObjects_; i++) delete newModel->object_[i]; newModel->numberObjects_ = 0; delete [] newModel->object_; newModel->object_ = NULL; newModel->findIntegers(true); //Set up all integer objects for (i = 0; i < numberIntegers_; i++) { newModel->modifiableObject(i)->setPriority(object_[i]->priority()); } if (originalColumns_) { // old model had originalColumns delete [] newModel->originalColumns_; newModel->originalColumns_ = new int[numberColumns+numberSlacks]; memcpy(newModel->originalColumns_, originalColumns_, numberColumns*sizeof(int)); // mark as not in previous model for (i = numberColumns; i < numberColumns + numberSlacks; i++) newModel->originalColumns_[i] = -1; } delete [] rows; delete [] element; newModel->addObjects(numberCliques, object); assert (ownObjects_); for (; i < numberCliques; i++) delete object[i]; delete [] object; newModel->synchronizeModel(); return newModel; } else { assert (ownObjects_); if (numberCliques > 0) { addObjects(numberCliques, object); for (; i < numberCliques; i++) delete object[i]; synchronizeModel(); } delete [] object; delete [] rows; delete [] element; return this; } } // Fill in useful estimates void CbcModel::pseudoShadow(int iActive) { assert (iActive<2*8*32 && iActive> -3); if (iActive == -1) { if (numberNodes_) { // zero out for (int i = 0; i < numberObjects_; i++) { CbcSimpleIntegerDynamicPseudoCost * obj1 = dynamic_cast (object_[i]) ; if (obj1) { //assert (obj1->downShadowPrice()>0.0); #define P_FACTOR 1.0 #ifndef JJF_ONE obj1->setDownShadowPrice(-P_FACTOR*obj1->downShadowPrice()); obj1->setUpShadowPrice(-P_FACTOR*obj1->upShadowPrice()); #else double pCost; double sCost; pCost = obj1->downDynamicPseudoCost(); sCost = P_FACTOR * obj1->downShadowPrice(); if (!obj1->numberTimesDown() || sCost > pCost) obj1->updateDownDynamicPseudoCost(sCost); obj1->setDownShadowPrice(0.0); pCost = obj1->upDynamicPseudoCost(); sCost = P_FACTOR * obj1->upShadowPrice(); if (!obj1->numberTimesUp() || sCost > pCost) obj1->updateUpDynamicPseudoCost(sCost); obj1->setUpShadowPrice(0.0); #endif } } } return; } bool doShadow = false; if (!iActive || iActive >= 32) { doShadow = true; if (iActive >= 32) iActive -= 32; } double * rowWeight = NULL; double * columnWeight = NULL; int numberColumns = solver_->getNumCols() ; int numberRows = solver_->getNumRows() ; // Column copy of matrix const double * element = solver_->getMatrixByCol()->getElements(); const int * row = solver_->getMatrixByCol()->getIndices(); const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts(); const int * columnLength = solver_->getMatrixByCol()->getVectorLengths(); const double * dual = solver_->getRowPrice(); const double * solution = solver_->getColSolution(); const double * dj = solver_->getReducedCost(); bool useMax = false; bool useAlpha = false; if (iActive) { // Use Patel and Chinneck ideas rowWeight = new double [numberRows]; columnWeight = new double [numberColumns]; // add in active constraints double tolerance = 1.0e-5; const double *rowLower = getRowLower() ; const double *rowUpper = getRowUpper() ; const double *rowActivity = solver_->getRowActivity(); const double * lower = getColLower(); const double * upper = getColUpper(); CoinZeroN(rowWeight, numberRows); /* 1 A weight 1 2 B weight 1/sum alpha 3 L weight 1/number integer 4 M weight 1/number active integer 7 O weight 1/number integer and use alpha 8 P weight 1/number active integer and use alpha 9 up subtract 8 and use maximum */ if (iActive > 8) { iActive -= 8; useMax = true; } if (iActive > 4) { iActive -= 4; useAlpha = true; } switch (iActive) { // A case 1: for (int iRow = 0; iRow < numberRows; iRow++) { if (rowActivity[iRow] > rowUpper[iRow] - tolerance || rowActivity[iRow] < rowLower[iRow] + tolerance) { rowWeight[iRow] = 1.0; } } break; // B case 2: for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; rowWeight[iRow] += fabs(element[j]); } } } for (int iRow = 0; iRow < numberRows; iRow++) { if (rowWeight[iRow]) rowWeight[iRow] = 1.0 / rowWeight[iRow]; } break; // L case 3: for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) { int iColumn = integerVariable_[jColumn]; if (upper[iColumn] > lower[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; rowWeight[iRow]++; } } } for (int iRow = 0; iRow < numberRows; iRow++) { if (rowWeight[iRow]) rowWeight[iRow] = 1.0 / rowWeight[iRow]; } break; // M case 4: for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) { int iColumn = integerVariable_[jColumn]; double value = solution[iColumn]; if (fabs(value - floor(value + 0.5)) > 1.0e-5) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; rowWeight[iRow]++; } } } for (int iRow = 0; iRow < numberRows; iRow++) { if (rowWeight[iRow]) rowWeight[iRow] = 1.0 / rowWeight[iRow]; } break; } if (doShadow) { for (int iRow = 0; iRow < numberRows; iRow++) { rowWeight[iRow] *= dual[iRow]; } } dual = rowWeight; } const double *objective = solver_->getObjCoefficients() ; double direction = solver_->getObjSense(); double * down = new double[numberColumns]; double * up = new double[numberColumns]; double upSum = 1.0e-20; double downSum = 1.0e-20; int numberIntegers = 0; if (doShadow) { // shadow prices if (!useMax) { for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) { int iColumn = integerVariable_[jColumn]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; double upValue = 0.0; double downValue = 0.0; double value = direction * objective[iColumn]; if (value) { if (value > 0.0) upValue += value; else downValue -= value; } for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; value = -dual[iRow]; assert (fabs(dual[iRow]) < 1.0e50); if (value) { value *= element[j]; if (value > 0.0) upValue += value; else downValue -= value; } } up[iColumn] = upValue; down[iColumn] = downValue; if (solver_->isInteger(iColumn)) { if (!numberNodes_ && handler_->logLevel() > 1) printf("%d - up %g down %g cost %g\n", iColumn, upValue, downValue, objective[iColumn]); upSum += upValue; downSum += downValue; numberIntegers++; } } } else { for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) { int iColumn = integerVariable_[jColumn]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; double upValue = 0.0; double downValue = 0.0; double value = direction * objective[iColumn]; if (value) { if (value > 0.0) upValue += value; else downValue -= value; } for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; value = -dual[iRow]; if (value) { value *= element[j]; if (value > 0.0) upValue = CoinMax(upValue, value); else downValue = CoinMax(downValue, -value); } } up[iColumn] = upValue; down[iColumn] = downValue; if (solver_->isInteger(iColumn)) { if (!numberNodes_ && handler_->logLevel() > 1) printf("%d - up %g down %g cost %g\n", iColumn, upValue, downValue, objective[iColumn]); upSum += upValue; downSum += downValue; numberIntegers++; } } } } else { for (int jColumn = 0; jColumn < numberIntegers_; jColumn++) { int iColumn = integerVariable_[jColumn]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; double upValue = 0.0; double downValue = 0.0; double value = direction * objective[iColumn]; if (value) { if (value > 0.0) upValue += value; else downValue -= value; } double weight = 0.0; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; value = -dual[iRow]; double thisWeight = rowWeight[iRow]; if (useAlpha) thisWeight *= fabs(element[j]); if (!useMax) weight += thisWeight; else weight = CoinMax(weight, thisWeight); if (value) { value *= element[j]; if (value > 0.0) upValue += value; else downValue -= value; } } columnWeight[iColumn] = weight; // use dj if bigger double djValue = dj[iColumn]; upValue = CoinMax(upValue, djValue); downValue = CoinMax(downValue, -djValue); up[iColumn] = upValue; down[iColumn] = downValue; if (solver_->isInteger(iColumn)) { if (!numberNodes_ && handler_->logLevel() > 1) printf("%d - dj %g up %g down %g cost %g\n", iColumn, djValue, upValue, downValue, objective[iColumn]); upSum += upValue; downSum += downValue; numberIntegers++; } } if (numberIntegers) { double averagePrice = (0.5 * (upSum + downSum)) / static_cast(numberIntegers); //averagePrice *= 0.1; averagePrice *= 100.0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double weight = columnWeight[iColumn]; up[iColumn] += averagePrice * weight; down[iColumn] += averagePrice * weight; } } } delete [] rowWeight; delete [] columnWeight; if (numberIntegers) { double smallDown = 0.0001 * (downSum / static_cast (numberIntegers)); double smallUp = 0.0001 * (upSum / static_cast (numberIntegers)); #define PSEUDO_FACTOR 5.0e-1 double pseudoFactor = PSEUDO_FACTOR; //if (!numberNodes_) //pseudoFactor=0.0; for (int i = 0; i < numberObjects_; i++) { CbcSimpleIntegerDynamicPseudoCost * obj1 = dynamic_cast (object_[i]) ; if (obj1 && obj1->upShadowPrice() >= 0.0) { int iColumn = obj1->columnNumber(); double upPseudoCost = obj1->upDynamicPseudoCost(); double saveUp = upPseudoCost; upPseudoCost = CoinMax(pseudoFactor * upPseudoCost, smallUp); upPseudoCost = CoinMax(upPseudoCost, up[iColumn]); upPseudoCost = CoinMax(upPseudoCost, 0.001 * down[iColumn]); obj1->setUpShadowPrice(upPseudoCost); if (upPseudoCost > saveUp && !numberNodes_ && handler_->logLevel() > 1) printf("For %d up went from %g to %g\n", iColumn, saveUp, upPseudoCost); double downPseudoCost = obj1->downDynamicPseudoCost(); double saveDown = downPseudoCost; downPseudoCost = CoinMax(pseudoFactor * downPseudoCost, smallDown); downPseudoCost = CoinMax(downPseudoCost, down[iColumn]); downPseudoCost = CoinMax(downPseudoCost, 0.001 * up[iColumn]); obj1->setDownShadowPrice(downPseudoCost); if (downPseudoCost > saveDown && !numberNodes_ && handler_->logLevel() > 1) printf("For %d down went from %g to %g\n", iColumn, saveDown, downPseudoCost); } } } delete [] down; delete [] up; } /* Set branching priorities. Setting integer priorities looks pretty robust; the call to findIntegers makes sure that SimpleInteger objects are in place. Setting priorities for other objects is entirely dependent on their existence, and the routine may quietly fail in several directions. */ void CbcModel::passInPriorities (const int * priorities, bool ifObject) { findIntegers(false); int i; if (priorities) { int i0 = 0; int i1 = numberObjects_ - 1; if (ifObject) { for (i = numberIntegers_; i < numberObjects_; i++) { object_[i]->setPriority(priorities[i-numberIntegers_]); } i0 = numberIntegers_; } else { for (i = 0; i < numberIntegers_; i++) { object_[i]->setPriority(priorities[i]); } i1 = numberIntegers_ - 1; } messageHandler()->message(CBC_PRIORITY, messages()) << i0 << i1 << numberObjects_ << CoinMessageEol ; } } // Delete all object information void CbcModel::deleteObjects(bool getIntegers) { if (ownObjects_) { int i; for (i = 0; i < numberObjects_; i++) delete object_[i]; delete [] object_; } object_ = NULL; numberObjects_ = 0; if (getIntegers && ownObjects_) findIntegers(true); } /*! Ensure all attached objects (OsiObjects, heuristics, and cut generators) point to this model. */ void CbcModel::synchronizeModel() { if (!numberObjects_) return; int i; for (i = 0; i < numberHeuristics_; i++) heuristic_[i]->setModel(this); for (i = 0; i < numberObjects_; i++) { CbcObject * obj = dynamic_cast (object_[i]) ; if (obj) { obj->setModel(this); obj->setPosition(i); } } for (i = 0; i < numberCutGenerators_; i++) generator_[i]->refreshModel(this); if (!solverCharacteristics_) { OsiBabSolver * solverCharacteristics = dynamic_cast (solver_->getAuxiliaryInfo()); if (solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } else { // replace in solver OsiBabSolver defaultC; solver_->setAuxiliaryInfo(&defaultC); solverCharacteristics_ = dynamic_cast (solver_->getAuxiliaryInfo()); } } solverCharacteristics_->setSolver(solver_); } // Fill in integers and create objects /** The routine first does a scan to count the number of integer variables. It then creates an array, integerVariable_, to store the indices of the integer variables, and an array of `objects', one for each variable. The scan is repeated, this time recording the index of each integer variable in integerVariable_, and creating an CbcSimpleInteger object that contains information about the integer variable. Initially, this is just the index and upper & lower bounds. \todo Note the assumption in cbc that the first numberIntegers_ objects are CbcSimpleInteger. In particular, the code which handles the startAgain case assumes that if the object_ array exists it can simply replace the first numberInteger_ objects. This is arguably unsafe. I am going to re-order if necessary */ void CbcModel::findIntegers(bool startAgain, int type) { assert(solver_); /* No need to do this if we have previous information, unless forced to start over. */ if (numberIntegers_ && !startAgain && object_) return; /* Clear out the old integer variable list, then count the number of integer variables. */ delete [] integerVariable_; integerVariable_ = NULL; numberIntegers_ = 0; int numberColumns = getNumCols(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (isInteger(iColumn)) numberIntegers_++; } // Find out how many old non-integer objects there are int nObjects = 0; OsiObject ** oldObject = object_; int iObject; // also see where old ones were char * mark = new char[numberColumns]; CoinZeroN(mark, numberColumns); int iPriority = -100000; for (iObject = 0; iObject < numberObjects_; iObject++) { iPriority = CoinMax(iPriority, object_[iObject]->priority()); CbcSimpleInteger * obj = dynamic_cast (oldObject[iObject]) ; if (obj) { int iColumn = obj->columnNumber(); if (iColumn >= 0 && iColumn < numberColumns) mark[iColumn] = 1; delete oldObject[iObject]; } else { oldObject[nObjects++] = oldObject[iObject]; } } // See if there any SOS #ifdef COIN_HAS_CLP if (!nObjects) { OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver && (clpSolver->numberSOS() || clpSolver->numberObjects())) { // deal with sos const CoinSet * setInfo = clpSolver->setInfo(); int numberSOS = clpSolver->numberSOS(); if (numberSOS) { nObjects = 0; delete [] oldObject; oldObject = new OsiObject * [numberSOS]; for (int i = 0; i < numberSOS; i++) { int type = setInfo[i].setType(); int n = setInfo[i].numberEntries(); const int * which = setInfo[i].which(); const double * weights = setInfo[i].weights(); oldObject[nObjects++] = new CbcSOS(this, n, which, weights, i, type); } } else { // objects - only works with SOS at present int numberObjects = clpSolver->numberObjects(); nObjects = 0; delete [] oldObject; oldObject = new OsiObject * [numberObjects]; OsiObject ** osiObjects = clpSolver->objects(); for (int i = 0; i < numberObjects; i++) { OsiSOS * obj = dynamic_cast (osiObjects[i]) ; if (obj) { int type = obj->setType(); int n = obj->numberMembers(); const int * which = obj->members(); const double * weights = obj->weights(); oldObject[nObjects++] = new CbcSOS(this, n, which, weights, i, type); } } } } } #endif /* Found any? Allocate an array to hold the indices of the integer variables. Make a large enough array for all objects */ delete [] integerVariable_; object_ = new OsiObject * [numberIntegers_+nObjects]; numberObjects_ = numberIntegers_ + nObjects; integerVariable_ = new int [numberIntegers_]; /* Walk the variables again, filling in the indices and creating objects for the integer variables. Initially, the objects hold the index and upper & lower bounds. */ numberIntegers_ = 0; if (type == 2) continuousPriority_ = iPriority + 1; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (isInteger(iColumn)) { if (!type) { object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn); } else if (type == 1) { object_[numberIntegers_] = new CbcSimpleIntegerPseudoCost(this, iColumn, 0.3); } else if (type == 2) { object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn); if (mark[iColumn]) { // could up priority on costs if all costs same?? } else { object_[numberIntegers_]->setPriority(iPriority + 1); } } integerVariable_[numberIntegers_++] = iColumn; } } delete [] mark; // Now append other objects memcpy(object_ + numberIntegers_, oldObject, nObjects*sizeof(OsiObject *)); // Delete old array (just array) delete [] oldObject; if (!numberObjects_) handler_->message(CBC_NOINT, messages_) << CoinMessageEol ; } /* If numberBeforeTrust >0 then we are going to use CbcBranchDynamic. Scan and convert CbcSimpleInteger objects */ void CbcModel::convertToDynamic() { int iObject; const double * cost = solver_->getObjCoefficients(); bool allDynamic = true; for (iObject = 0; iObject < numberObjects_; iObject++) { CbcSimpleInteger * obj1 = dynamic_cast (object_[iObject]) ; CbcSimpleIntegerPseudoCost * obj1a = dynamic_cast (object_[iObject]) ; CbcSimpleIntegerDynamicPseudoCost * obj2 = dynamic_cast (object_[iObject]) ; if (obj1 && !obj2) { // replace int iColumn = obj1->columnNumber(); int priority = obj1->priority(); int preferredWay = obj1->preferredWay(); double costValue = CoinMax(1.0e-5, fabs(cost[iColumn])); // treat as if will cost what it says up double upCost = costValue; // and balance at breakeven of 0.3 double downCost = (0.7 * upCost) / 0.3; if (obj1a) { upCost = obj1a->upPseudoCost(); downCost = obj1a->downPseudoCost(); } delete object_[iObject]; CbcSimpleIntegerDynamicPseudoCost * newObject = new CbcSimpleIntegerDynamicPseudoCost(this, iColumn, 1.0e0*downCost, 1.0e0*upCost); //newObject->setNumberBeforeTrust(numberBeforeTrust_); newObject->setPriority(priority); newObject->setPosition(iObject); newObject->setPreferredWay(preferredWay); object_[iObject] = newObject; } else if (!obj2) { CbcObject * obj3 = dynamic_cast (object_[iObject]) ; if (!obj3 || !obj3->optionalObject()) allDynamic = false; } else { // synchronize trust //obj2->setNumberBeforeTrust(numberBeforeTrust_); } } if (branchingMethod_) { if ((branchingMethod_->whichMethod()&1) == 0 && !branchingMethod_->chooseMethod()) { // Need a method which can do better delete branchingMethod_; branchingMethod_ = NULL; } } if (allDynamic) ownership_ |= 0x40000000; if (!branchingMethod_ && allDynamic) { // create one branchingMethod_ = new CbcBranchDynamicDecision(); } synchronizeNumberBeforeTrust(); } // Set numberBeforeTrust in all objects void CbcModel::synchronizeNumberBeforeTrust(int type) { int iObject; for (iObject = 0; iObject < numberObjects_; iObject++) { CbcSimpleIntegerDynamicPseudoCost * obj2 = dynamic_cast (object_[iObject]) ; if (obj2) { // synchronize trust if (!type) { obj2->setNumberBeforeTrust(numberBeforeTrust_); } else if (type == 1) { int value = obj2->numberBeforeTrust(); value = (value * 11) / 10 + 1; value = CoinMax(numberBeforeTrust_, value); obj2->setNumberBeforeTrust(value); } else { assert (type == 2); int value = obj2->numberBeforeTrust(); int n = CoinMax(obj2->numberTimesDown(), obj2->numberTimesUp()); if (n >= value) { value = CoinMin(CoinMin(n+1,3*(value+1)/2),5*numberBeforeTrust_); obj2->setNumberBeforeTrust(value); } } } } } /* Add in any object information (objects are cloned - owner can delete originals */ void CbcModel::addObjects(int numberObjects, CbcObject ** objects) { // If integers but not enough objects fudge if (numberIntegers_ > numberObjects_ || !numberObjects_) findIntegers(true); /* But if incoming objects inherit from simple integer we just want to replace */ int numberColumns = solver_->getNumCols(); /** mark is -1 if not integer, >=0 if using existing simple integer and >=numberColumns if using new integer */ int * mark = new int[numberColumns]; int i; for (i = 0; i < numberColumns; i++) mark[i] = -1; int newNumberObjects = numberObjects; int newIntegers = 0; for (i = 0; i < numberObjects; i++) { CbcSimpleInteger * obj = dynamic_cast (objects[i]) ; if (obj) { int iColumn = obj->columnNumber(); assert (iColumn >= 0); mark[iColumn] = i + numberColumns; newIntegers++; } } // and existing for (i = 0; i < numberObjects_; i++) { CbcSimpleInteger * obj = dynamic_cast (object_[i]) ; if (obj) { int iColumn = obj->columnNumber(); if (mark[iColumn] < 0) { newIntegers++; newNumberObjects++; mark[iColumn] = i; } } else { // some other object - keep newNumberObjects++; } } delete [] integerVariable_; integerVariable_ = NULL; #if COIN_DEVELOP>1 if (newIntegers != numberIntegers_) printf("changing number of integers from %d to %d\n", numberIntegers_, newIntegers); #endif numberIntegers_ = newIntegers; integerVariable_ = new int [numberIntegers_]; OsiObject ** temp = new OsiObject * [newNumberObjects]; // Put integers first newIntegers = 0; numberIntegers_ = 0; for (i = 0; i < numberColumns; i++) { int which = mark[i]; if (which >= 0) { if (!isInteger(i)) { newIntegers++; solver_->setInteger(i); } if (which < numberColumns) { temp[numberIntegers_] = object_[which]; object_[which] = NULL; } else { temp[numberIntegers_] = objects[which-numberColumns]->clone(); } integerVariable_[numberIntegers_++] = i; } } #if COIN_DEVELOP>1 if (newIntegers) printf("%d variables were declared integer\n", newIntegers); #endif int n = numberIntegers_; // Now rest of old for (i = 0; i < numberObjects_; i++) { if (object_[i]) { CbcSimpleInteger * obj = dynamic_cast (object_[i]) ; if (obj) { delete object_[i]; } else { temp[n++] = object_[i]; } } } // and rest of new for (i = 0; i < numberObjects; i++) { CbcSimpleInteger * obj = dynamic_cast (objects[i]) ; if (!obj) { temp[n] = objects[i]->clone(); CbcObject * obj = dynamic_cast (temp[n]) ; if (obj) obj->setModel(this); n++; } } delete [] mark; assert (ownObjects_); delete [] object_; object_ = temp; assert (n == newNumberObjects); numberObjects_ = newNumberObjects; } /* Add in any object information (objects are cloned - owner can delete originals */ void CbcModel::addObjects(int numberObjects, OsiObject ** objects) { // If integers but not enough objects fudge if (numberIntegers_ > numberObjects_) findIntegers(true); /* But if incoming objects inherit from simple integer we just want to replace */ int numberColumns = solver_->getNumCols(); /** mark is -1 if not integer, >=0 if using existing simple integer and >=numberColumns if using new integer */ int * mark = new int[numberColumns]; int i; for (i = 0; i < numberColumns; i++) mark[i] = -1; int newNumberObjects = numberObjects; int newIntegers = 0; for (i = 0; i < numberObjects; i++) { CbcSimpleInteger * obj = dynamic_cast (objects[i]) ; if (obj) { int iColumn = obj->columnNumber(); mark[iColumn] = i + numberColumns; newIntegers++; } else { OsiSimpleInteger * obj2 = dynamic_cast (objects[i]) ; if (obj2) { // Osi takes precedence int iColumn = obj2->columnNumber(); mark[iColumn] = i + numberColumns; newIntegers++; } } } // and existing for (i = 0; i < numberObjects_; i++) { CbcSimpleInteger * obj = dynamic_cast (object_[i]) ; if (obj) { int iColumn = obj->columnNumber(); if (mark[iColumn] < 0) { newIntegers++; newNumberObjects++; mark[iColumn] = i; } } } delete [] integerVariable_; integerVariable_ = NULL; #if COIN_DEVELOP>1 if (newIntegers != numberIntegers_) printf("changing number of integers from %d to %d\n", numberIntegers_, newIntegers); #endif numberIntegers_ = newIntegers; integerVariable_ = new int [numberIntegers_]; OsiObject ** temp = new OsiObject * [newNumberObjects]; // Put integers first newIntegers = 0; numberIntegers_ = 0; for (i = 0; i < numberColumns; i++) { int which = mark[i]; if (which >= 0) { if (!isInteger(i)) { newIntegers++; solver_->setInteger(i); } if (which < numberColumns) { temp[numberIntegers_] = object_[which]; object_[which] = NULL; } else { temp[numberIntegers_] = objects[which-numberColumns]->clone(); } integerVariable_[numberIntegers_++] = i; } } #if COIN_DEVELOP>1 if (newIntegers) printf("%d variables were declared integer\n", newIntegers); #endif int n = numberIntegers_; // Now rest of old for (i = 0; i < numberObjects_; i++) { if (object_[i]) { CbcSimpleInteger * obj = dynamic_cast (object_[i]) ; if (obj) { delete object_[i]; } else { temp[n++] = object_[i]; } } } // and rest of new for (i = 0; i < numberObjects; i++) { CbcSimpleInteger * obj = dynamic_cast (objects[i]) ; OsiSimpleInteger * obj2 = dynamic_cast (objects[i]) ; if (!obj && !obj2) { temp[n] = objects[i]->clone(); CbcObject * obj = dynamic_cast (temp[n]) ; if (obj) obj->setModel(this); n++; } } delete [] mark; assert (ownObjects_); delete [] object_; object_ = temp; assert (n == newNumberObjects); numberObjects_ = newNumberObjects; } /** This routine sets the objective cutoff value used for fathoming and determining monotonic variables. If the fathoming discipline is strict, a small tolerance is added to the new cutoff. This avoids problems due to roundoff when the target value is exact. The common example would be an IP with only integer variables in the objective. If the target is set to the exact value z of the optimum, it's possible to end up fathoming an ancestor of the solution because the solver returns z+epsilon. Determining if strict fathoming is needed is best done by analysis. In cbc, that's analyseObjective. The default is false. In cbc we always minimize so add epsilon */ void CbcModel::setCutoff (double value) { #ifdef JJF_ZERO double tol = 0 ; int fathomStrict = getIntParam(CbcFathomDiscipline) ; if (fathomStrict == 1) { solver_->getDblParam(OsiDualTolerance, tol) ; tol = tol * (1 + fabs(value)) ; value += tol ; } #endif dblParam_[CbcCurrentCutoff] = value; if (solver_) { // Solvers know about direction double direction = solver_->getObjSense(); solver_->setDblParam(OsiDualObjectiveLimit, value*direction); } } /* Call this to really test if a valid solution can be feasible. The cutoff is passed in as a parameter so that we don't need to worry here after swapping solvers. The solution is assumed to be numberColumns in size. If fixVariables is true then the bounds of the continuous solver are updated. The routine returns the objective value determined by reoptimizing from scratch. If the solution is rejected, this will be worse than the cutoff. TODO: There's an issue with getting the correct cutoff value: We update the cutoff in the regular solver, but not in continuousSolver_. But our only use for continuousSolver_ is verifying candidate solutions. Would it make sense to update the cutoff? Then we wouldn't need to step around isDualObjectiveLimitReached(). */ double CbcModel::checkSolution (double cutoff, double *solution, int fixVariables, double objectiveValue) { if (!solverCharacteristics_->solutionAddsCuts()) { // Can trust solution int numberColumns = solver_->getNumCols(); /* Grab the continuous solver (the pristine copy of the problem, made before starting to work on the root node). Save the bounds on the variables. Install the solution passed as a parameter, and copy it to the model's currentSolution_. TODO: This is a belt-and-suspenders approach. Once the code has settled a bit, we can cast a critical eye here. */ OsiSolverInterface * saveSolver = solver_; if (continuousSolver_) solver_ = continuousSolver_; // save basis and solution CoinWarmStartBasis * basis = dynamic_cast(solver_->getWarmStart()) ; assert(basis != NULL); double * saveSolution = CoinCopyOfArray(solver_->getColSolution(), solver_->getNumCols()); // move solution to continuous copy solver_->setColSolution(solution); // Put current solution in safe place // Point to current solution const double * save = testSolution_; // Safe as will be const inside infeasibility() testSolution_ = solver_->getColSolution(); //memcpy(currentSolution_,solver_->getColSolution(), // numberColumns*sizeof(double)); //solver_->messageHandler()->setLogLevel(4); // save original bounds double * saveUpper = new double[numberColumns]; double * saveLower = new double[numberColumns]; memcpy(saveUpper, getColUpper(), numberColumns*sizeof(double)); memcpy(saveLower, getColLower(), numberColumns*sizeof(double)); // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); /* Run through the objects and use feasibleRegion() to set variable bounds so as to fix the variables specified in the objects at their value in this solution. Since the object list contains (at least) one object for every integer variable, this has the effect of fixing all integer variables. */ int i; for (i = 0; i < numberObjects_; i++) object_[i]->feasibleRegion(solver_, &usefulInfo); // If relaxed then leave bounds on basic variables if (fixVariables == -1 && (specialOptions_&16) == 0) { CoinWarmStartBasis * basis = dynamic_cast(saveSolver->getWarmStart()) ; assert(basis != NULL); #ifdef JJF_ZERO //ndef CBC_OTHER_SOLVER for (i = 0; i < numberObjects_; i++) { CbcSimpleInteger * obj = dynamic_cast (object_[i]) ; if (obj) { int iColumn = obj->columnNumber(); if (basis->getStructStatus(iColumn) == CoinWarmStartBasis::basic) { solver_->setColLower(iColumn, saveLower[iColumn]); solver_->setColUpper(iColumn, saveUpper[iColumn]); } } } #endif delete basis; } // We can switch off check if ((specialOptions_&4) == 0) { if ((specialOptions_&2) == 0 && solverCharacteristics_->warmStart()) { /* Remove any existing warm start information to be sure there is no residual influence on initialSolve(). */ CoinWarmStartBasis *slack = dynamic_cast(solver_->getEmptyWarmStart()) ; solver_->setWarmStart(slack); delete slack ; } else { if (bestSolutionBasis_.getNumStructural() == solver_->getNumCols() && bestSolutionBasis_.getNumArtificial() == solver_->getNumRows()) solver_->setWarmStart(&bestSolutionBasis_); } // Give a hint to do dual bool saveTakeHint; OsiHintStrength saveStrength; #ifndef NDEBUG bool gotHint = (solver_->getHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength)); assert (gotHint); #else (solver_->getHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength)); #endif solver_->setHintParam(OsiDoDualInInitial, true, OsiHintTry); solver_->initialSolve(); #ifdef JJF_ZERO if (solver_->isProvenOptimal()) { solver_->writeMps("feasible"); printf("XXXXXXXXXXXX - saving feasible\n"); } #endif if (!solver_->isProvenOptimal()) { #if COIN_DEVELOP>1 printf("checkSolution infeas! Retrying with primal.\n"); #endif //bool saveTakeHint; //OsiHintStrength saveStrength; //bool savePrintHint; //solver_->writeMps("infeas"); //bool gotHint = (solver_->getHintParam(OsiDoReducePrint,savePrintHint,saveStrength)); //gotHint = (solver_->getHintParam(OsiDoScale,saveTakeHint,saveStrength)); //solver_->setHintParam(OsiDoScale,false,OsiHintTry); //solver_->setHintParam(OsiDoReducePrint,false,OsiHintTry) ; solver_->setHintParam(OsiDoDualInInitial, false, OsiHintTry); solver_->initialSolve(); //solver_->setHintParam(OsiDoScale,saveTakeHint,saveStrength); //solver_->setHintParam(OsiDoReducePrint,savePrintHint,OsiHintTry) ; // go from all slack now specialOptions_ &= ~2; if (!solver_->isProvenOptimal()) { CoinWarmStartBasis *slack = dynamic_cast(solver_->getEmptyWarmStart()) ; solver_->setWarmStart(slack); delete slack ; #if COIN_DEVELOP>1 printf("checkSolution infeas! Retrying wihout basis and with primal.\n"); #endif solver_->initialSolve(); #if COIN_DEVELOP>1 if (!solver_->isProvenOptimal()) { printf("checkSolution still infeas!\n"); } #endif } } //assert(solver_->isProvenOptimal()); solver_->setHintParam(OsiDoDualInInitial, saveTakeHint, saveStrength); objectiveValue = solver_->getObjValue() * solver_->getObjSense(); } bestSolutionBasis_ = CoinWarmStartBasis(); /* Check that the solution still beats the objective cutoff. If it passes, make a copy of the primal variable values and do some cleanup and checks: + Values of all variables are are within original bounds and values of all integer variables are within tolerance of integral. + There are no constraint violations. There really should be no need for the check against original bounds. Perhaps an opportunity for a sanity check? */ if (objectiveValue > cutoff && objectiveValue < cutoff + 1.0e-8 + 1.0e-8*fabs(cutoff)) cutoff = objectiveValue; // relax if ((solver_->isProvenOptimal() || (specialOptions_&4) != 0) && objectiveValue <= cutoff) { memcpy(solution , solver_->getColSolution(), numberColumns*sizeof(double)) ; int iColumn; #ifndef NDEBUG double integerTolerance = getIntegerTolerance() ; #endif #if COIN_DEVELOP>1 const double * dj = solver_->getReducedCost(); const double * colLower = saveSolver->getColLower(); const double * colUpper = saveSolver->getColUpper(); int nAtLbNatural = 0; int nAtUbNatural = 0; int nAtLbNaturalZero = 0; int nAtUbNaturalZero = 0; int nAtLbFixed = 0; int nAtUbFixed = 0; int nAtOther = 0; int nAtOtherNatural = 0; int nNotNeeded = 0; #endif for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) { double value = solution[iColumn] ; value = CoinMax(value, saveLower[iColumn]) ; value = CoinMin(value, saveUpper[iColumn]) ; if (solver_->isInteger(iColumn)) { assert(fabs(value - solution[iColumn]) <= 100.0*integerTolerance) ; #if COIN_DEVELOP>1 double value2 = floor(value + 0.5); if (dj[iColumn] < -1.0e-6) { // negative dj //assert (value2==colUpper[iColumn]); if (saveUpper[iColumn] == colUpper[iColumn]) { nAtUbNatural++; if (saveLower[iColumn] != colLower[iColumn]) nNotNeeded++; } else if (saveLower[iColumn] == colUpper[iColumn]) { nAtLbFixed++; } else { nAtOther++; if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) nNotNeeded++; } } else if (dj[iColumn] > 1.0e-6) { // positive dj //assert (value2==colLower[iColumn]); if (saveLower[iColumn] == colLower[iColumn]) { nAtLbNatural++; if (saveUpper[iColumn] != colUpper[iColumn]) nNotNeeded++; } else if (saveUpper[iColumn] == colLower[iColumn]) { nAtUbFixed++; } else { nAtOther++; if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) nNotNeeded++; } } else { // zero dj if (value2 == saveUpper[iColumn]) { nAtUbNaturalZero++; if (saveLower[iColumn] != colLower[iColumn]) nNotNeeded++; } else if (value2 == saveLower[iColumn]) { nAtLbNaturalZero++; } else { nAtOtherNatural++; if (saveLower[iColumn] != colLower[iColumn] && saveUpper[iColumn] != colUpper[iColumn]) nNotNeeded++; } } #endif } solution[iColumn] = value ; } #if COIN_DEVELOP>1 printf("nAtLbNat %d,nAtUbNat %d,nAtLbNatZero %d,nAtUbNatZero %d,nAtLbFixed %d,nAtUbFixed %d,nAtOther %d,nAtOtherNat %d, useless %d\n", nAtLbNatural, nAtUbNatural, nAtLbNaturalZero, nAtUbNaturalZero, nAtLbFixed, nAtUbFixed, nAtOther, nAtOtherNatural, nNotNeeded); //if (currentNode_) //printf(" SOL at depth %d\n",currentNode_->depth()); //else //printf(" SOL at unknown depth\n"); #endif if ((specialOptions_&16) == 0) { #ifdef JJF_ZERO // check without scaling bool saveTakeHint; OsiHintStrength saveStrength; solver_->getHintParam(OsiDoScale, saveTakeHint, saveStrength); solver_->setHintParam(OsiDoScale, false, OsiHintTry); solver_->resolve(); solver_->setHintParam(OsiDoScale, saveTakeHint, saveStrength); #endif double largestInfeasibility = 0.0; double primalTolerance ; solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ; const double * rowLower = solver_->getRowLower() ; const double * rowUpper = solver_->getRowUpper() ; int numberRows = solver_->getNumRows() ; double *rowActivity = new double[numberRows] ; memset(rowActivity, 0, numberRows*sizeof(double)) ; double *rowSum = new double[numberRows] ; memset(rowSum, 0, numberRows*sizeof(double)) ; const double * element = solver_->getMatrixByCol()->getElements(); const int * row = solver_->getMatrixByCol()->getIndices(); const CoinBigIndex * columnStart = solver_->getMatrixByCol()->getVectorStarts(); const int * columnLength = solver_->getMatrixByCol()->getVectorLengths(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = solution[iColumn]; if (value) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; rowSum[iRow] += fabs(value * element[j]); } } } for (i = 0 ; i < numberRows ; i++) { #ifdef CLP_INVESTIGATE double inf; inf = rowLower[i] - rowActivity[i]; if (inf > primalTolerance) printf("Row %d inf %g sum %g %g <= %g <= %g\n", i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]); inf = rowActivity[i] - rowUpper[i]; if (inf > primalTolerance) printf("Row %d inf %g sum %g %g <= %g <= %g\n", i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]); #endif double infeasibility = CoinMax(rowActivity[i]-rowUpper[i], rowLower[i]-rowActivity[i]); // but allow for errors double factor = CoinMax(1.0,rowSum[i]*1.0e-3); if (infeasibility>largestInfeasibility*factor) largestInfeasibility = infeasibility/factor; } delete [] rowActivity ; delete [] rowSum; #ifdef CLP_INVESTIGATE if (largestInfeasibility > 10.0*primalTolerance) printf("largest infeasibility is %g\n", largestInfeasibility); #endif if (largestInfeasibility > 1000.0*primalTolerance) { handler_->message(CBC_NOTFEAS3, messages_) << largestInfeasibility << CoinMessageEol ; objectiveValue = 1.0e50 ; } } } else { objectiveValue = 1.0e50 ; } /* Regardless of what we think of the solution, we may need to restore the original bounds of the continuous solver. Unfortunately, const'ness prevents us from simply reversing the memcpy used to make these snapshots. */ if (fixVariables <= 0) { for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) { solver_->setColLower(iColumn, saveLower[iColumn]) ; solver_->setColUpper(iColumn, saveUpper[iColumn]) ; } } delete [] saveLower; delete [] saveUpper; solver_->setColSolution(saveSolution); delete [] saveSolution; solver_->setWarmStart(basis); delete basis ; /* Restore the usual solver. */ solver_ = saveSolver; testSolution_ = save; return objectiveValue; } else { // Outer approximation or similar //If this is true then the solution comes from the nlp we don't need to resolve the same nlp with ipopt //solverCharacteristics_->setSolver(solver_); bool solutionComesFromNlp = solverCharacteristics_->bestObjectiveValue() < cutoff; double objectiveValue; int numberColumns = solver_->getNumCols(); double *saveLower = NULL; double * saveUpper = NULL; if (! solutionComesFromNlp) { //Otherwise solution already comes from ipopt and cuts are known if (fixVariables > 0) { //Will temporarily fix all integer valued var // save original bounds saveUpper = new double[numberColumns]; saveLower = new double[numberColumns]; memcpy(saveUpper, solver_->getColUpper(), numberColumns*sizeof(double)); memcpy(saveLower, solver_->getColLower(), numberColumns*sizeof(double)); //in any case solution should be already loaded into solver_ /* Run through the objects and use feasibleRegion() to set variable bounds so as to fix the variables specified in the objects at their value in this solution. Since the object list contains (at least) one object for every integer variable, this has the effect of fixing all integer variables. */ const double * save = testSolution_; testSolution_ = solution; // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); for (int i = 0; i < numberObjects_; i++) object_[i]->feasibleRegion(solver_, &usefulInfo); testSolution_ = save; resolve(solver_); } /* Now step through the cut generators and see if any of them are flagged to run when a new solution is discovered. Only global cuts are useful. (The solution being evaluated may not correspond to the current location in the search tree --- discovered by heuristic, for example.) */ OsiCuts theseCuts; int i; int lastNumberCuts = 0; // reset probing info //if (probingInfo_) //probingInfo_->initializeFixing(); for (i = 0; i < numberCutGenerators_; i++) { if (generator_[i]->atSolution()) { generator_[i]->generateCuts(theseCuts, 1, solver_, NULL); int numberCuts = theseCuts.sizeRowCuts(); for (int j = lastNumberCuts; j < numberCuts; j++) { const OsiRowCut * thisCut = theseCuts.rowCutPtr(j); if (thisCut->globallyValid()) { // if ((specialOptions_&1)!=0) // { // /* As these are global cuts - // a) Always get debugger object // b) Not fatal error to cutoff optimal (if we have just got optimal) // */ // const OsiRowCutDebugger *debugger = solver_->getRowCutDebuggerAlways() ; // if (debugger) // { // if(debugger->invalidCut(*thisCut)) // printf("ZZZZ Global cut - cuts off optimal solution!\n"); // } // } // add to global list OsiRowCut newCut(*thisCut); newCut.setGloballyValid(true); newCut.mutableRow().setTestForDuplicateIndex(false); globalCuts_.addCutIfNotDuplicate(newCut) ; } else { // obviously wrong if (handler_->logLevel() > 1) printf("Cut generator %s set to run on new solution but NOT globally valid!!\n", generator_[i]->cutGeneratorName()); } } } } // int numberCuts = theseCuts.sizeColCuts(); // for (i=0;igloballyValid()) { // // add to global list // globalCuts_.insert(*thisCut); // } // } //have to retrieve the solution and its value from the nlp } double newObjectiveValue = cutoff; if (solverCharacteristics_->solution(newObjectiveValue, const_cast (solution), numberColumns)) { objectiveValue = newObjectiveValue; } else { objectiveValue = 2e50; } if (!solutionComesFromNlp && fixVariables > 0) { for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) { solver_->setColLower(iColumn, saveLower[iColumn]) ; solver_->setColUpper(iColumn, saveUpper[iColumn]) ; } delete [] saveLower; delete [] saveUpper; solver_->resolve(); } //If the variables were fixed the cutting plane procedure may have believed that the node could be fathomed //re-establish truth.- should do no harm for non nlp if (!solutionComesFromNlp && fixVariables > 0) solverCharacteristics_->setMipBound(-COIN_DBL_MAX); return objectiveValue; } } /* Call this routine from anywhere when a solution is found. The solution vector is assumed to contain one value for each structural variable. The first action is to run checkSolution() to confirm the objective and feasibility. If this check causes the solution to be rejected, we're done. If fixVariables = true, the variable bounds held by the continuous solver will be left fixed to the values in the solution; otherwise they are restored to the original values. If the solution is accepted, install it as the best solution. The routine also contains a hook to run any cut generators that are flagged to run when a new solution is discovered. There's a potential hazard because the cut generators see the continuous solver >after< possible restoration of original bounds (which may well invalidate the solution). */ void CbcModel::setBestSolution (CBC_Message how, double & objectiveValue, const double *solutionIn, int fixVariables) { double * solution = CoinCopyOfArray(solutionIn, solver_->getNumCols()); #ifdef JJF_ZERO { double saveOffset; solver_->getDblParam(OsiObjOffset, saveOffset); const double * obj = solver_->getObjCoefficients(); double newTrueSolutionValue = -saveOffset; double newSumInfeas = 0.0; int numberColumns = solver_->getNumCols(); for (int i = 0 ; i < numberColumns ; i++ ) { if (solver_->isInteger(i)) { double value = solution[i]; double nearest = floor(value + 0.5); newSumInfeas += fabs(value - nearest); } if (solution[i]) printf("%d obj %g val %g - total %g true\n", i, obj[i], solution[i], newTrueSolutionValue); newTrueSolutionValue += obj[i] * solution[i]; } printf("obj %g\n", newTrueSolutionValue); } #endif if (!solverCharacteristics_->solutionAddsCuts()) { // Can trust solution double cutoff = getCutoff(); if (cutoff < 1.0e30) cutoff = CoinMin(cutoff, bestObjective_) ; /* Double check the solution to catch pretenders. */ double saveObjectiveValue = objectiveValue; // save basis CoinWarmStartBasis * basis = dynamic_cast(solver_->getWarmStart()) ; assert(basis != NULL); objectiveValue = checkSolution(cutoff, solution, fixVariables, objectiveValue); if (saveObjectiveValue + 1.0e-3 < objectiveValue) { #if COIN_DEVELOP>1 printf("First try at solution had objective %.16g, rechecked as %.16g\n", saveObjectiveValue, objectiveValue); #endif // try again with basic variables with original bounds // save basis CoinWarmStartBasis * basis2 = dynamic_cast(solver_->getWarmStart()) ; assert(basis2 != NULL); solver_->setWarmStart(basis); int numberColumns = solver_->getNumCols(); double * solution2 = CoinCopyOfArray(solutionIn, numberColumns); double objectiveValue2 = saveObjectiveValue; objectiveValue2 = checkSolution(cutoff, solution2, -1, objectiveValue2); #if COIN_DEVELOP>1 printf("Relaxed second try had objective of %.16g\n", objectiveValue2); #endif if (objectiveValue2 + 1.0e-7 < objectiveValue) { // Now check tolerances double integerTolerance = dblParam_[CbcIntegerTolerance]; double tolerance; solver_->getDblParam(OsiPrimalTolerance, tolerance) ; double largestAway = 0.0; int iAway = -1; double largestInfeasibility = tolerance; #if COIN_DEVELOP>1 int iInfeas = -1; #endif const double * columnLower = continuousSolver_->getColLower(); const double * columnUpper = continuousSolver_->getColUpper(); int i; for (i = 0; i < numberColumns; i++) { double value = solution2[i]; if (value > columnUpper[i] + largestInfeasibility) { #if COIN_DEVELOP>1 iInfeas = i; #endif largestInfeasibility = value - columnUpper[i]; } else if (value < columnLower[i] - largestInfeasibility) { #if COIN_DEVELOP>1 iInfeas = i; #endif largestInfeasibility = columnLower[i] - value; } } for (i = 0; i < numberObjects_; i++) { CbcSimpleInteger * obj = dynamic_cast (object_[i]) ; if (obj) { int iColumn = obj->columnNumber(); double value = solution2[iColumn]; value = fabs(floor(value + 0.5) - value); if (value > largestAway) { iAway = iColumn; largestAway = value; } } } #if COIN_DEVELOP>1 if (iInfeas >= 0) printf("Largest infeasibility of %g on column %d - tolerance %g\n", largestInfeasibility, iInfeas, tolerance); #endif if (largestAway > integerTolerance) { handler_->message(CBC_RELAXED1, messages_) << objectiveValue2 << iAway << largestAway << integerTolerance << CoinMessageEol ; } else { handler_->message(CBC_RELAXED2, messages_) << objectiveValue2 << integerTolerance << CoinMessageEol ; // take CoinCopyN(solution2, numberColumns, solution); objectiveValue = objectiveValue2; } } delete [] solution2; solver_->setWarmStart(basis2); delete basis2 ; } delete basis ; if (objectiveValue > cutoff && objectiveValue < cutoff + 1.0e-8 + 1.0e-8*fabs(cutoff)) cutoff = objectiveValue; // relax CbcEventHandler::CbcAction action = dealWithEventHandler(CbcEventHandler::beforeSolution2, objectiveValue, solution); if (action == CbcEventHandler::killSolution) { // Pretend solution never happened objectiveValue = cutoff + 1.0e30; } if (objectiveValue > cutoff || objectiveValue > 1.0e30) { if (objectiveValue > 1.0e30) handler_->message(CBC_NOTFEAS1, messages_) << CoinMessageEol ; else handler_->message(CBC_NOTFEAS2, messages_) << objectiveValue << cutoff << CoinMessageEol ; } else if (objectiveValue < bestObjective_) { /* We have a winner. Install it as the new incumbent. Bump the objective cutoff value and solution counts. Give the user the good news. */ specialOptions_ |= 256; // mark as full cut scan should be done saveBestSolution(solution, objectiveValue); //bestObjective_ = objectiveValue; //int numberColumns = solver_->getNumCols(); //if (!bestSolution_) //bestSolution_ = new double[numberColumns]; //CoinCopyN(solution,numberColumns,bestSolution_); cutoff = bestObjective_ - dblParam_[CbcCutoffIncrement]; // But allow for rounding errors if (dblParam_[CbcCutoffIncrement] == 1e-5) { #if COIN_DEVELOP>5 if (saveObjectiveValue + 1.0e-7 < bestObjective_) printf("First try at solution had objective %.16g, rechecked as %.16g\n", saveObjectiveValue, bestObjective_); #endif saveObjectiveValue = CoinMax(saveObjectiveValue, bestObjective_ - 0.0000001 * fabs(bestObjective_)); cutoff = CoinMin(bestObjective_, saveObjectiveValue) - 1.0e-5; if (fabs(cutoff + 1.0e-5 - floor(cutoff + 0.5)) < 1.0e-8) cutoff -= 2.0e-5; } // This is not correct - that way cutoff can go up if maximization //double direction = solver_->getObjSense(); //setCutoff(cutoff*direction); setCutoff(cutoff); // change cutoff as constraint if wanted if (cutoffRowNumber_>=0) { if (solver_->getNumRows()>cutoffRowNumber_) { double offset; solver_->getDblParam(OsiObjOffset, offset); solver_->setRowUpper(cutoffRowNumber_,cutoff+offset); } } if (how == CBC_ROUNDING) numberHeuristicSolutions_++; numberSolutions_++; if (how != CBC_ROUNDING) { handler_->message(how, messages_) << bestObjective_ << numberIterations_ << numberNodes_ << getCurrentSeconds() << CoinMessageEol; } else { const char * name ; if (lastHeuristic_) name = lastHeuristic_->heuristicName(); else name = "Reduced search"; handler_->message(CBC_ROUNDING, messages_) << bestObjective_ << name << numberIterations_ << numberNodes_ << getCurrentSeconds() << CoinMessageEol; dealWithEventHandler(CbcEventHandler::heuristicSolution, objectiveValue, solution); } /* Now step through the cut generators and see if any of them are flagged to run when a new solution is discovered. Only global cuts are useful. (The solution being evaluated may not correspond to the current location in the search tree --- discovered by heuristic, for example.) */ OsiCuts theseCuts; int i; int lastNumberCuts = 0; // reset probing info //if (probingInfo_) //probingInfo_->initializeFixing(); for (i = 0; i < numberCutGenerators_; i++) { bool generate = generator_[i]->atSolution(); // skip if not optimal and should be (maybe a cut generator has fixed variables) if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable()) generate = false; if (generate) { generator_[i]->generateCuts(theseCuts, 1, solver_, NULL); int numberCuts = theseCuts.sizeRowCuts(); for (int j = lastNumberCuts; j < numberCuts; j++) { const OsiRowCut * thisCut = theseCuts.rowCutPtr(j); if (thisCut->globallyValid()) { if ((specialOptions_&1) != 0) { /* As these are global cuts - a) Always get debugger object b) Not fatal error to cutoff optimal (if we have just got optimal) */ const OsiRowCutDebugger *debugger = solver_->getRowCutDebuggerAlways() ; if (debugger) { if (debugger->invalidCut(*thisCut)) printf("ZZZZ Global cut - cuts off optimal solution!\n"); } } // add to global list OsiRowCut newCut(*thisCut); newCut.setGloballyValid(true); newCut.mutableRow().setTestForDuplicateIndex(false); globalCuts_.addCutIfNotDuplicate(newCut) ; generator_[i]->incrementNumberCutsInTotal(); } } } } int numberCuts = theseCuts.sizeColCuts(); for (i = 0; i < numberCuts; i++) { const OsiColCut * thisCut = theseCuts.colCutPtr(i); if (thisCut->globallyValid()) { // fix makeGlobalCut(thisCut); } } } } else { // Outer approximation or similar double cutoff = getCutoff() ; /* Double check the solution to catch pretenders. */ int numberRowBefore = solver_->getNumRows(); int numberColBefore = solver_->getNumCols(); double *saveColSol = NULL; CoinWarmStart * saveWs = NULL; // if(how!=CBC_SOLUTION) return; if (how == CBC_ROUNDING)//We don't want to make any change to solver_ //take a snapshot of current state { //save solution saveColSol = new double[numberColBefore]; CoinCopyN(solver_->getColSolution(), numberColBefore, saveColSol); //save warm start saveWs = solver_->getWarmStart(); } //run check solution this will eventually generate cuts //if in strongBranching or heuristic will do only one cut generation iteration // by fixing variables. if (!fixVariables && ((how == CBC_ROUNDING) || (how == CBC_STRONGSOL))) fixVariables = 1; double * candidate = new double[numberColBefore]; CoinCopyN(solution, numberColBefore, candidate); objectiveValue = checkSolution(cutoff, candidate, fixVariables, objectiveValue); //If it was an heuristic solution we have to clean up the solver if (how == CBC_ROUNDING) { //delete the cuts int currentNumberRowCuts = solver_->getNumRows() - numberRowBefore; int currentNumberColCuts = solver_->getNumCols() - numberColBefore; if (CoinMax(currentNumberColCuts, currentNumberRowCuts) > 0) { int *which = new int[CoinMax(currentNumberColCuts, currentNumberRowCuts)]; if (currentNumberRowCuts) { for (int i = 0 ; i < currentNumberRowCuts ; i++) which[i] = i + numberRowBefore; solver_->deleteRows(currentNumberRowCuts, which); } if (currentNumberColCuts) { for (int i = 0 ; i < currentNumberColCuts ; i++) which[i] = i + numberColBefore; solver_->deleteCols(currentNumberColCuts, which); } delete [] which; } // Reset solution and warm start info solver_->setColSolution(saveColSol); solver_->setWarmStart(saveWs); delete [] saveColSol; delete saveWs; } if (objectiveValue > cutoff) { // message only for solution if (how == CBC_SOLUTION) { if (!solverCharacteristics_->solutionAddsCuts()) { if (objectiveValue > 1.0e30) handler_->message(CBC_NOTFEAS1, messages_) << CoinMessageEol ; else handler_->message(CBC_NOTFEAS2, messages_) << objectiveValue << cutoff << CoinMessageEol ; } } } else { /* We have a winner. Install it as the new incumbent. Bump the objective cutoff value and solution counts. Give the user the good news. NB - Not all of this if from solve with cuts */ saveBestSolution(candidate, objectiveValue); //bestObjective_ = objectiveValue; //int numberColumns = solver_->getNumCols(); //if (!bestSolution_) //bestSolution_ = new double[numberColumns]; //CoinCopyN(candidate,numberColumns,bestSolution_); // don't update if from solveWithCuts if (how != CBC_SOLUTION2) { if (how == CBC_ROUNDING) numberHeuristicSolutions_++; cutoff = bestObjective_ - dblParam_[CbcCutoffIncrement]; // This is not correct - that way cutoff can go up if maximization //double direction = solver_->getObjSense(); //setCutoff(cutoff*direction); setCutoff(cutoff); // change cutoff as constraint if wanted if (cutoffRowNumber_>=0) { if (solver_->getNumRows()>cutoffRowNumber_) { double offset; solver_->getDblParam(OsiObjOffset, offset); solver_->setRowUpper(cutoffRowNumber_,cutoff+offset); } } numberSolutions_++; if (how != CBC_ROUNDING) { handler_->message(how, messages_) << bestObjective_ << numberIterations_ << numberNodes_ << getCurrentSeconds() << CoinMessageEol; } else { assert (lastHeuristic_); const char * name = lastHeuristic_->heuristicName(); handler_->message(CBC_ROUNDING, messages_) << bestObjective_ << name << numberIterations_ << numberNodes_ << getCurrentSeconds() << CoinMessageEol; } } } delete [] candidate; } delete [] solution; return ; } // Deals with event handler and solution CbcEventHandler::CbcAction CbcModel::dealWithEventHandler(CbcEventHandler::CbcEvent event, double objValue, const double * solution) { CbcEventHandler *eventHandler = getEventHandler() ; if (eventHandler) { // Temporarily put in best double saveObj = bestObjective_; int numberColumns = solver_->getNumCols(); double * saveSol = CoinCopyOfArray(bestSolution_, numberColumns); if (!saveSol) bestSolution_ = new double [numberColumns]; bestObjective_ = objValue; memcpy(bestSolution_, solution, numberColumns*sizeof(double)); CbcEventHandler::CbcAction action = eventHandler->event(event); bestObjective_ = saveObj; if (saveSol) { memcpy(bestSolution_, saveSol, numberColumns*sizeof(double)); delete [] saveSol; } else { delete [] bestSolution_; bestSolution_ = NULL; } return action; } else { return CbcEventHandler::noAction; } } /* Test the current solution for feasibility. Calculate the number of standard integer infeasibilities, then scan the remaining objects to see if any of them report infeasibilities. Currently (2003.08) the only object besides SimpleInteger is Clique, hence the comments about `odd ones' infeasibilities. */ bool CbcModel::feasibleSolution(int & numberIntegerInfeasibilities, int & numberObjectInfeasibilities) const { int numberUnsatisfied = 0; //double sumUnsatisfied=0.0; int preferredWay; int j; // Point to current solution const double * save = testSolution_; // Safe as will be const inside infeasibility() testSolution_ = solver_->getColSolution(); // Put current solution in safe place //memcpy(currentSolution_,solver_->getColSolution(), // solver_->getNumCols()*sizeof(double)); // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); #define SIMPLE_INTEGER #ifdef SIMPLE_INTEGER const double * solution = usefulInfo.solution_; const double * lower = usefulInfo.lower_; const double * upper = usefulInfo.upper_; double tolerance = usefulInfo.integerTolerance_; #endif for (j = 0; j < numberIntegers_; j++) { #ifndef SIMPLE_INTEGER const OsiObject * object = object_[j]; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); if (infeasibility) { assert (infeasibility > 0); numberUnsatisfied++; //sumUnsatisfied += infeasibility; } #else int iColumn = integerVariable_[j]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); double nearest = floor(value + 0.5); if (fabs(value - nearest) > tolerance) { numberUnsatisfied++; } #endif } numberIntegerInfeasibilities = numberUnsatisfied; for (; j < numberObjects_; j++) { const OsiObject * object = object_[j]; double infeasibility = object->infeasibility(&usefulInfo, preferredWay); if (infeasibility) { assert (infeasibility > 0); numberUnsatisfied++; //sumUnsatisfied += infeasibility; } } // and restore testSolution_ = save; numberObjectInfeasibilities = numberUnsatisfied - numberIntegerInfeasibilities; return (!numberUnsatisfied); } /* For all vubs see if we can tighten bounds by solving Lp's type - 0 just vubs 1 all (could be very slow) -1 just vubs where variable away from bound Returns false if not feasible */ bool CbcModel::tightenVubs(int type, bool allowMultipleBinary, double useCutoff) { CoinPackedMatrix matrixByRow(*solver_->getMatrixByRow()); int numberRows = solver_->getNumRows(); int numberColumns = solver_->getNumCols(); int iRow, iColumn; // Row copy //const double * elementByRow = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); const double * colUpper = solver_->getColUpper(); const double * colLower = solver_->getColLower(); //const double * rowUpper = solver_->getRowUpper(); //const double * rowLower = solver_->getRowLower(); const double * objective = solver_->getObjCoefficients(); //double direction = solver_->getObjSense(); const double * colsol = solver_->getColSolution(); int numberVub = 0; int * continuous = new int[numberColumns]; if (type >= 0) { double * sort = new double[numberColumns]; for (iRow = 0; iRow < numberRows; iRow++) { int j; int numberBinary = 0; int numberUnsatisfiedBinary = 0; int numberContinuous = 0; int iCont = -1; double weight = 1.0e30; for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; if (colUpper[iColumn] - colLower[iColumn] > 1.0e-8) { if (solver_->isFreeBinary(iColumn)) { numberBinary++; /* For sort I make naive assumption: x - a * delta <=0 or -x + a * delta >= 0 */ if (colsol[iColumn] > colLower[iColumn] + 1.0e-6 && colsol[iColumn] < colUpper[iColumn] - 1.0e-6) { numberUnsatisfiedBinary++; weight = CoinMin(weight, fabs(objective[iColumn])); } } else { numberContinuous++; iCont = iColumn; } } } if (numberContinuous == 1 && numberBinary) { if (numberBinary == 1 || allowMultipleBinary) { // treat as vub if (!numberUnsatisfiedBinary) weight = -1.0; // at end sort[numberVub] = -weight; continuous[numberVub++] = iCont; } } } if (type > 0) { // take so many CoinSort_2(sort, sort + numberVub, continuous); numberVub = CoinMin(numberVub, type); } delete [] sort; } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) continuous[iColumn] = iColumn; numberVub = numberColumns; } bool feasible = tightenVubs(numberVub, continuous, useCutoff); delete [] continuous; return feasible; } // This version is just handed a list of variables bool CbcModel::tightenVubs(int numberSolves, const int * which, double useCutoff) { int numberColumns = solver_->getNumCols(); int iColumn; OsiSolverInterface * solver = solver_; double saveCutoff = getCutoff() ; double * objective = new double[numberColumns]; memcpy(objective, solver_->getObjCoefficients(), numberColumns*sizeof(double)); double direction = solver_->getObjSense(); // add in objective if there is a cutoff if (useCutoff < 1.0e30) { // get new version of model solver = solver_->clone(); CoinPackedVector newRow; for (iColumn = 0; iColumn < numberColumns; iColumn++) { solver->setObjCoeff(iColumn, 0.0); // zero out in new model if (objective[iColumn]) newRow.insert(iColumn, direction * objective[iColumn]); } solver->addRow(newRow, -COIN_DBL_MAX, useCutoff); // signal no objective delete [] objective; objective = NULL; } setCutoff(COIN_DBL_MAX); bool * vub = new bool [numberColumns]; int iVub; // mark vub columns for (iColumn = 0; iColumn < numberColumns; iColumn++) vub[iColumn] = false; for (iVub = 0; iVub < numberSolves; iVub++) vub[which[iVub]] = true; OsiCuts cuts; // First tighten bounds anyway if CglProbing there CglProbing* generator = NULL; int iGen; // reset probing info //if (probingInfo_) //probingInfo_->initializeFixing(); for (iGen = 0; iGen < numberCutGenerators_; iGen++) { generator = dynamic_cast(generator_[iGen]->generator()); if (generator) break; } int numberFixed = 0; int numberTightened = 0; int numberFixedByProbing = 0; int numberTightenedByProbing = 0; int printFrequency = (numberSolves + 19) / 20; // up to 20 messages int save[4] = {0, 0, 0, 0}; if (generator) { // set to cheaper and then restore at end save[0] = generator->getMaxPass(); save[1] = generator->getMaxProbe(); save[2] = generator->getMaxLook(); save[3] = generator->rowCuts(); generator->setMaxPass(1); generator->setMaxProbe(10); generator->setMaxLook(50); generator->setRowCuts(0); // Probing - return tight column bounds CglTreeInfo info; generator->generateCutsAndModify(*solver, cuts, &info); const double * tightLower = generator->tightLower(); const double * lower = solver->getColLower(); const double * tightUpper = generator->tightUpper(); const double * upper = solver->getColUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { double newUpper = tightUpper[iColumn]; double newLower = tightLower[iColumn]; if (newUpper < upper[iColumn] - 1.0e-8*(fabs(upper[iColumn]) + 1) || newLower > lower[iColumn] + 1.0e-8*(fabs(lower[iColumn]) + 1)) { if (newUpper < newLower) { fprintf(stderr, "Problem is infeasible\n"); return false; } if (newUpper == newLower) { numberFixed++; numberFixedByProbing++; solver->setColLower(iColumn, newLower); solver->setColUpper(iColumn, newUpper); COIN_DETAIL_PRINT(printf("Column %d, new bounds %g %g\n", iColumn, newLower, newUpper)); } else if (vub[iColumn]) { numberTightened++; numberTightenedByProbing++; if (!solver->isInteger(iColumn)) { // relax newLower = CoinMax(lower[iColumn], newLower - 1.0e-5 * (fabs(lower[iColumn]) + 1)); newUpper = CoinMin(upper[iColumn], newUpper + 1.0e-5 * (fabs(upper[iColumn]) + 1)); } solver->setColLower(iColumn, newLower); solver->setColUpper(iColumn, newUpper); } } } } CoinWarmStart * ws = solver->getWarmStart(); double * solution = new double [numberColumns]; memcpy(solution, solver->getColSolution(), numberColumns*sizeof(double)); for (iColumn = 0; iColumn < numberColumns; iColumn++) solver->setObjCoeff(iColumn, 0.0); //solver->messageHandler()->setLogLevel(2); for (iVub = 0; iVub < numberSolves; iVub++) { iColumn = which[iVub]; int iTry; for (iTry = 0; iTry < 2; iTry++) { double saveUpper = solver->getColUpper()[iColumn]; double saveLower = solver->getColLower()[iColumn]; double value; if (iTry == 1) { // try all way up solver->setObjCoeff(iColumn, -1.0); } else { // try all way down solver->setObjCoeff(iColumn, 1.0); } solver->initialSolve(); setPointers(continuousSolver_); value = solver->getColSolution()[iColumn]; bool change = false; if (iTry == 1) { if (value < saveUpper - 1.0e-4) { if (solver->isInteger(iColumn)) { value = floor(value + 0.00001); } else { // relax a bit value = CoinMin(saveUpper, value + 1.0e-5 * (fabs(saveUpper) + 1)); } if (value - saveLower < 1.0e-7) value = saveLower; // make sure exactly same solver->setColUpper(iColumn, value); saveUpper = value; change = true; } } else { if (value > saveLower + 1.0e-4) { if (solver->isInteger(iColumn)) { value = ceil(value - 0.00001); } else { // relax a bit value = CoinMax(saveLower, value - 1.0e-5 * (fabs(saveLower) + 1)); } if (saveUpper - value < 1.0e-7) value = saveUpper; // make sure exactly same solver->setColLower(iColumn, value); saveLower = value; change = true; } } solver->setObjCoeff(iColumn, 0.0); if (change) { if (saveUpper == saveLower) numberFixed++; else numberTightened++; int saveFixed = numberFixed; int jColumn; if (generator) { // Probing - return tight column bounds cuts = OsiCuts(); CglTreeInfo info; generator->generateCutsAndModify(*solver, cuts, &info); const double * tightLower = generator->tightLower(); const double * lower = solver->getColLower(); const double * tightUpper = generator->tightUpper(); const double * upper = solver->getColUpper(); for (jColumn = 0; jColumn < numberColumns; jColumn++) { double newUpper = tightUpper[jColumn]; double newLower = tightLower[jColumn]; if (newUpper < upper[jColumn] - 1.0e-8*(fabs(upper[jColumn]) + 1) || newLower > lower[jColumn] + 1.0e-8*(fabs(lower[jColumn]) + 1)) { if (newUpper < newLower) { fprintf(stderr, "Problem is infeasible\n"); return false; } if (newUpper == newLower) { numberFixed++; numberFixedByProbing++; solver->setColLower(jColumn, newLower); solver->setColUpper(jColumn, newUpper); } else if (vub[jColumn]) { numberTightened++; numberTightenedByProbing++; if (!solver->isInteger(jColumn)) { // relax newLower = CoinMax(lower[jColumn], newLower - 1.0e-5 * (fabs(lower[jColumn]) + 1)); newUpper = CoinMin(upper[jColumn], newUpper + 1.0e-5 * (fabs(upper[jColumn]) + 1)); } solver->setColLower(jColumn, newLower); solver->setColUpper(jColumn, newUpper); } } } } if (numberFixed > saveFixed) { // original solution may not be feasible // go back to true costs to solve if exists if (objective) { for (jColumn = 0; jColumn < numberColumns; jColumn++) solver->setObjCoeff(jColumn, objective[jColumn]); } solver->setColSolution(solution); solver->setWarmStart(ws); solver->resolve(); if (!solver->isProvenOptimal()) { fprintf(stderr, "Problem is infeasible\n"); return false; } delete ws; ws = solver->getWarmStart(); memcpy(solution, solver->getColSolution(), numberColumns*sizeof(double)); for (jColumn = 0; jColumn < numberColumns; jColumn++) solver->setObjCoeff(jColumn, 0.0); } } solver->setColSolution(solution); solver->setWarmStart(ws); } if (iVub % printFrequency == 0) handler_->message(CBC_VUB_PASS, messages_) << iVub + 1 << numberFixed << numberTightened << CoinMessageEol; } handler_->message(CBC_VUB_END, messages_) << numberFixed << numberTightened << CoinMessageEol; delete ws; delete [] solution; // go back to true costs to solve if exists if (objective) { for (iColumn = 0; iColumn < numberColumns; iColumn++) solver_->setObjCoeff(iColumn, objective[iColumn]); delete [] objective; } delete [] vub; if (generator) { /*printf("Probing fixed %d and tightened %d\n", numberFixedByProbing, numberTightenedByProbing);*/ if (generator_[iGen]->howOften() == -1 && (numberFixedByProbing + numberTightenedByProbing)*5 > (numberFixed + numberTightened)) generator_[iGen]->setHowOften(1000000 + 1); generator->setMaxPass(save[0]); generator->setMaxProbe(save[1]); generator->setMaxLook(save[2]); generator->setRowCuts(save[3]); } if (solver != solver_) { // move bounds across const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * lowerOrig = solver_->getColLower(); const double * upperOrig = solver_->getColUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { solver_->setColLower(iColumn, CoinMax(lower[iColumn], lowerOrig[iColumn])); solver_->setColUpper(iColumn, CoinMin(upper[iColumn], upperOrig[iColumn])); } delete solver; } setCutoff(saveCutoff); return true; } // Pass in Message handler (not deleted at end) void CbcModel::passInMessageHandler(CoinMessageHandler * handler) { if (defaultHandler_) { delete handler_; handler_ = NULL; } defaultHandler_ = false; handler_ = handler; if (solver_) solver_->passInMessageHandler(handler); if (continuousSolver_) continuousSolver_->passInMessageHandler(handler); if (referenceSolver_) referenceSolver_->passInMessageHandler(handler); } void CbcModel::passInTreeHandler(CbcTree & tree) { delete tree_; tree_ = tree.clone(); } // Make sure region there void CbcModel::reserveCurrentSolution(const double * solution) { int numberColumns = getNumCols() ; if (!currentSolution_) currentSolution_ = new double[numberColumns] ; testSolution_ = currentSolution_; if (solution) memcpy(currentSolution_, solution, numberColumns*sizeof(double)); } /* For passing in an CbcModel to do a sub Tree (with derived tree handlers). Passed in model must exist for duration of branch and bound */ void CbcModel::passInSubTreeModel(CbcModel & model) { subTreeModel_ = &model; } // For retrieving a copy of subtree model with given OsiSolver or NULL CbcModel * CbcModel::subTreeModel(OsiSolverInterface * solver) const { const CbcModel * subModel = subTreeModel_; if (!subModel) subModel = this; // Get new copy CbcModel * newModel = new CbcModel(*subModel); if (solver) newModel->assignSolver(solver); return newModel; } //############################################################################# // Set/Get Application Data // This is a pointer that the application can store into and retrieve // from the solverInterface. // This field is the application to optionally define and use. //############################################################################# void CbcModel::setApplicationData(void * appData) { appData_ = appData; } //----------------------------------------------------------------------------- void * CbcModel::getApplicationData() const { return appData_; } // Set a pointer to a row cut which will be added instead of normal branching. void CbcModel::setNextRowCut(const OsiRowCut & cut) { nextRowCut_ = new OsiRowCut(cut); nextRowCut_->setEffectiveness(COIN_DBL_MAX); // mark so will always stay } // Just update objectiveValue void CbcModel::setBestObjectiveValue( double objectiveValue) { bestObjective_ = objectiveValue; } double CbcModel::getBestPossibleObjValue() const { return CoinMin(bestPossibleObjective_, bestObjective_) * solver_->getObjSense() ; } // Make given rows (L or G) into global cuts and remove from lp void CbcModel::makeGlobalCuts(int number, const int * which) { const double * rowLower = solver_->getRowLower(); const double * rowUpper = solver_->getRowUpper(); int numberRows = solver_->getNumRows(); // Row copy const double * elementByRow = solver_->getMatrixByRow()->getElements(); const int * column = solver_->getMatrixByRow()->getIndices(); const CoinBigIndex * rowStart = solver_->getMatrixByRow()->getVectorStarts(); const int * rowLength = solver_->getMatrixByRow()->getVectorLengths(); // Not all rows may be good so we need new array int * whichDelete = new int[numberRows]; int nDelete = 0; for (int i = 0; i < number; i++) { int iRow = which[i]; if (iRow >= 0 && iRow < numberRows) { if (rowLower[iRow] < -1.0e20 || rowUpper[iRow] > 1.0e20) { whichDelete[nDelete++] = iRow; OsiRowCut thisCut; thisCut.setLb(rowLower[iRow]); thisCut.setUb(rowUpper[iRow]); int start = rowStart[iRow]; thisCut.setRow(rowLength[iRow], column + start, elementByRow + start, false); thisCut.setGloballyValid(true); globalCuts_.addCutIfNotDuplicate(thisCut) ; } } } if (nDelete) solver_->deleteRows(nDelete, whichDelete); delete [] whichDelete; } // Make given cut into a global cut void CbcModel::makeGlobalCut(const OsiRowCut * cut) { OsiRowCut newCut(*cut); newCut.setGloballyValidAsInteger(2); newCut.mutableRow().setTestForDuplicateIndex(false); globalCuts_.addCutIfNotDuplicate(newCut) ; } // Make given cut into a global cut void CbcModel::makeGlobalCut(const OsiRowCut & cut) { OsiRowCut newCut(cut); newCut.setGloballyValid(true); newCut.mutableRow().setTestForDuplicateIndex(false); globalCuts_.addCutIfNotDuplicate(newCut) ; } // Make given column cut into a global cut void CbcModel::makeGlobalCut(const OsiColCut * cut) { const double * lower; const double * upper; if (topOfTree_) { lower = topOfTree_->lower(); upper = topOfTree_->upper(); } else { lower = solver_->getColLower(); upper = solver_->getColUpper(); } int nLower=cut->lbs().getNumElements(); const int * indexLower=cut->lbs().getIndices(); const double * boundLower=cut->lbs().getElements(); for (int i=0;isetColLower(iColumn,newValue); else solver_->setColLower(iColumn,newValue); } int nUpper=cut->ubs().getNumElements(); const int * indexUpper=cut->ubs().getIndices(); const double * boundUpper=cut->ubs().getElements(); for (int i=0;isetColUpper(iColumn,newValue); else solver_->setColUpper(iColumn,newValue); } } // Make given column cut into a global cut void CbcModel::makeGlobalCut(const OsiColCut & cut) { const double * lower; const double * upper; if (topOfTree_) { lower = topOfTree_->lower(); upper = topOfTree_->upper(); } else { lower = solver_->getColLower(); upper = solver_->getColUpper(); } int nLower=cut.lbs().getNumElements(); const int * indexLower=cut.lbs().getIndices(); const double * boundLower=cut.lbs().getElements(); for (int i=0;isetColLower(iColumn,newValue); else solver_->setColLower(iColumn,newValue); } int nUpper=cut.ubs().getNumElements(); const int * indexUpper=cut.ubs().getIndices(); const double * boundUpper=cut.ubs().getElements(); for (int i=0;isetColUpper(iColumn,newValue); else solver_->setColUpper(iColumn,newValue); } } // Make partial cut into a global cut and save void CbcModel::makePartialCut(const OsiRowCut * partialCut, const OsiSolverInterface * solver) { // get greedy cut double bSum = partialCut->lb(); assert (bSum<0.0); if (!solver) solver=solver_; int nConflict = partialCut->row().getNumElements(); const int * column = partialCut->row().getIndices(); const double * element = partialCut->row().getElements(); double * originalLower = topOfTree_->mutableLower(); const double * columnLower = solver->getColLower(); double * originalUpper = topOfTree_->mutableUpper(); const double * columnUpper = solver->getColUpper(); int nC=nConflict; while (nConflict) { int iColumn = column[nConflict-1]; double farkasValue = element[nConflict-1]; double change; if (farkasValue>0.0) { change=farkasValue*(originalUpper[iColumn]-columnUpper[iColumn]); } else { change=farkasValue*(originalLower[iColumn]-columnLower[iColumn]); } if (bSum+change>-1.0e-4) break; nConflict--; bSum += change; } OsiRowCut newCut; newCut.setUb(COIN_DBL_MAX); double lo=1.0; double * values = new double[nConflict]; for (int i=0;i1) { if ((specialOptions_&1) != 0) { const OsiRowCutDebugger *debugger = continuousSolver_->getRowCutDebugger() ; if (debugger) { if (debugger->invalidCut(newCut)) { continuousSolver_->applyRowCuts(1,&newCut); continuousSolver_->writeMps("bad"); } CoinAssert (!debugger->invalidCut(newCut)); } } newCut.setGloballyValidAsInteger(2); newCut.mutableRow().setTestForDuplicateIndex(false); globalCuts_.addCutIfNotDuplicate(newCut) ; } else { // change bounds int iColumn=column[0]; if (values[0]<0.0) { // change upper bound double newUpper = -lo; assert (newUpperoriginalLower[iColumn]); printf("Changing lower bound on %d from %g to %g\n", iColumn,originalLower[iColumn],newLower); originalLower[iColumn]=newLower; } } // add to partial cuts if (globalConflictCuts_) { globalConflictCuts_->addCutIfNotDuplicateWhenGreedy(*partialCut,2); } delete [] values; } // Make partial cuts into global cuts void CbcModel::makeGlobalCuts() { } void CbcModel::setNodeComparison(CbcCompareBase * compare) { delete nodeCompare_; nodeCompare_ = compare->clone(); } void CbcModel::setNodeComparison(CbcCompareBase & compare) { delete nodeCompare_; nodeCompare_ = compare.clone(); } void CbcModel::setProblemFeasibility(CbcFeasibilityBase * feasibility) { delete problemFeasibility_; problemFeasibility_ = feasibility->clone(); } void CbcModel::setProblemFeasibility(CbcFeasibilityBase & feasibility) { delete problemFeasibility_; problemFeasibility_ = feasibility.clone(); } // Set the strategy. Clones void CbcModel::setStrategy(CbcStrategy & strategy) { delete strategy_; strategy_ = strategy.clone(); } // Increases usedInSolution for nonzeros void CbcModel::incrementUsed(const double * solution) { // might as well mark all including continuous int numberColumns = solver_->getNumCols(); for (int i = 0; i < numberColumns; i++) { if (solution[i]) usedInSolution_[i]++; } } // Are there numerical difficulties (for initialSolve) ? bool CbcModel::isInitialSolveAbandoned() const { if (status_ != -1) { return false; } else { return solver_->isAbandoned(); } } // Is optimality proven (for initialSolve) ? bool CbcModel::isInitialSolveProvenOptimal() const { if (status_ != -1) { return fabs(originalContinuousObjective_) < 1.0e50; } else { return solver_->isProvenOptimal(); } } // Is primal infeasiblity proven (for initialSolve) ? bool CbcModel::isInitialSolveProvenPrimalInfeasible() const { if (status_ != -1) { if (status_ == 0 && secondaryStatus_ == 7) return false; else return originalContinuousObjective_ >= 1.0e50; } else { return solver_->isProvenPrimalInfeasible(); } } // Is dual infeasiblity proven (for initialSolve) ? bool CbcModel::isInitialSolveProvenDualInfeasible() const { if (status_ != -1) { if (status_ == 0 && secondaryStatus_ == 7) return true; else return false; } else { return solver_->isProvenDualInfeasible(); } } // Set pointers for speed void CbcModel::setPointers(const OsiSolverInterface * solver) { /// Pointer to array[getNumCols()] (for speed) of column lower bounds cbcColLower_ = solver_->getColLower(); /// Pointer to array[getNumCols()] (for speed) of column upper bounds cbcColUpper_ = solver_->getColUpper(); /// Pointer to array[getNumRows()] (for speed) of row lower bounds cbcRowLower_ = solver_->getRowLower(); /// Pointer to array[getNumRows()] (for speed) of row upper bounds cbcRowUpper_ = solver_->getRowUpper(); /// Pointer to array[getNumCols()] (for speed) of primal solution vector cbcColSolution_ = solver_->getColSolution(); /// Pointer to array[getNumRows()] (for speed) of dual prices cbcRowPrice_ = solver_->getRowPrice(); /// Get a pointer to array[getNumCols()] (for speed) of reduced costs if (solverCharacteristics_ && solverCharacteristics_->reducedCostsAccurate()) cbcReducedCost_ = solver_->getReducedCost(); else cbcReducedCost_ = NULL; /// Pointer to array[getNumRows()] (for speed) of row activity levels. cbcRowActivity_ = solver_->getRowActivity(); dblParam_[CbcCurrentObjectiveValue] = solver->getObjValue(); dblParam_[CbcCurrentMinimizationObjectiveValue] = dblParam_[CbcCurrentObjectiveValue] * dblParam_[CbcOptimizationDirection]; } /* Delete any existing handler and create a clone of the one supplied. */ void CbcModel::passInEventHandler (const CbcEventHandler *eventHandler) { delete eventHandler_; eventHandler_ = NULL ; if (eventHandler) { eventHandler_ = eventHandler->clone(); eventHandler_->setModel(this); } } /* CbcEventHandler* CbcModel::eventHandler is inlined in CbcModel.hpp. */ // Encapsulates solver resolve int CbcModel::resolve(OsiSolverInterface * solver) { numberSolves_++; #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver); #endif #ifdef CLIQUE_ANALYSIS if (probingInfo_ && currentDepth_ > 0) { int nFix = probingInfo_->fixColumns(*solver); if (nFix < 0) { #ifdef COIN_HAS_CLP if (clpSolver) clpSolver->getModelPtr()->setProblemStatus(1); #endif return 0; } } #endif #ifdef COIN_HAS_CLP if (clpSolver) { /*bool takeHint; OsiHintStrength strength; bool gotHint = (clpSolver->getHintParam(OsiDoDualInResolve,takeHint,strength)); assert (gotHint); int algorithm=-1; if (strength!=OsiHintIgnore) algorithm = takeHint ? -1 : 1; assert (algorithm==-1);*/ //clpSolver->setHintParam(OsiDoDualInResolve,true,OsiHintTry); ClpSimplex * clpSimplex = clpSolver->getModelPtr(); int save = clpSimplex->specialOptions(); if ((moreSpecialOptions_&8388608)==0) clpSimplex->setSpecialOptions(save | 0x11000000); // say is Cbc (and in branch and bound) else clpSimplex->setSpecialOptions(save | 0x11200000); // say is Cbc (and in branch and bound - but save ray) int save2 = clpSolver->specialOptions(); if (false && (save2&2048) == 0) { // see if worthwhile crunching int nFixed = 0; const double * columnLower = clpSimplex->columnLower(); const double * columnUpper = clpSimplex->columnUpper(); for (int i = 0; i < numberIntegers_; i++) { int iColumn = integerVariable_[i]; if (columnLower[iColumn] == columnUpper[iColumn]) nFixed++; } if (nFixed*20 < clpSimplex->numberColumns()) { double d = nFixed; printf("%d fixed out of %d - ratio %g\n", nFixed, clpSimplex->numberColumns(), d / clpSimplex->numberColumns()); clpSolver->setSpecialOptions(save2 | 2048); } } clpSolver->resolve(); if (!numberNodes_) { double error = CoinMax(clpSimplex->largestDualError(), clpSimplex->largestPrimalError()); if (error > 1.0e-2 || !clpSolver->isProvenOptimal()) { #ifdef CLP_INVESTIGATE printf("Problem was %s largest dual error %g largest primal %g - safer cuts\n", clpSolver->isProvenOptimal() ? "optimal" : "!infeasible", clpSimplex->largestDualError(), clpSimplex->largestPrimalError()); #endif if (!clpSolver->isProvenOptimal()) { clpSolver->setSpecialOptions(save2 | 2048); clpSimplex->allSlackBasis(true); clpSolver->resolve(); if (!clpSolver->isProvenOptimal()) { bool takeHint; OsiHintStrength strength; clpSolver->getHintParam(OsiDoDualInResolve, takeHint, strength); clpSolver->setHintParam(OsiDoDualInResolve, false, OsiHintDo); clpSolver->resolve(); clpSolver->setHintParam(OsiDoDualInResolve, takeHint, strength); } } // make cuts safer for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { CglCutGenerator * generator = generator_[iCutGenerator]->generator(); CglGomory * cgl1 = dynamic_cast(generator); if (cgl1) { cgl1->setLimitAtRoot(cgl1->getLimit()); } CglTwomir * cgl2 = dynamic_cast(generator); if (cgl2) { generator_[iCutGenerator]->setHowOften(-100); } } } } clpSolver->setSpecialOptions(save2); #ifdef CLP_INVESTIGATE if (clpSimplex->numberIterations() > 1000) printf("node %d took %d iterations\n", numberNodes_, clpSimplex->numberIterations()); #endif clpSimplex->setSpecialOptions(save); if (clpSimplex->status()==4) clpSimplex->setProblemStatus(1); } else { solver->resolve(); } #else solver->resolve(); #endif return solver->isProvenOptimal() ? 1 : 0; } #ifdef CLP_RESOLVE // Special purpose resolve int CbcModel::resolveClp(OsiClpSolverInterface * clpSolver, int type) { numberSolves_++; ClpSimplex * clpSimplex = clpSolver->getModelPtr(); int save = clpSimplex->specialOptions(); clpSimplex->setSpecialOptions(save | 0x11000000); // say is Cbc (and in branch and bound) int save2 = clpSolver->specialOptions(); clpSolver->resolve(); if (!numberNodes_) { double error = CoinMax(clpSimplex->largestDualError(), clpSimplex->largestPrimalError()); if (error > 1.0e-2 || !clpSolver->isProvenOptimal()) { #ifdef CLP_INVESTIGATE printf("Problem was %s largest dual error %g largest primal %g - safer cuts\n", clpSolver->isProvenOptimal() ? "optimal" : "!infeasible", clpSimplex->largestDualError(), clpSimplex->largestPrimalError()); #endif if (!clpSolver->isProvenOptimal()) { clpSolver->setSpecialOptions(save2 | 2048); clpSimplex->allSlackBasis(true); clpSolver->resolve(); if (!clpSolver->isProvenOptimal()) { bool takeHint; OsiHintStrength strength; clpSolver->getHintParam(OsiDoDualInResolve, takeHint, strength); clpSolver->setHintParam(OsiDoDualInResolve, false, OsiHintDo); clpSolver->resolve(); clpSolver->setHintParam(OsiDoDualInResolve, takeHint, strength); } } // make cuts safer for (int iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { CglCutGenerator * generator = generator_[iCutGenerator]->generator(); CglGomory * cgl1 = dynamic_cast(generator); if (cgl1) { cgl1->setLimitAtRoot(cgl1->getLimit()); } CglTwomir * cgl2 = dynamic_cast(generator); if (cgl2) { generator_[iCutGenerator]->setHowOften(-100); } } } } clpSolver->setSpecialOptions(save2); #ifdef CLP_INVESTIGATE if (clpSimplex->numberIterations() > 1000) printf("node %d took %d iterations\n", numberNodes_, clpSimplex->numberIterations()); #endif if (type==0 && clpSolver->isProvenOptimal()) { ClpSimplex newModel(*clpSimplex); newModel.primal(); int numberColumns = newModel.numberColumns(); int numberRows = newModel.numberRows(); double * obj = new double [numberColumns]; int * which = new int [numberColumns]; const double * solution = clpSimplex->primalColumnSolution(); double rhs=1.0e-8; int numberObj=0; double integerTolerance = getDblParam(CbcIntegerTolerance) ; double * objective = newModel.objective(); for (int i=0;iupper[iSequence]-integerTolerance) { objective[iSequence]=-1.0; numberUb++; } else if (fabs(value - nearest) <= integerTolerance) { // fix?? lower[iSequence]=nearest; upper[iSequence]=nearest; numberInt++; } else { lower[iSequence]=floor(value); upper[iSequence]=ceil(value); if (value>nearest) { objective[iSequence]=1.0; sumInf += value-nearest; } else { objective[iSequence]=-1.0; sumInf -= value-nearest; } numberInf++; } } printf("XX %d inf (sum %g), %d at lb %d at ub %d other integer\n", numberInf,sumInf,numberLb,numberUb,numberInt); if (numberInf) { newModel.primal(1); if (!newModel.isProvenOptimal()) { printf("not optimal - scaling issue - switch off\n"); clpSimplex->setSpecialOptions(save); if (clpSimplex->status()==4) clpSimplex->setProblemStatus(1); return clpSolver->isProvenOptimal() ? 1 : 0; } //newModel.writeMps("bad.mps"); //assert (newModel.isProvenOptimal()); printf("%d iterations\n",newModel.numberIterations()); int numberInf2 = 0; int numberLb2 = 0; int numberUb2 = 0; int numberInt2 = 0; double sumInf2=0.0; const double * solution = newModel.primalColumnSolution(); const double * lower = clpSimplex->columnLower(); const double * upper = clpSimplex->columnUpper(); for (int i=0;iupper[iSequence]-integerTolerance) { numberUb2++; } else if (fabs(value - nearest) <= integerTolerance) { numberInt2++; } else { if (value>nearest) { sumInf2 += value-nearest; } else { sumInf2 -= value-nearest; } numberInf2++; } } printf("XXX %d inf (sum %g), %d at lb %d at ub %d other integer\n", numberInf2,sumInf2,numberLb2,numberUb2,numberInt2); if (sumInf2objective(), numberColumns*sizeof(double)); memcpy(newModel.columnLower(), clpSimplex->columnLower(), numberColumns*sizeof(double)); memcpy(newModel.columnUpper(), clpSimplex->columnUpper(), numberColumns*sizeof(double)); newModel.setClpScaledMatrix(NULL); newModel.primal(1); printf("%d iterations\n",newModel.numberIterations()); int numberInf3 = 0; int numberLb3 = 0; int numberUb3 = 0; int numberInt3 = 0; double sumInf3=0.0; const double * solution = newModel.primalColumnSolution(); const double * lower = clpSimplex->columnLower(); const double * upper = clpSimplex->columnUpper(); for (int i=0;iupper[iSequence]-integerTolerance) { numberUb3++; } else if (fabs(value - nearest) <= integerTolerance) { numberInt3++; } else { if (value>nearest) { sumInf3 += value-nearest; } else { sumInf3 -= value-nearest; } numberInf3++; } } printf("XXXXX %d inf (sum %g), %d at lb %d at ub %d other integer\n", numberInf3,sumInf3,numberLb3,numberUb3,numberInt3); if (sumInf3primalColumnSolution(), newModel.primalColumnSolution(), numberColumns*sizeof(double)); memcpy(clpSimplex->dualColumnSolution(), newModel.dualColumnSolution(), numberColumns*sizeof(double)); memcpy(clpSimplex->primalRowSolution(), newModel.primalRowSolution(), numberRows*sizeof(double)); memcpy(clpSimplex->dualRowSolution(), newModel.dualRowSolution(), numberRows*sizeof(double)); memcpy(clpSimplex->statusArray(), newModel.statusArray(), (numberColumns+numberRows)*sizeof(unsigned char)); clpSolver->setWarmStart(NULL); } } } } clpSimplex->setSpecialOptions(save); if (clpSimplex->status()==4) clpSimplex->setProblemStatus(1); return clpSolver->isProvenOptimal() ? 1 : 0; } #endif /*! \todo It'd be really nice if there were an overload for this method that allowed a separate value for the underlying solver's log level. The overload could be coded to allow an increase in the log level of the underlying solver. It's worth contemplating whether OSI should have a setLogLevel method that's more specific than the hint mechanism. */ // Set log level void CbcModel::setLogLevel(int value) { handler_->setLogLevel(value); // Reduce print out in Osi if (solver_) { int oldLevel = solver_->messageHandler()->logLevel(); if (value < oldLevel) solver_->messageHandler()->setLogLevel(value); #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { ClpSimplex * clpSimplex = clpSolver->getModelPtr(); oldLevel = clpSimplex->logLevel(); if (value < oldLevel) clpSimplex->setLogLevel(value); } #else // COIN_HAS_CLP /* For generic OSI solvers, if the new log level is 0, try the DoReducePrint hint for emphasis. */ if (value == 0) { solver_->setHintParam(OsiDoReducePrint, true, OsiHintDo) ; } #endif // COIN_HAS_CLP } } /* Pass in target solution and optional priorities. If priorities then >0 means only branch if incorrect while <0 means branch even if correct. +1 or -1 are highest priority */ void CbcModel::setHotstartSolution(const double * solution, const int * priorities) { if (solution == NULL) { delete [] hotstartSolution_; hotstartSolution_ = NULL; delete [] hotstartPriorities_; hotstartPriorities_ = NULL; } else { int numberColumns = solver_->getNumCols(); hotstartSolution_ = CoinCopyOfArray(solution, numberColumns); hotstartPriorities_ = CoinCopyOfArray(priorities, numberColumns); for (int i = 0; i < numberColumns; i++) { if (hotstartSolution_[i] == -COIN_DBL_MAX) { hotstartSolution_[i] = 0.0; hotstartPriorities_[i] += 10000; } if (solver_->isInteger(i)) hotstartSolution_[i] = floor(hotstartSolution_[i] + 0.5); } } } // Increment strong info void CbcModel::incrementStrongInfo(int numberTimes, int numberIterations, int numberFixed, bool ifInfeasible) { strongInfo_[0] += numberTimes; numberStrongIterations_ += numberIterations; strongInfo_[1] += numberFixed; if (ifInfeasible) strongInfo_[2] ++; } /* Set objective value in a node. This is separated out so that odd solvers can use. It may look at extra information in solverCharacteriscs_ and will also use bound from parent node */ void CbcModel::setObjectiveValue(CbcNode * thisNode, const CbcNode * parentNode) const { double newObjValue = solver_->getObjSense() * solver_->getObjValue(); // If odd solver take its bound if (solverCharacteristics_) { newObjValue = CoinMax(newObjValue, solverCharacteristics_->mipBound()); // Reset bound anyway (no harm if not odd) solverCharacteristics_->setMipBound(-COIN_DBL_MAX); } // If not root then use max of this and parent if (parentNode) newObjValue = CoinMax(newObjValue, parentNode->objectiveValue()); thisNode->setObjectiveValue(newObjValue); } // Current time since start of branchAndbound double CbcModel::getCurrentSeconds() const { if (!useElapsedTime()) return CoinCpuTime() - getDblParam(CbcStartSeconds); else return CoinGetTimeOfDay() - getDblParam(CbcStartSeconds); } /* Encapsulates choosing a variable - anyAction: -2 infeasible -1 round again 0 done At the point where chooseBranch is called, we've decided that this problem will need to be placed in the live set and we need to choose a branching variable. Parameters: newNode: the node just created for the active subproblem. oldNode: newNode's parent. lastws: oldNode's basis lowerBefore, upperBefore: column bound arrays for oldNode cuts: list of cuts added to newNode. resolved: (o) set to true if newNode is resolved during processing branches: (o) will be filled in with ... ? Null on entry */ int CbcModel::chooseBranch(CbcNode * &newNode, int numberPassesLeft, CbcNode * oldNode, OsiCuts & cuts, bool & resolved, CoinWarmStartBasis *lastws, const double * lowerBefore, const double * upperBefore, OsiSolverBranch * & branches) { // Set state of search /* 0 - outside CbcNode 1 - no solutions 2 - all heuristic solutions 3 - a solution reached by branching (could be strong) 4 - no solution but many nodes add 10 if depth >= K K is currently hardcoded to 8, a few lines below. CBCMODEL_DEBUG: Seems like stateOfSearch_ should be 2 if numberHeuristicSolutions_ == numberSolutions_. */ stateOfSearch_ = 1; if (numberSolutions_ > 0) { if (numberHeuristicSolutions_ == numberSolutions_) stateOfSearch_ = 3; else stateOfSearch_ = 3; } if (numberNodes_ > 2*numberObjects_ + 1000) { stateOfSearch_ = 4; } //stateOfSearch_=3; if (currentNode_ && currentNode_->depth() >= 8) stateOfSearch_ += 10; //printf("STate %d, %d nodes - parent %c - sol %d %d\n", // stateOfSearch_,numberNodes_,parentModel_ ? 'Y' :'N', // numberSolutions_,numberHeuristicSolutions_); int anyAction = -1 ; resolved = false ; if (newNode->objectiveValue() >= getCutoff()) anyAction = -2; branches = NULL; bool feasible = true; int branchingState = -1; // Compute "small" change in branch int nBranches = intParam_[CbcNumberBranches]; if (nBranches) { double average = dblParam_[CbcSumChange] / static_cast(nBranches); dblParam_[CbcSmallChange] = CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]); dblParam_[CbcSmallChange] = CoinMax(dblParam_[CbcSmallChange], 1.0e-8); } else { dblParam_[CbcSmallChange] = 1.0e-8; } #ifdef JJF_ZERO // Say not on optimal path bool onOptimalPath = false; if ((specialOptions_&1) != 0) { /* This doesn't work as intended --- getRowCutDebugger will return null unless the current feasible solution region includes the optimal solution that RowCutDebugger knows. There's no way to tell inactive from off the optimal path. */ const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ; if (debugger) { onOptimalPath = true; printf("On optimal path - choose\n") ; } } #endif currentNode_ = newNode; // so can be used elsewhere // Remember number of rows to restore at the end of the loop int saveNumberRows=solver_->getNumRows(); /* Enough preparation. Get down to the business of choosing a branching variable. */ while (anyAction == -1) { // Set objective value (not so obvious if NLP etc) setObjectiveValue(newNode, oldNode); //if (numberPassesLeft<=0) //branchingState=1; /* Is there a CbcBranchDecision object installed? Does it specify a chooseVariable method? If not, we're using the old (Cbc) side of the branch decision hierarchy. In quick summary, CbcNode::chooseBranch uses strong branching on any objects, while CbcNode::chooseDynamicBranch uses dynamic branching, but only on simple integers (-3 is the code for punt due to complex objects). Serious bugs remain on the Cbc side, particularly in chooseDynamicBranch. */ if (!branchingMethod_ || !branchingMethod_->chooseMethod()) { #ifdef COIN_HAS_CLP bool doClp = oldNode && (oldNode->depth() % 2) == 1; if (!doCutsNow(1)) doClp = true; //doClp = true; int testDepth = 5; // Don't do if many iterations per node int totalNodes = numberNodes_ + numberExtraNodes_; int totalIterations = numberIterations_ + numberExtraIterations_; bool diving=false; if ((moreSpecialOptions_&33554432)!=0) { testDepth=COIN_INT_MAX; if (oldNode&&(oldNode->depth()==-2||oldNode->depth()==4)) diving=true; } if (totalNodes*40 < totalIterations || numberNodes_ < 1000) { doClp = false; //} else if (oldNode&&fastNodeDepth_>=0&&oldNode->depth()>=testDepth&&(specialOptions_&2048)==0) { //printf("size %d %d - cuts %d - nodes %d its %d %c\n",solver_->getNumRows(), // solver_->getNumCols(),cuts.sizeRowCuts(), // totalNodes,totalIterations,doClp ? 'Y' : 'N'); } if (oldNode && ((fastNodeDepth_ >= 0 && oldNode->depth() >= testDepth && doClp)||diving) &&/*!parentModel_*/(specialOptions_&2048) == 0 && !cuts.sizeRowCuts()) { OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) { anyAction = newNode->chooseClpBranch(this, oldNode) ; if (anyAction != -1) break; } } #endif #ifdef COIN_HAS_CLP int save=0; OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver&&(moreSpecialOptions_&4194304)!=0) { ClpSimplex * clpSimplex = clpSolver->getModelPtr(); save=clpSimplex->specialOptions(); clpSimplex->setSpecialOptions(save | 0x11200000); // say is Cbc (and in branch and bound - but save ray) } #endif if (numberBeforeTrust_ == 0 ) { anyAction = newNode->chooseBranch(this, oldNode, numberPassesLeft) ; } else { anyAction = newNode->chooseDynamicBranch(this, oldNode, branches, numberPassesLeft) ; if (anyAction == -3) anyAction = newNode->chooseBranch(this, oldNode, numberPassesLeft) ; // dynamic did nothing } #ifdef COIN_HAS_CLP if (clpSolver&&(moreSpecialOptions_&4194304)!=0) { ClpSimplex * clpSimplex = clpSolver->getModelPtr(); clpSimplex->setSpecialOptions(save); } #endif /* We're on the new (Osi) side of the branching hierarchy. */ } else { OsiBranchingInformation usefulInfo = usefulInformation(); anyAction = newNode->chooseOsiBranch(this, oldNode, &usefulInfo, branchingState) ;; // Osi method //branchingState=0; } if (!oldNode) { if (numberUpdateItems_) { for (int i = 0; i < numberUpdateItems_; i++) { CbcObjectUpdateData * update = updateItems_ + i; CbcObject * object = dynamic_cast (update->object_); #ifndef NDEBUG bool found = false; for (int j = 0; j < numberObjects_; j++) { if (update->object_ == object_[j]) { found = true; break; } } assert (found); #endif //if (object) //assert (object==object_[update->objectNumber_]); if (object) object->updateInformation(*update); } numberUpdateItems_ = 0; } } if (solverCharacteristics_ && solverCharacteristics_->solutionAddsCuts() && // we are in some OA based bab feasible && (newNode->numberUnsatisfied() == 0) //solution has become integer feasible during strong branching ) { //in the present case we need to check here integer infeasibility if the node is not fathomed we will have to do the loop // again //std::cout<getObjValue(); lastHeuristic_ = NULL; setBestSolution(CBC_SOLUTION, objval, solver_->getColSolution()) ; int easy = 2; if (!solverCharacteristics_->mipFeasible())//did we prove that the node could be pruned? feasible = false; // Reset the bound now solverCharacteristics_->setMipBound(-COIN_DBL_MAX); solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ; feasible &= resolve(oldNode ? oldNode->nodeInfo() : NULL, 11) != 0 ; solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; resolved = true ; if (problemFeasibility_->feasible(this, 0) < 0) { feasible = false; // pretend infeasible } if (feasible) anyAction = -1; else anyAction = -2; } /* Yep, false positives for sure. And no easy way to distinguish honest infeasibility from `found a solution and tightened objective target.' if (onOptimalPath) assert (anyAction!=-2); // can be useful but gives false positives on strong */ numberPassesLeft--; if (numberPassesLeft <= -1) { if (!numberLongStrong_ && !numberThreads_) messageHandler()->message(CBC_WARNING_STRONG, messages()) << CoinMessageEol ; numberLongStrong_++; } if (anyAction == -1) { // can do quick optimality check int easy = 2; solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ; feasible = resolve(oldNode ? oldNode->nodeInfo() : NULL, 11) != 0 ; solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ; resolved = true ; if (problemFeasibility_->feasible(this, 0) < 0) { feasible = false; // pretend infeasible } if (feasible) { // Set objective value (not so obvious if NLP etc) setObjectiveValue(newNode, oldNode); reducedCostFix() ; if (newNode->objectiveValue() >= getCutoff()) anyAction = -2; } else { anyAction = -2 ; } } } //A candidate has been found; restore the subproblem. if( saveNumberRowsgetNumRows()) { // delete rows - but leave solution int n = solver_->getNumRows(); int * del = new int [n-saveNumberRows]; for (int i=saveNumberRows;ideleteRows(n-saveNumberRows,del); delete [] del; } /* End main loop to choose a branching variable. */ if (anyAction >= 0) { if (resolved) { /* Used to be that when the node was not fathomed (branching object present) the solution was not needed. But that's no longer the case --- heuristics are applied, and they may want the solution. */ // bool needValidSolution = (newNode->branchingObject() == NULL) ; bool needValidSolution = true ; takeOffCuts(cuts, needValidSolution , NULL) ; # ifdef CHECK_CUT_COUNTS { printf("Number of rows after chooseBranch fix (node)" "(active only) %d\n", numberRowsAtContinuous_ + numberNewCuts_ + numberOldActiveCuts_) ; const CoinWarmStartBasis* debugws = dynamic_cast (solver_->getWarmStart()) ; debugws->print() ; delete debugws ; } # endif } { OsiBranchingObject * branchingObject = newNode->modifiableBranchingObject(); CbcGeneralBranchingObject * generalBranch = dynamic_cast (branchingObject); if (generalBranch && false) { int numberProblems = generalBranch->numberSubProblems(); for (int i = 0; i < numberProblems; i++) { double objectiveValue; double sumInfeasibilities; int numberUnsatisfied; generalBranch->state(objectiveValue, sumInfeasibilities, numberUnsatisfied, i); printf("node %d obj %g sumI %g numI %i rel depth %d\n", i, objectiveValue, sumInfeasibilities, numberUnsatisfied, generalBranch->subProblem(i)->depth_); } } if (generalBranch) { int numberProblems = generalBranch->numberSubProblems(); newNode->setBranchingObject(NULL); CbcNode * newNode2 = NULL; assert (numberProblems); int nProbMinus1 = numberProblems - 1; lockThread(); for (int i = 0; i < currentNumberCuts_; i++) { if (addedCuts_[i]) addedCuts_[i]->increment(nProbMinus1) ; } unlockThread(); for (int i = 0; i < numberProblems; i++) { double objectiveValue; double sumInfeasibilities; int numberUnsatisfied; generalBranch->state(objectiveValue, sumInfeasibilities, numberUnsatisfied, i); //printf("node %d obj %g sumI %g numI %i rel depth %d\n", // i,objectiveValue,sumInfeasibilities,numberUnsatisfied, // generalBranch->subProblem(i)->depth_); newNode2 = new CbcNode(); newNode2->setDepth(generalBranch->subProblem(i)->depth_ + currentDepth_); generalBranch->subProblem(i)->apply(solver_, 8); // basis newNode2->setNumberUnsatisfied(numberUnsatisfied); newNode2->setSumInfeasibilities(sumInfeasibilities); newNode2->setGuessedObjectiveValue(objectiveValue); newNode2->setObjectiveValue(objectiveValue); CbcOneGeneralBranchingObject * object = new CbcOneGeneralBranchingObject(this, generalBranch, i); newNode2->setBranchingObject(object); assert (lastws->fullBasis()); newNode2->createInfo(this, oldNode, lastws, lowerBefore, upperBefore, numberOldActiveCuts_, numberNewCuts_) ; newNode2->nodeInfo()->setNumberBranchesLeft(1); //newNode2->nodeInfo()->unsetParentBasedData(); if (i < nProbMinus1) { //OsiBranchingObject * object = oldNode->modifiableBranchingObject(); CbcNodeInfo * nodeInfo = oldNode->nodeInfo(); //object->incrementNumberBranchesLeft(); nodeInfo->incrementNumberPointingToThis(); newNode2->nodeInfo()->setNodeNumber(numberNodes2_); //newNode2->nodeInfo()->setNumberBranchesLeft(1); newNode2->initializeInfo(); numberNodes2_++; tree_->push(newNode2); } } delete newNode; newNode = newNode2; } else { if (lastws) { if (parallelMode() < -1) { lastws->fixFullBasis(); } else { if ((specialOptions_&8192) == 0) assert (lastws->fullBasis()); else lastws->fixFullBasis(); } } newNode->createInfo(this, oldNode, lastws, lowerBefore, upperBefore, numberOldActiveCuts_, numberNewCuts_) ; } } if (newNode->numberUnsatisfied()) { maximumDepthActual_ = CoinMax(maximumDepthActual_, newNode->depth()); // Number of branches is in oldNode! newNode->initializeInfo() ; if (cuts.sizeRowCuts()) { int initialNumber = ((threadMode_ & 1) == 0) ? 0 : 1000000000; lockThread(); newNode->nodeInfo()->addCuts(cuts, newNode->numberBranches(), //whichGenerator_, initialNumber) ; unlockThread(); } } } else { anyAction = -2 ; // Reset bound anyway (no harm if not odd) solverCharacteristics_->setMipBound(-COIN_DBL_MAX); } // May have slipped through i.e. anyAction == 0 and objective above cutoff // I think this will screw up cut reference counts if executed. // We executed addCuts just above. (lh) if ( anyAction >= 0 ) { assert (newNode); if (newNode->objectiveValue() >= getCutoff()) { anyAction = -2; // say bad after all // zap parent nodeInfo #ifdef COIN_DEVELOP printf("zapping3 CbcNodeInfo %x\n", reinterpret_cast(newNode->nodeInfo()->parent())); #endif if (newNode->nodeInfo()) newNode->nodeInfo()->nullParent(); } } stateOfSearch_ = 0; // outside chooseBranch #ifdef JJF_ZERO if (onOptimalPath) { const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ; if (!debugger) { printf("NOT On optimal path - choose\n") ; abort(); } else { printf("Still On optimal path - choose\n") ; if (anyAction == -2) { printf("anyAction 2!!\n"); abort(); } } } #endif return anyAction; } /* For advanced applications you may wish to modify the behavior of Cbc e.g. if the solver is a NLP solver then you may not have an exact optimum solution at each step. Information could be built into OsiSolverInterface but this is an alternative so that that interface does not have to be changed. If something similar is useful to enough solvers then it could be migrated. You can also pass in by using solver->setAuxiliaryInfo. You should do that if solver is odd - if solver is normal simplex then use this */ void CbcModel::passInSolverCharacteristics(OsiBabSolver * solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } // Generate an OsiBranchingInformation object OsiBranchingInformation CbcModel::usefulInformation() const { OsiBranchingInformation usefulInfo(solver_, normalSolver(), false); // and modify usefulInfo.solution_ = testSolution_; usefulInfo.integerTolerance_ = dblParam_[CbcIntegerTolerance] ; usefulInfo.hotstartSolution_ = hotstartSolution_; usefulInfo.numberSolutions_ = numberSolutions_; usefulInfo.numberBranchingSolutions_ = numberSolutions_ - numberHeuristicSolutions_; usefulInfo.depth_ = -1; return usefulInfo; } void CbcModel::setBestSolution(const double * solution, int numberColumns, double objectiveValue, bool checkSolution) { // May be odd discontinuities - so only check if asked if (checkSolution) { assert (numberColumns == solver_->getNumCols()); double * saveLower = CoinCopyOfArray(solver_->getColLower(), numberColumns); double * saveUpper = CoinCopyOfArray(solver_->getColUpper(), numberColumns); // Fix integers int numberAway = 0; for (int i = 0; i < numberColumns; i++) { if (solver_->isInteger(i)) { double value = solution[i]; double intValue = floor(value + 0.5); if (fabs(value - intValue) > 1.0e-4) numberAway++; solver_->setColLower(i, intValue); solver_->setColUpper(i, intValue); } } // Save basis CoinWarmStart * saveBasis = solver_->getWarmStart(); // Solve solver_->initialSolve(); char printBuffer[200]; if (numberAway) { sprintf(printBuffer, "Warning %d integer variables were more than 1.0e-4 away from integer", numberAway); messageHandler()->message(CBC_GENERAL, messages()) << printBuffer << CoinMessageEol ; } bool looksGood = solver_->isProvenOptimal(); if (looksGood) { double direction = solver_->getObjSense() ; double objValue = direction * solver_->getObjValue(); if (objValue > objectiveValue + 1.0e-8*(1.0 + fabs(objectiveValue))) { sprintf(printBuffer, "Given objective value %g, computed %g", objectiveValue, objValue); messageHandler()->message(CBC_GENERAL, messages()) << printBuffer << CoinMessageEol ; } // Use this as objective value and solution objectiveValue = objValue; solution = solver_->getColSolution(); // Save current basis CoinWarmStartBasis* ws = dynamic_cast (solver_->getWarmStart()) ; assert(ws); setBestSolutionBasis(*ws); delete ws; } // Restore basis solver_->setWarmStart(saveBasis); delete saveBasis; // Restore bounds solver_->setColLower(saveLower); delete [] saveLower; solver_->setColUpper(saveUpper); delete [] saveUpper; // Return if no good if (!looksGood) { messageHandler()->message(CBC_GENERAL, messages()) << "Error solution not saved as not feasible" << CoinMessageEol ; return; } else { // message sprintf(printBuffer, "Solution with objective value %g saved", objectiveValue); messageHandler()->message(CBC_GENERAL, messages()) << printBuffer << CoinMessageEol ; } } if (bestSolution_) saveExtraSolution(bestSolution_, bestObjective_); bestObjective_ = objectiveValue; // may be able to change cutoff now double cutoff = getCutoff(); double increment = getDblParam(CbcModel::CbcCutoffIncrement) ; if (cutoff > objectiveValue - increment) { cutoff = objectiveValue - increment ; setCutoff(cutoff) ; // change cutoff as constraint if wanted if (cutoffRowNumber_>=0) { if (solver_->getNumRows()>cutoffRowNumber_) { double offset; solver_->getDblParam(OsiObjOffset, offset); solver_->setRowUpper(cutoffRowNumber_,cutoff+offset); } } } int n = CoinMax(numberColumns, solver_->getNumCols()); delete [] bestSolution_; bestSolution_ = new double [n]; memset(bestSolution_, 0, n*sizeof(double)); memcpy(bestSolution_, solution, numberColumns*sizeof(double)); } /* Do heuristics at root. 0 - don't delete 1 - delete 2 - just delete - don't even use Parameter of 2 means what it says --- the routine will do nothing except delete the existing heuristics. A feasibility pump is always deleted, independent of the parameter value, as it's only useful at the root. The routine is called from branchAndBound to process the root node. But it will also be called when we've recursed into branchAndBound via smallBaB. */ void CbcModel::doHeuristicsAtRoot(int deleteHeuristicsAfterwards) { int numberColumns = getNumCols() ; double * newSolution = new double [numberColumns] ; int i; if (deleteHeuristicsAfterwards != 2) { /* If mode == 1, we delete and recreate here, then delete at the bottom. The create/delete part makes sense, but why delete the existing array? Seems like it should be preserved and restored. */ if (deleteHeuristicsAfterwards) { delete [] usedInSolution_; usedInSolution_ = new int [numberColumns]; CoinZeroN(usedInSolution_, numberColumns); } double heuristicValue = getCutoff() ; int found = -1; // no solution found CbcEventHandler *eventHandler = getEventHandler() ; if (eventHandler) eventHandler->setModel(this); /* currentPassNumber_ is described as `cut pass number'. Again, seems a bit cavalier to just change it. Whether this has any effect is determined by individual heuristics. Typically there will be a check at the front of the solution() routine that determines whether it will run or simply return. Root heuristics are characterised by node count of 0. In addition, currentPassNumber_ can be checked to to limit execution in terms of passes through cut generation / heuristic execution in solveWithCuts. */ currentPassNumber_ = 1; // so root heuristics will run /* A loop to run the heuristics. incrementUsed will mark entries in usedInSolution corresponding to variables that are nonzero in the solution. CBC_ROUNDING just identifies a message template, not the heuristic. */ // Modify based on size etc adjustHeuristics(); // See if already within allowable gap bool exitNow = false; for (i = 0; i < numberHeuristics_; i++) { if (heuristic_[i]->exitNow(bestObjective_)) exitNow = true; } if (!exitNow) { /** -1 first time otherwise number of solutions last time */ int lastSolutionCount = -1; while (lastSolutionCount) { int thisSolutionCount=0; #ifdef CBC_THREAD if ((threadMode_&4) != 0) { typedef struct { double solutionValue; CbcModel * model; double * solution; int foundSol; } argBundle; int chunk; if (!numberThreads_) chunk = numberHeuristics_; else chunk = numberThreads_; for (int iChunk = 0; iChunk < numberHeuristics_; iChunk += chunk) { argBundle * parameters = new argBundle [chunk]; for (int i = 0; i < chunk; i++) parameters[i].model = NULL; int nThisTime = CoinMin(numberHeuristics_ - iChunk, chunk); for (int i = iChunk; i < iChunk + nThisTime; i++) { // skip if can't run here if (!heuristic_[i]->shouldHeurRun(0)) continue; if (lastSolutionCount>0&& (heuristic_[i]->switches()&16)==0) continue; // no point parameters[i-iChunk].solutionValue = heuristicValue; // Don't want a strategy object CbcStrategy * saveStrategy = strategy_; strategy_ = NULL; CbcModel * newModel = new CbcModel(*this); strategy_ = saveStrategy; assert (!newModel->continuousSolver_); if (continuousSolver_) newModel->continuousSolver_ = continuousSolver_->clone(); else newModel->continuousSolver_ = solver_->clone(); parameters[i-iChunk].model = newModel; parameters[i-iChunk].solution = new double [numberColumns];; parameters[i-iChunk].foundSol = 0; //newModel->gutsOfCopy(*this,-1); for (int j = 0; j < numberHeuristics_; j++) delete newModel->heuristic_[j]; //newModel->heuristic_ = new CbcHeuristic * [1]; newModel->heuristic_[0] = heuristic_[i]->clone(); newModel->heuristic_[0]->setModel(newModel); newModel->heuristic_[0]->resetModel(newModel); newModel->numberHeuristics_ = 1; } void parallelHeuristics (int numberThreads, int sizeOfData, void * argBundle); parallelHeuristics(nThisTime, static_cast(sizeof(argBundle)), parameters); double cutoff = heuristicValue; for (int i = 0; i < chunk; i++) { if (parameters[i].model) { if (parameters[i].foundSol > 0 && parameters[i].solutionValue < heuristicValue) { memcpy(newSolution, parameters[i].solution, numberColumns*sizeof(double)); lastHeuristic_ = heuristic_[i+iChunk]; double value = parameters[i].solutionValue; setBestSolution(CBC_ROUNDING, value, newSolution) ; // Double check valid if (getCutoff() < cutoff) { cutoff = getCutoff(); heuristicValue = value; heuristic_[i+iChunk]->incrementNumberSolutionsFound(); incrementUsed(newSolution); // increment number of solutions so other heuristics can test thisSolutionCount++; numberHeuristicSolutions_++; found = i + iChunk ; } } if (heuristic_[i+iChunk]->exitNow(bestObjective_) || (parameters[i].model->heuristic(0)->switches()&(1024 + 2048)) == (1024 + 2048)) exitNow = true; delete [] parameters[i].solution; delete parameters[i].model; } } delete [] parameters; if (exitNow) break; } } else { #endif int whereFrom = 0; for (i = 0; i < numberHeuristics_; i++) { // skip if can't run here if (!heuristic_[i]->shouldHeurRun(whereFrom)) continue; if (lastSolutionCount>0&& (heuristic_[i]->switches()&16)==0) continue; // no point if (maximumSecondsReached()) { thisSolutionCount=-1000000; break; } // see if heuristic will do anything double saveValue = heuristicValue ; double before = getCurrentSeconds(); int ifSol = heuristic_[i]->solution(heuristicValue, newSolution); if (handler_->logLevel()>1) { char line[100]; sprintf(line,"Heuristic %s took %g seconds (%s)", heuristic_[i]->heuristicName(), getCurrentSeconds()-before, ifSol ? "good" : "no good"); handler_->message(CBC_GENERAL, messages_) << line << CoinMessageEol ; } if (ifSol > 0) { // better solution found double currentObjective = bestObjective_; CbcHeuristic * saveHeuristic = lastHeuristic_; lastHeuristic_ = heuristic_[i]; setBestSolution(CBC_ROUNDING, heuristicValue, newSolution) ; if (bestObjective_ < currentObjective) { thisSolutionCount++; heuristic_[i]->incrementNumberSolutionsFound(); found = i ; incrementUsed(newSolution); // increment number of solutions so other heuristics can test // numberSolutions_++; numberHeuristicSolutions_++; #ifdef CLP_INVESTIGATE printf("HEUR %s where %d C\n", lastHeuristic_->heuristicName(), whereFrom); #endif whereFrom |= 8; // say solution found if (heuristic_[i]->exitNow(bestObjective_) ||numberSolutions_>=getMaximumSolutions()) { thisSolutionCount=-1000000; break; } if (eventHandler) { if (!eventHandler->event(CbcEventHandler::heuristicSolution)) { eventHappened_ = true; // exit thisSolutionCount=-1000000; break; } } double testGap = CoinMax(dblParam_[CbcAllowableGap], CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_)) * dblParam_[CbcAllowableFractionGap]); if (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0 &&bestPossibleObjective_ < 1.0e30) { if (bestPossibleObjective_ < getCutoff()) stoppedOnGap_ = true ; //eventHappened_=true; // stop as fast as possible thisSolutionCount=-1000000; break; } reducedCostFix(); } else { // NOT better solution #ifdef CLP_INVESTIGATE printf("HEUR %s where %d REJECTED i==%d\n", heuristic_[i]->heuristicName(), whereFrom, i); #endif lastHeuristic_ = saveHeuristic; heuristicValue = saveValue ; } } else { heuristicValue = saveValue ; } if (eventHandler) { if (!eventHandler->event(CbcEventHandler::afterHeuristic)) { eventHappened_ = true; // exit thisSolutionCount=-1000000; break; } } } #ifdef CBC_THREAD } #endif if (thisSolutionCount<=0) break; lastSolutionCount=thisSolutionCount; } } currentPassNumber_ = 0; /* Did any of the heuristics turn up a new solution? Record it before we free the vector. tree_ will not necessarily be a CbcTreeLocal; the main model gets a CbcTree by default. CbcTreeLocal actually implements a k-neighbourhood search heuristic. This initialises it with a solution and creates the k-neighbourhood cut. */ if (found >= 0) { CbcTreeLocal * tree = dynamic_cast (tree_); if (tree) tree->passInSolution(bestSolution_, heuristicValue); if (eventHandler) { if (!eventHandler->event(CbcEventHandler::solution)) { eventHappened_ = true; // exit } } } } /* Cleanup. The feasibility pump heuristic is a root heuristic to look for an initial feasible solution. It's had its chance; remove it. For modes 1 and 2, all the heuristics are deleted. */ if (!deleteHeuristicsAfterwards) { for (i = 0; i < numberHeuristics_; i++) { // delete FPump CbcHeuristicFPump * pump = dynamic_cast (heuristic_[i]); if (pump && pump->feasibilityPumpOptions() < 1000000) { delete pump; numberHeuristics_ --; for (int j = i; j < numberHeuristics_; j++) heuristic_[j] = heuristic_[j+1]; } } } else { // delete all for (i = 0; i < numberHeuristics_; i++) delete heuristic_[i]; numberHeuristics_ = 0; delete [] heuristic_; heuristic_ = NULL; delete [] usedInSolution_; usedInSolution_ = NULL; } delete [] newSolution ; } // Zap integer information in problem (may leave object info) void CbcModel::zapIntegerInformation(bool leaveObjects) { numberIntegers_ = 0; delete [] integerVariable_; integerVariable_ = NULL; if (!leaveObjects && ownObjects_) { int i; for (i = 0; i < numberObjects_; i++) delete object_[i]; delete [] object_; numberObjects_ = 0; object_ = NULL; } } // Create C++ lines to get to current state void CbcModel::generateCpp( FILE * fp, int /*options*/) { // Do cut generators int i; for (i = 0; i < numberCutGenerators_; i++) { CglCutGenerator * generator = generator_[i]->generator(); std::string name = generator->generateCpp(fp); int howOften = generator_[i]->howOften(); int howOftenInSub = generator_[i]->howOftenInSub(); int whatDepth = generator_[i]->whatDepth(); int whatDepthInSub = generator_[i]->whatDepthInSub(); bool normal = generator_[i]->normal(); bool atSolution = generator_[i]->atSolution(); bool whenInfeasible = generator_[i]->whenInfeasible(); bool timing = generator_[i]->timing(); fprintf(fp, "3 cbcModel->addCutGenerator(&%s,%d,", name.c_str(), howOften); // change name name[0] = static_cast(toupper(name[0])); fprintf(fp, "\"%s\",%s,%s,%s,%d,%d,%d);\n", name.c_str(), normal ? "true" : "false", atSolution ? "true" : "false", whenInfeasible ? "true" : "false", howOftenInSub, whatDepth, whatDepthInSub); fprintf(fp, "3 cbcModel->cutGenerator(%d)->setTiming(%s);\n", i, timing ? "true" : "false"); fprintf(fp, "3 \n"); } for (i = 0; i < numberHeuristics_; i++) { CbcHeuristic * heuristic = heuristic_[i]; heuristic->generateCpp(fp); fprintf(fp, "3 \n"); } if (nodeCompare_) nodeCompare_->generateCpp(fp); tree_->generateCpp(fp); CbcModel defaultModel; CbcModel * other = &defaultModel; int iValue1, iValue2; double dValue1, dValue2; iValue1 = this->getMaximumNodes(); iValue2 = other->getMaximumNodes(); fprintf(fp, "%d int save_getMaximumNodes = cbcModel->getMaximumNodes();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setMaximumNodes(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setMaximumNodes(save_getMaximumNodes);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->getMaximumSolutions(); iValue2 = other->getMaximumSolutions(); fprintf(fp, "%d int save_getMaximumSolutions = cbcModel->getMaximumSolutions();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setMaximumSolutions(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setMaximumSolutions(save_getMaximumSolutions);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->numberStrong(); iValue2 = other->numberStrong(); fprintf(fp, "%d int save_numberStrong = cbcModel->numberStrong();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setNumberStrong(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setNumberStrong(save_numberStrong);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->numberBeforeTrust(); iValue2 = other->numberBeforeTrust(); fprintf(fp, "%d int save_numberBeforeTrust = cbcModel->numberBeforeTrust();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setNumberBeforeTrust(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setNumberBeforeTrust(save_numberBeforeTrust);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->numberPenalties(); iValue2 = other->numberPenalties(); fprintf(fp, "%d int save_numberPenalties = cbcModel->numberPenalties();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setNumberPenalties(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setNumberPenalties(save_numberPenalties);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->howOftenGlobalScan(); iValue2 = other->howOftenGlobalScan(); fprintf(fp, "%d int save_howOftenGlobalScan = cbcModel->howOftenGlobalScan();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setHowOftenGlobalScan(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setHowOftenGlobalScan(save_howOftenGlobalScan);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->printFrequency(); iValue2 = other->printFrequency(); fprintf(fp, "%d int save_printFrequency = cbcModel->printFrequency();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setPrintFrequency(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setPrintFrequency(save_printFrequency);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->getPrintingMode(); iValue2 = other->getPrintingMode(); fprintf(fp, "%d int save_printingMode = cbcModel->getPrintingMode();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setPrintingMode(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setPrintingMode(save_printingMode);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->searchStrategy(); iValue2 = other->searchStrategy(); fprintf(fp, "%d int save_searchStrategy = cbcModel->searchStrategy();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setSearchStrategy(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setSearchStrategy(save_searchStrategy);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->specialOptions(); iValue2 = other->specialOptions(); fprintf(fp, "%d int save_cbcSpecialOptions = cbcModel->specialOptions();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setSpecialOptions(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setSpecialOptions(save_cbcSpecialOptions);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->messageHandler()->logLevel(); iValue2 = other->messageHandler()->logLevel(); fprintf(fp, "%d int save_cbcMessageLevel = cbcModel->messageHandler()->logLevel();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->messageHandler()->setLogLevel(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->messageHandler()->setLogLevel(save_cbcMessageLevel);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->getMaximumCutPassesAtRoot(); iValue2 = other->getMaximumCutPassesAtRoot(); fprintf(fp, "%d int save_getMaximumCutPassesAtRoot = cbcModel->getMaximumCutPassesAtRoot();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setMaximumCutPassesAtRoot(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setMaximumCutPassesAtRoot(save_getMaximumCutPassesAtRoot);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->getMaximumCutPasses(); iValue2 = other->getMaximumCutPasses(); fprintf(fp, "%d int save_getMaximumCutPasses = cbcModel->getMaximumCutPasses();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setMaximumCutPasses(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setMaximumCutPasses(save_getMaximumCutPasses);\n", iValue1 == iValue2 ? 7 : 6); iValue1 = this->getPreferredWay(); iValue2 = other->getPreferredWay(); fprintf(fp, "%d int save_getPreferredWay = cbcModel->getPreferredWay();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setPreferredWay(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d cbcModel->setPreferredWay(save_getPreferredWay);\n", iValue1 == iValue2 ? 7 : 6); dValue1 = this->getMinimumDrop(); dValue2 = other->getMinimumDrop(); fprintf(fp, "%d double save_getMinimumDrop = cbcModel->getMinimumDrop();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setMinimumDrop(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d cbcModel->setMinimumDrop(save_getMinimumDrop);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->getIntegerTolerance(); dValue2 = other->getIntegerTolerance(); fprintf(fp, "%d double save_getIntegerTolerance = cbcModel->getIntegerTolerance();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setIntegerTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d cbcModel->setIntegerTolerance(save_getIntegerTolerance);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->getInfeasibilityWeight(); dValue2 = other->getInfeasibilityWeight(); fprintf(fp, "%d double save_getInfeasibilityWeight = cbcModel->getInfeasibilityWeight();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setInfeasibilityWeight(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d cbcModel->setInfeasibilityWeight(save_getInfeasibilityWeight);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->getCutoffIncrement(); dValue2 = other->getCutoffIncrement(); fprintf(fp, "%d double save_getCutoffIncrement = cbcModel->getCutoffIncrement();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setCutoffIncrement(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d cbcModel->setCutoffIncrement(save_getCutoffIncrement);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->getAllowableGap(); dValue2 = other->getAllowableGap(); fprintf(fp, "%d double save_getAllowableGap = cbcModel->getAllowableGap();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setAllowableGap(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d cbcModel->setAllowableGap(save_getAllowableGap);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->getAllowableFractionGap(); dValue2 = other->getAllowableFractionGap(); fprintf(fp, "%d double save_getAllowableFractionGap = cbcModel->getAllowableFractionGap();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setAllowableFractionGap(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d cbcModel->setAllowableFractionGap(save_getAllowableFractionGap);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->getMaximumSeconds(); dValue2 = other->getMaximumSeconds(); fprintf(fp, "%d double save_cbcMaximumSeconds = cbcModel->getMaximumSeconds();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d cbcModel->setMaximumSeconds(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d cbcModel->setMaximumSeconds(save_cbcMaximumSeconds);\n", dValue1 == dValue2 ? 7 : 6); } // So we can use osiObject or CbcObject during transition void getIntegerInformation(const OsiObject * object, double & originalLower, double & originalUpper) { const CbcSimpleInteger * integerObject = dynamic_cast (object); if (integerObject) { // get original bounds originalLower = integerObject->originalLowerBound(); originalUpper = integerObject->originalUpperBound(); } else { const OsiSimpleInteger * integerObject = dynamic_cast (object); assert (integerObject); // get original bounds originalLower = integerObject->originalLowerBound(); originalUpper = integerObject->originalUpperBound(); } } // Set original columns as created by preprocessing void CbcModel::setOriginalColumns(const int * originalColumns,int numberGood) { int numberColumns = getNumCols(); delete [] originalColumns_; originalColumns_ = new int [numberColumns]; int numberCopy=CoinMin(numberColumns,numberGood); memcpy(originalColumns_,originalColumns,numberCopy*sizeof(int)); for (int i=numberCopy;iclone(); } /* Set the cut modifier method */ void CbcModel::setCutModifier(CbcCutModifier & modifier) { delete cutModifier_; cutModifier_ = modifier.clone(); } /* Do one node - broken out for clarity? also for parallel (when baseModel!=this) Returns 1 if solution found node NULL on return if no branches left newNode NULL if no new node created */ int CbcModel::doOneNode(CbcModel * baseModel, CbcNode * & node, CbcNode * & newNode) { int foundSolution = 0; int saveNumberCutGenerators=numberCutGenerators_; if ((moreSpecialOptions_&33554432)!=0 && (specialOptions_&2048)==0) { if (node&&(node->depth()==-2||node->depth()==4)) numberCutGenerators_=0; // so can dive and branch } currentNode_ = node; // so can be accessed elsewhere double bestObjective = bestObjective_; numberUpdateItems_ = 0; // Say not on optimal path bool onOptimalPath = false; # ifdef CHECK_NODE printf("Node %x popped from tree - %d left, %d count\n", node, node->nodeInfo()->numberBranchesLeft(), node->nodeInfo()->numberPointingToThis()) ; printf("\tdepth = %d, z = %g, unsat = %d\n", //var = %d.\n", node->depth(), node->objectiveValue(), node->numberUnsatisfied()); //node->columnNumber()) ; # endif /* Rebuild the subproblem for this node: Call addCuts() to adjust the model to recreate the subproblem for this node (set proper variable bounds, add cuts, create a basis). This may result in the problem being fathomed by bound or infeasibility. Returns 1 if node is fathomed. Execute the current arm of the branch: If the problem survives, save the resulting variable bounds and call branch() to modify variable bounds according to the current arm of the branching object. If we're processing the final arm of the branching object, flag the node for removal from the live set. */ /* Used to generate bound edits for CbcPartialNodeInfo. */ int numberColumns = getNumCols() ; double * lowerBefore = new double [numberColumns] ; double * upperBefore = new double [numberColumns] ; if (parallelMode() >= 0) newNode = NULL ; else newNode = new CbcNode(); bool feasible = true; CoinWarmStartBasis *lastws = new CoinWarmStartBasis(); lockThread(); // point to genuine ones //int save1 = maximumNumberCuts_; //maximumNumberCuts_ = baseModel->maximumNumberCuts_; //addedCuts_ = baseModel->addedCuts_; if (parallelMode() >= 0) { maximumDepth_ = baseModel->maximumDepth_; walkback_ = baseModel->walkback_; lastNodeInfo_ = baseModel->lastNodeInfo_; lastNumberCuts_ = baseModel->lastNumberCuts_; lastCut_ = baseModel->lastCut_; lastNumberCuts2_ = baseModel->lastNumberCuts2_; } int save2 = maximumDepth_; int retCode = addCuts(node, lastws, numberFixedNow_ > numberFixedAtRoot_); //if (save1maximumNumberCuts_ = maximumNumberCuts_; //baseModel->addedCuts_ = addedCuts_; //} if (parallelMode() >= 0 && save2 < maximumDepth_) { // increased baseModel->maximumDepth_ = maximumDepth_; baseModel->walkback_ = walkback_; baseModel->lastNodeInfo_ = lastNodeInfo_; baseModel->lastNumberCuts_ = lastNumberCuts_; baseModel->lastCut_ = lastCut_; baseModel->lastNumberCuts2_ = lastNumberCuts2_; } int branchesLeft = 0; if (!retCode) { unlockThread(); int i ; const double * lower = getColLower() ; const double * upper = getColUpper() ; for (i = 0 ; i < numberColumns ; i++) { lowerBefore[i] = lower[i] ; upperBefore[i] = upper[i] ; } if ((solverCharacteristics_->extraCharacteristics()&2) != 0) { solverCharacteristics_->setBeforeLower(lowerBefore); solverCharacteristics_->setBeforeUpper(upperBefore); } lockThread(); assert (node->objectiveValue() < 1.0e200); if (messageHandler()->logLevel() > 2) node->modifiableBranchingObject()->print(); if (branchingMethod_ && branchingMethod_->chooseMethod()) { branchesLeft = node->branch(solver_); // new way } else { // old way so need to cheat OsiBranchingObject * branch2 = node->modifiableBranchingObject(); #ifndef NDEBUG CbcBranchingObject * branch = dynamic_cast (branch2) ; assert (branch); #else CbcBranchingObject * branch = static_cast (branch2) ; #endif #if 1 branch->setModel(this); branchesLeft = node->branch(NULL); // old way #else branchesLeft = node->branch(solver_); #endif if (parallelMode() >= 0) branch->setModel(baseModel); } assert (branchesLeft == node->nodeInfo()->numberBranchesLeft()); if (parallelMode() > 0) { assert(masterThread_); assert (node->nodeInfo()); node->nodeInfo()->increment() ; unlockThread(); } if ((specialOptions_&1) != 0) { /* This doesn't work as intended --- getRowCutDebugger will return null unless the current feasible solution region includes the optimal solution that RowCutDebugger knows. There's no way to tell inactive from off the optimal path. */ const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ; if (debugger) { onOptimalPath = true; printf("On optimal path\n") ; } } /* Reoptimize, possibly generating cuts and/or using heuristics to find solutions. Cut reference counts are unaffected unless we lose feasibility, in which case solveWithCuts() will make the adjustment. */ phase_ = 2; OsiCuts cuts ; int saveNumber = numberIterations_; if (solverCharacteristics_->solutionAddsCuts()) { int returnCode = resolve(node ? node->nodeInfo() : NULL, 1); feasible = returnCode != 0; if (feasible) { int iObject ; int preferredWay ; int numberUnsatisfied = 0 ; memcpy(currentSolution_, solver_->getColSolution(), numberColumns*sizeof(double)) ; // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); for (iObject = 0 ; iObject < numberObjects_ ; iObject++) { double infeasibility = object_[iObject]->infeasibility(&usefulInfo, preferredWay) ; if (infeasibility ) numberUnsatisfied++ ; } if (returnCode > 0) { if (numberUnsatisfied) { feasible = solveWithCuts(cuts, maximumCutPasses_, node); } else { // may generate cuts and turn the solution //to an infeasible one feasible = solveWithCuts(cuts, 1, node); } } // check extra info on feasibility if (!solverCharacteristics_->mipFeasible()) { feasible = false; solverCharacteristics_->setMipBound(-COIN_DBL_MAX); } } } else { // normal if (false) { const double * lower = solver_->getColLower(); const double * upper = solver_->getColUpper(); printf("STATE before solve\n"); for (int i = 0; i < 100; i++) if (lower[i] || !upper[i]) printf("%d fixed to %g\n", i, lower[i]); } #ifdef COIN_HAS_CLP bool fathomDone = false; OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if ((clpSolver || (specialOptions_&16384) != 0) && fastNodeDepth_ < -1 && (specialOptions_&2048) == 0) { #define FATHOM_BIAS -2 if (numberNodes_ == 1) { int numberNodesBeforeFathom = 500; if (fastNodeDepth_ < -1000001) { numberNodesBeforeFathom = (-fastNodeDepth_) / 1000000; numberNodesBeforeFathom = 250 * numberNodesBeforeFathom; } #ifdef COIN_DEVELOP int fastNodeDepth1 = -fastNodeDepth_ % 1000000; printf("initial depth %d after %d nodes\n", FATHOM_BIAS + fastNodeDepth1, numberNodesBeforeFathom); #endif } //#endif ClpNodeStuff stuff; ClpNodeStuff * info = &stuff; /* Used to generate bound edits for CbcPartialNodeInfo. */ //double * lowerBefore = NULL; //double * upperBefore = NULL; int fastNodeDepth1 = -fastNodeDepth_ % 1000000; int numberNodesBeforeFathom = 500; if (fastNodeDepth_ < -1000001) { numberNodesBeforeFathom = (-fastNodeDepth_) / 1000000; numberNodesBeforeFathom = 100 * numberNodesBeforeFathom; } int go_fathom = FATHOM_BIAS + fastNodeDepth1; if ((specialOptions_&16384) != 0) numberNodesBeforeFathom = 0; if (node->depth() >= go_fathom && (specialOptions_&2048) == 0 //if (node->depth()>=FATHOM_BIAS-fastNodeDepth_&&!parentModel_ && numberNodes_ >= numberNodesBeforeFathom && !hotstartSolution_) { #ifndef COIN_HAS_CPX specialOptions_ &= ~16384; #endif if ((specialOptions_&16384) == 0) { info->integerTolerance_ = getIntegerTolerance(); info->integerIncrement_ = getCutoffIncrement(); info->numberBeforeTrust_ = numberBeforeTrust_; info->stateOfSearch_ = 1; if (numberSolutions_ > 0) { info->stateOfSearch_ = 3; } if (numberNodes_ > 2*numberObjects_ + 1000) { info->stateOfSearch_ = 4; } // Compute "small" change in branch int nBranches = intParam_[CbcNumberBranches]; if (nBranches) { double average = dblParam_[CbcSumChange] / static_cast(nBranches); info->smallChange_ = CoinMax(average * 1.0e-5, dblParam_[CbcSmallestChange]); info->smallChange_ = CoinMax(info->smallChange_, 1.0e-8); } else { info->smallChange_ = 1.0e-8; } double * down = new double[numberIntegers_]; double * up = new double[numberIntegers_]; int * priority = new int[numberIntegers_]; int * numberDown = new int[numberIntegers_]; int * numberUp = new int[numberIntegers_]; int * numberDownInfeasible = new int[numberIntegers_]; int * numberUpInfeasible = new int[numberIntegers_]; fillPseudoCosts(down, up, priority, numberDown, numberUp, numberDownInfeasible, numberUpInfeasible); // See if all priorities same bool allSame = true; int kPriority = priority[0]; for (int i = 1; i < numberIntegers_; i++) { if (kPriority != priority[i]) { allSame = false; break; } } ClpSimplex * simplex = clpSolver->getModelPtr(); if (allSame && false) { // change priorities on general const double * lower = simplex->columnLower(); const double * upper = simplex->columnUpper(); for (int i = 0; i < numberIntegers_; i++) { int iColumn = integerVariable_[i]; if (upper[iColumn] > lower[iColumn] + 1.1) priority[i] = kPriority + 1; } } info->fillPseudoCosts(down, up, priority, numberDown, numberUp, numberDownInfeasible, numberUpInfeasible, numberIntegers_); info->presolveType_ = 1; // for reduced costs and duals info->solverOptions_ |= 7; delete [] down; delete [] up; delete [] numberDown; delete [] priority; delete [] numberUp; delete [] numberDownInfeasible; delete [] numberUpInfeasible; bool takeHint; OsiHintStrength strength; solver_->getHintParam(OsiDoReducePrint, takeHint, strength); //printf("mod cutoff %g solver %g offset %g\n", // getCutoff(),simplex->dualObjectiveLimit(),simplex->objectiveOffset()); int saveLevel = simplex->logLevel(); if (strength != OsiHintIgnore && takeHint && saveLevel == 1) simplex->setLogLevel(0); clpSolver->setBasis(); int perturbation = simplex->perturbation(); if ((specialOptions_&131072) != 0) { //assert (perturbation == 100); simplex->setPerturbation(50); } int saveMoreOptions = simplex->moreSpecialOptions(); int flags = (moreSpecialOptions_>>18)&3; simplex->setMoreSpecialOptions(saveMoreOptions|flags<<11); #ifndef NO_FATHOM_PRINT info->startingDepth_ = node->depth(); info->nodeCalled_ = numberNodes_; info->handler_ = handler_; #endif feasible = simplex->fathom(info) != 0; simplex->setMoreSpecialOptions(saveMoreOptions); simplex->setPerturbation(perturbation); numberExtraNodes_ += info->numberNodesExplored_; numberExtraIterations_ += info->numberIterations_; char general[200]; int fathomStatus=info->nNodes_; if (feasible) fathomStatus=1; sprintf(general, "fathom took %d nodes, %d iterations - status %d", info->numberNodesExplored_, info->numberIterations_,fathomStatus); messageHandler()->message(CBC_FPUMP2, messages()) << general << CoinMessageEol ; if (info->numberNodesExplored_ > 10000 /* && !feasible */ && (moreSpecialOptions_&524288) == 0 && info->nNodes_>=0) { fastNodeDepth_ --; #ifndef NO_FATHOM_PRINT if ((moreSpecialOptions_&262144) != 0) handler_->message(CBC_FATHOM_CHANGE, messages_) << FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol ; #endif #ifdef CLP_INVESTIGATE printf(">10000 - depth now %d so at depth >= %d\n", fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_); #endif } if (info->nNodes_ < 0) { // we gave up //abort(); fastNodeDepth_ -= 3; #ifndef NO_FATHOM_PRINT if ((moreSpecialOptions_&262144) != 0) handler_->message(CBC_FATHOM_CHANGE, messages_) << FATHOM_BIAS - fastNodeDepth_ << CoinMessageEol ; #endif #ifdef CLP_INVESTIGATE printf("fastNodeDepth now %d - so at depth >= %d\n", fastNodeDepth_, FATHOM_BIAS - fastNodeDepth_); #endif if (feasible) { // Save bounds round bestSolution //double * saveLower = CoinCopyOfArray(solver_->getColLower(), // numberColumns); //double * saveUpper = CoinCopyOfArray(solver_->getColUpper(), // numberColumns); clpSolver->setWarmStart(NULL); // try and do solution double value = simplex->objectiveValue() * simplex->optimizationDirection(); double * newSolution = CoinCopyOfArray(simplex->primalColumnSolution(), numberColumns); setBestSolution(CBC_STRONGSOL, value, newSolution) ; delete [] newSolution; //solver_->setColLower(saveLower); //solver_->setColUpper(saveUpper); //delete [] saveLower; //delete [] saveUpper; } // say feasible so will redo node feasible = true; } else { if (feasible) { clpSolver->setWarmStart(NULL); // try and do solution double value = simplex->objectiveValue() * simplex->optimizationDirection(); double * newSolution = CoinCopyOfArray(simplex->primalColumnSolution(), numberColumns); setBestSolution(CBC_STRONGSOL, value, newSolution) ; delete [] newSolution; } // update pseudo costs double smallest = 1.0e50; double largest = -1.0; for (int i = 0; i < numberIntegers_; i++) { CbcSimpleIntegerDynamicPseudoCost * obj = dynamic_cast (object_[i]) ; if (!obj) continue; assert (obj->columnNumber() == integerVariable_[i]); if (info->numberUp_[i] > 0) { if (info->downPseudo_[i] > largest) largest = info->downPseudo_[i]; if (info->downPseudo_[i] < smallest) smallest = info->downPseudo_[i]; if (info->upPseudo_[i] > largest) largest = info->upPseudo_[i]; if (info->upPseudo_[i] < smallest) smallest = info->upPseudo_[i]; obj->updateAfterMini(info->numberDown_[i], info->numberDownInfeasible_[i], info->downPseudo_[i], info->numberUp_[i], info->numberUpInfeasible_[i], info->upPseudo_[i]); } } //printf("range of costs %g to %g\n",smallest,largest); // If value of objective borderline then may not be feasible double value = simplex->objectiveValue() * simplex->optimizationDirection(); if (value - getCutoff() < -1.0e-1) fathomDone = true; } simplex->setLogLevel(saveLevel); #ifdef COIN_HAS_CPX } else { // try cplex OsiCpxSolverInterface cpxSolver; double direction = clpSolver->getObjSense(); cpxSolver.setObjSense(direction); // load up cplex const CoinPackedMatrix * matrix = clpSolver->getMatrixByCol(); const double * rowLower = clpSolver->getRowLower(); const double * rowUpper = clpSolver->getRowUpper(); const double * columnLower = clpSolver->getColLower(); const double * columnUpper = clpSolver->getColUpper(); const double * objective = clpSolver->getObjCoefficients(); cpxSolver.loadProblem(*matrix, columnLower, columnUpper, objective, rowLower, rowUpper); double * setSol = new double [numberIntegers_]; int * setVar = new int [numberIntegers_]; // cplex doesn't know about objective offset double offset = clpSolver->getModelPtr()->objectiveOffset(); for (int i = 0; i < numberIntegers_; i++) { int iColumn = integerVariable_[i]; cpxSolver.setInteger(iColumn); if (bestSolution_) { setSol[i] = bestSolution_[iColumn]; setVar[i] = iColumn; } } CPXENVptr env = cpxSolver.getEnvironmentPtr(); CPXLPptr lpPtr = cpxSolver.getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL); cpxSolver.switchToMIP(); if (bestSolution_) { CPXcopymipstart(env, lpPtr, numberIntegers_, setVar, setSol); } if (getCutoff() < 1.0e50) { double useCutoff = getCutoff() + offset; if (bestObjective_ < 1.0e50) useCutoff = bestObjective_ + offset + 1.0e-7; cpxSolver.setDblParam(OsiDualObjectiveLimit, useCutoff* direction); if ( direction > 0.0 ) CPXsetdblparam( env, CPX_PARAM_CUTUP, useCutoff ) ; // min else CPXsetdblparam( env, CPX_PARAM_CUTLO, useCutoff ) ; // max } CPXsetdblparam(env, CPX_PARAM_EPGAP, dblParam_[CbcAllowableFractionGap]); delete [] setSol; delete [] setVar; if (offset) { char printBuffer[200]; sprintf(printBuffer, "Add %g to all Cplex messages for true objective", -offset); messageHandler()->message(CBC_GENERAL, messages()) << printBuffer << CoinMessageEol ; cpxSolver.setDblParam(OsiObjOffset, offset); } cpxSolver.branchAndBound(); numberExtraNodes_ += CPXgetnodecnt(env, lpPtr); numberExtraIterations_ += CPXgetmipitcnt(env, lpPtr); double value = cpxSolver.getObjValue() * direction; if (cpxSolver.isProvenOptimal() && value <= getCutoff()) { feasible = true; clpSolver->setWarmStart(NULL); // try and do solution double * newSolution = CoinCopyOfArray(cpxSolver.getColSolution(), getNumCols()); setBestSolution(CBC_STRONGSOL, value, newSolution) ; delete [] newSolution; fathomDone = true; } else { feasible = false; } #endif } } } if (feasible) { //int numberPasses = doCutsNow(1) ? maximumCutPasses_ : 0; int numberPasses = /*doCutsNow(1) ?*/ maximumCutPasses_ /*: 0*/; feasible = solveWithCuts(cuts, numberPasses, node); if (fathomDone) assert (feasible); } #else feasible = solveWithCuts(cuts, maximumCutPasses_, node); #endif } if ((specialOptions_&1) != 0 && onOptimalPath) { if(solver_->getRowCutDebuggerAlways()->optimalValue()getRowCutDebugger() || !feasible) { // dj fix did something??? solver_->writeMpsNative("infeas2.mps", NULL, NULL, 2); solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_); #ifndef NDEBUG const OsiRowCutDebugger * debugger = solver_->getRowCutDebugger() ; #endif assert (debugger) ; int numberRows0=continuousSolver_->getNumRows(); int numberRows=solver_->getNumRows(); const CoinPackedMatrix * rowCopy = solver_->getMatrixByRow(); const int * rowLength = rowCopy->getVectorLengths(); const double * elements = rowCopy->getElements(); const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const double * rowLower = solver_->getRowLower(); const double * rowUpper = solver_->getRowUpper(); for (int iRow=numberRows0;iRowinvalidCut(rc)); } assert (feasible); } } } if (statistics_) { assert (numberNodes2_); assert (statistics_[numberNodes2_-1]); assert (statistics_[numberNodes2_-1]->node() == numberNodes2_ - 1); statistics_[numberNodes2_-1]->endOfBranch(numberIterations_ - saveNumber, feasible ? solver_->getObjValue() : COIN_DBL_MAX); } /* Are we still feasible? If so, create a node and do the work to attach a branching object, reoptimising as needed if chooseBranch() identifies monotone objects. Finally, attach a partial nodeInfo object and store away any cuts that we created back in solveWithCuts. addCuts() will initialise the reference counts for these new cuts. This next test can be problematic if we've discovered an alternate equivalent answer and subsequently fathom the solution known to the row cut debugger due to bounds. */ if (onOptimalPath) { bool objLim = solver_->isDualObjectiveLimitReached() ; if (!feasible && !objLim) { if(solver_->getRowCutDebuggerAlways()->optimalValue()getRowCutDebuggerAlways()->printOptimalSolution(*solver_); solver_->writeMpsNative("infeas.mps", NULL, NULL, 2); CoinWarmStartBasis *slack = dynamic_cast(solver_->getEmptyWarmStart()) ; solver_->setWarmStart(slack); delete slack ; solver_->setHintParam(OsiDoReducePrint, false, OsiHintDo, 0) ; solver_->initialSolve(); assert (!solver_->isProvenOptimal()); assert (feasible || objLim); } } } bool checkingNode = false; if (feasible) { #ifdef FUNNY_BRANCHING2 // Far too clever if ((numberThreads_ == -10 || true) && node->numberBranches() == 2) { // see if any parent branches redundant // Look at state of "node" CbcNodeInfo * nodeInfo = node->nodeInfo(); if (nodeInfo) { // See if any branched variables off bounds const double * dj = solver_->getReducedCost(); const double * lower = solver_->getColLower(); const double * upper = solver_->getColUpper(); const double * solution = solver_->getColSolution(); int numberColumns = solver_->getNumCols(); double * currentLower = CoinCopyOfArray(lower, numberColumns); double * currentUpper = CoinCopyOfArray(upper, numberColumns); char * touched = new char[numberColumns]; memset(touched, 0, numberColumns); double direction = solver_->getObjSense() ; bool canDelete = nodeInfo->numberBranchesLeft() > 0; //int numberBounds = nodeInfo->numberChangedBounds(); //const int * which = nodeInfo->variables(); //const double * bounds = nodeInfo->newBounds(); const OsiBranchingObject * obj = node->branchingObject(); const CbcIntegerBranchingObject * objectI = dynamic_cast (obj); if (objectI) { const CbcSimpleInteger * object1 = dynamic_cast (objectI->object()); int iColumn1 = -1; int way1 = 0; const double * bounds1 = NULL; bool zeroOne1 = false; if (object1) { iColumn1 = object1->columnNumber(); double originalLower1 = object1->originalLowerBound(); double originalUpper1 = object1->originalUpperBound(); // Unset all bounds from parents CbcPartialNodeInfo * partial = dynamic_cast(nodeInfo); touched[iColumn1] = 1; if (partial) { /* maybe don't do if obj hasn't changed as then you might get loop at present just 0-1 as need to know original bound */ int n = partial->numberChangedBounds(); const int * which = partial->variables(); const double * values = partial->newBounds(); for (int i = 0; i < n; i++) { int variable = which[i]; int k = variable & 0x3fffffff; assert (k != iColumn1); if (!touched[k]) { if ((variable&0x80000000) == 0) { // lower bound changing assert (currentLower[k] == 1.0); currentLower[k] = 0.0; } else { // upper bound changing assert (currentUpper[k] == 0.0); currentUpper[k] = 1.0; } } } } zeroOne1 = originalLower1 == 0.0 && originalUpper1 == 1.0; way1 = objectI->way(); assert (way1 == -1 || way1 == 1); int kWay = way1; //way1 = -way1; // what last branch did // work out using bounds if (objectI->downBounds()[1] >= upper[iColumn1] && objectI->downBounds()[0] <= lower[iColumn1]) way1 = -1; else way1 = 1; assert (kWay == -way1); if (way1 < 0) { // must have been down branch bounds1 = objectI->downBounds(); } else { // must have been up branch bounds1 = objectI->upBounds(); } // double check bounds assert (bounds1[0] <= lower[iColumn1] && bounds1[1] >= upper[iColumn1]); } bool inBetween = false; #ifdef CBC_PRINT2 printf("%d (way %d) with down bounds %g, %g and up bounds %g, %g current bounds %g, %g solution %g dj %g (bleft %d)\n", iColumn1, way1, objectI->downBounds()[0], objectI->downBounds()[1], objectI->upBounds()[0], objectI->upBounds()[1], lower[iColumn1], upper[iColumn1], solution[iColumn1], dj[iColumn1], nodeInfo->numberBranchesLeft()); #endif while (nodeInfo->parent()) { nodeInfo = nodeInfo->parent(); CbcNode * nodeLook = nodeInfo->mutableOwner(); if (!nodeLook || nodeLook->objectiveValue() == 0.5*COIN_DBL_MAX) continue; OsiBranchingObject * obj = nodeLook->modifiableBranchingObject(); CbcIntegerBranchingObject * objectI = dynamic_cast (obj); //const OsiObject * object2a = obj->originalObject(); //assert (object2a); const CbcSimpleInteger * object2 = dynamic_cast (objectI->object()); if (nodeInfo->numberBranchesLeft() && object2) { int iColumn2 = object2->columnNumber(); double originalLower = object2->originalLowerBound(); double originalUpper = object2->originalUpperBound(); bool zeroOne2 = originalLower == 0.0 && originalUpper == 1.0; zeroOne1 = true; // temp double newUpper = originalUpper; double newLower = originalLower; //double value = solution[iColumn2]; double djValue = dj[iColumn2] * direction; int way = objectI->way(); assert (way == -1 || way == 1); way = -way; // what last branch did #ifdef CBC_PRINT2 printf("%d (way %d) with down bounds %g, %g and up bounds %g, %g current bounds %g, %g solution %g dj %g (bleft %d)\n", iColumn2, way, objectI->downBounds()[0], objectI->downBounds()[1], objectI->upBounds()[0], objectI->upBounds()[1], lower[iColumn2], upper[iColumn2], solution[iColumn2], djValue, nodeInfo->numberBranchesLeft()); #endif /*if (objectI->downBounds()[0]==0&&objectI->downBounds()[1]==1&& objectI->upBounds()[0]==0&&objectI->upBounds()[1]==1) assert(lower[iColumn2]downBounds(); if (djValue > 1.0e-3 || solution[iColumn2] < upper[iColumn2] - 1.0e-5) { if (canDelete) { //nRedundantDown++; #ifndef JJF_ONE COIN_DETAIL_PRINT(printf("%d redundant branch down with bounds %g, %g current upper %g solution %g dj %g\n", iColumn2, bounds[0], bounds[1], upper[iColumn2], solution[iColumn2], djValue)); #endif if (bounds[0] == bounds[1] || zeroOne2 || (bounds[0] == lower[iColumn2] && false)) { { // get rid of node as far as branching nodeLook->setObjectiveValue(0.5*COIN_DBL_MAX); objectI->deactivate(); } previousBounds(node, nodeInfo, iColumn2, newLower, newUpper, 2); solver_->setColUpper(iColumn2, newUpper); assert (newLower == lower[iColumn2]); } else { COIN_DETAIL_PRINT(printf("SKipping\n")); } } else if (iColumn1 >= 0 && iColumn1 != iColumn2 && (!inBetween || true) && zeroOne1 && zeroOne2 && false) { #ifndef JJF_ONE if (true) { // add in bounds newLower = bounds1[0]; newUpper = bounds1[1]; COIN_DETAIL_PRINT(printf("setting bounds of %g and %g (column %d) on other branch for column %d\n", newLower, newUpper, iColumn1, iColumn2)); int infeasible = objectI->applyExtraBounds(iColumn1, newLower, newUpper, objectI->way()); if (infeasible) { COIN_DETAIL_PRINT(printf("infeasa!\n")); // get rid of node as far as branching nodeLook->setObjectiveValue(0.5*COIN_DBL_MAX); } } #endif } //break; } else { inBetween = true; } } else { // must have been up branch const double * bounds = objectI->upBounds(); if (djValue < -1.0e-3 || solution[iColumn2] > lower[iColumn2] + 1.0e-5) { if (canDelete) { //nRedundantUp++; #ifndef JJF_ONE COIN_DETAIL_PRINT(printf("%d redundant branch up with bounds %g, %g current lower %g solution %g dj %g\n", iColumn2, bounds[0], bounds[1], lower[iColumn2], solution[iColumn2], djValue)); #endif if (bounds[0] == bounds[1] || zeroOne2 || (bounds[1] == upper[iColumn2] && false)) { { // get rid of node as far as branching nodeLook->setObjectiveValue(0.5*COIN_DBL_MAX); objectI->deactivate(); } previousBounds(node, nodeInfo, iColumn2, newLower, newUpper, 1); solver_->setColLower(iColumn2, newLower); assert (newUpper == upper[iColumn2]); } else { COIN_DETAIL_PRINT(printf("SKipping\n")); } } else if (iColumn1 >= 0 && iColumn1 != iColumn2 && (!inBetween || true) && zeroOne1 && zeroOne2 && false) { #ifndef JJF_ONE // add in bounds newLower = bounds1[0]; newUpper = bounds1[1]; COIN_DETAIL_PRINT(printf("setting bounds of %g and %g (column %d) on other branch for column %d\n", newLower, newUpper, iColumn1, iColumn2)); int infeasible = objectI->applyExtraBounds(iColumn1, newLower, newUpper, objectI->way()); if (infeasible) { COIN_DETAIL_PRINT(printf("infeasb!\n")); // get rid of node as far as branching nodeLook->setObjectiveValue(0.5*COIN_DBL_MAX); } #endif } // break; } else { inBetween = true; } } } else { // odd break; } } } delete [] currentLower; delete [] currentUpper; } } #endif if (parallelMode() >= 0) newNode = new CbcNode() ; #if 0 // Try diving if (parallelMode() >= 0 && (specialOptions_&2048) == 0) { // See if any diving heuristics set to do dive+save CbcHeuristicDive * dive=NULL; for (int i = 0; i < numberHeuristics_; i++) { CbcHeuristicDive * possible = dynamic_cast(heuristic_[i]); if (possible&&possible->maxSimplexIterations()==COIN_INT_MAX) { // if more than one then rotate later? //if (possible->canHeuristicRun()) { if (node->depth()==0||node->depth()==5) { dive=possible; break; } } } if (dive) { int numberNodes; CbcSubProblem ** nodes=NULL; int branchState=dive->fathom(this,numberNodes,nodes); if (branchState) { printf("new solution\n"); } if (0) { for (int iNode=0;iNodepush(nodes[iNode]) ; } assert (node->nodeInfo()); if (node->nodeInfo()->numberBranchesLeft()) { tree_->push(node) ; } else { node->setActive(false); } } delete [] nodes; } } // end try diving #endif // Set objective value (not so obvious if NLP etc) setObjectiveValue(newNode, node); int anyAction = -1 ; bool resolved = false ; if (newNode->objectiveValue() >= getCutoff()) { anyAction = -2; } else {// only allow at most a few passes int numberPassesLeft = 5; checkingNode = true; OsiSolverBranch * branches = NULL; // point to useful information anyAction = chooseBranch(newNode, numberPassesLeft, node, cuts, resolved, lastws, lowerBefore, upperBefore, branches); } /* If we end up infeasible, we can delete the new node immediately. Since this node won't be needing the cuts we collected, decrement the reference counts. If we are feasible, then we'll be placing this node into the live set, so increment the reference count in the current (parent) nodeInfo. */ lockThread(); if (anyAction == -2) { if (parallelMode() > 0) { assert (masterThread_); assert (node->nodeInfo()); node->nodeInfo()->decrement() ; delete newNode ; assert (node->nodeInfo()); node->nodeInfo()->increment() ; newNode = NULL ; } else if (parallelMode() == 0) { delete newNode ; newNode = NULL ; } else { //assert (newNode->active()); newNode->setActive(false); } // say strong doing well if (checkingNode) setSpecialOptions(specialOptions_ | 8); for (i = 0 ; i < currentNumberCuts_ ; i++) { if (addedCuts_[i]) { if (!addedCuts_[i]->decrement(1)) { delete addedCuts_[i] ; } addedCuts_[i] = NULL; //} } } } else { assert (node->nodeInfo()); if (parallelMode() >= 0) node->nodeInfo()->increment() ; if ((numberNodes_ % 20) == 0) { // say strong not doing as well setSpecialOptions(specialOptions_&~8); } } unlockThread(); } /* At this point, there are three possibilities: * newNode is live and will require further branching to resolve (variable() >= 0). Increment the cut reference counts by numberBranches() to allow for use by children of this node, and decrement by 1 because we've executed one arm of the branch of our parent (consuming one reference). Before we push newNode onto the search tree, try for a heuristic solution. * We have a solution, in which case newNode is non-null but we have no branching variable. Decrement the cut counts and save the solution. * The node was found to be infeasible, in which case it's already been deleted, and newNode is null. */ if (eventHandler_ && !eventHandler_->event(CbcEventHandler::node)) { eventHappened_ = true; // exit } if (parallelMode() >= 0) assert (!newNode || newNode->objectiveValue() <= getCutoff()) ; else assert (!newNode->active() || newNode->objectiveValue() <= getCutoff()) ; if (statistics_) { assert (numberNodes2_); assert (statistics_[numberNodes2_-1]); assert (statistics_[numberNodes2_-1]->node() == numberNodes2_ - 1); if (newNode && newNode->active()) statistics_[numberNodes2_-1]->updateInfeasibility(newNode->numberUnsatisfied()); else statistics_[numberNodes2_-1]->sayInfeasible(); } lockThread(); bool locked = true; if (parallelMode() <= 0) { if (numberUpdateItems_) { for (i = 0; i < numberUpdateItems_; i++) { CbcObjectUpdateData * update = updateItems_ + i; CbcObject * object = dynamic_cast (update->object_); #ifndef NDEBUG bool found = false; for (int j = 0; j < numberObjects_; j++) { if (update->object_ == object_[j]) { found = true; break; } } assert (found); #endif //if (object) //assert (object==object_[update->objectNumber_]); if (object) object->updateInformation(*update); } numberUpdateItems_ = 0; } } if (newNode) if (newNode && newNode->active()) { if (newNode->branchingObject() == NULL) { const double * solution = solver_->getColSolution(); CbcEventHandler::CbcAction action = dealWithEventHandler(CbcEventHandler::beforeSolution1, getSolverObjValue(), solution); if (action == CbcEventHandler::addCuts || solverCharacteristics_->solverType() == 4) { // need to check if any cuts would do anything OsiCuts theseCuts; // reset probing info //if (probingInfo_) //probingInfo_->initializeFixing(solver_); for (int i = 0; i < numberCutGenerators_; i++) { bool generate = generator_[i]->normal(); // skip if not optimal and should be (maybe a cut generator has fixed variables) if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable()) generate = false; if (!generator_[i]->mustCallAgain()) generate = false; // only special cuts if (generate) { generator_[i]->generateCuts(theseCuts, -1, solver_, NULL) ; int numberRowCutsAfter = theseCuts.sizeRowCuts() ; if (numberRowCutsAfter) break; } } int numberRowCutsAfter = theseCuts.sizeRowCuts() ; if (numberRowCutsAfter || action == CbcEventHandler::addCuts) { // need dummy branch newNode->setBranchingObject(new CbcDummyBranchingObject(this)); newNode->nodeInfo()->initializeInfo(1); } } } if (newNode->branchingObject()) { handler_->message(CBC_BRANCH, messages_) << numberNodes_ << newNode->objectiveValue() << newNode->numberUnsatisfied() << newNode->depth() << CoinMessageEol ; // Increment cut counts (taking off current) int numberLeft = newNode->numberBranches() ; for (i = 0; i < currentNumberCuts_; i++) { if (addedCuts_[i]) { # ifdef CHECK_CUT_COUNTS printf("Count on cut %x increased by %d\n", addedCuts_[i], numberLeft - 1) ; # endif addedCuts_[i]->increment(numberLeft - 1) ; } } unlockThread(); locked = false; double estValue = newNode->guessedObjectiveValue() ; int found = -1 ; double * newSolution = new double [numberColumns] ; double heurValue = getCutoff() ; int iHeur ; int whereFrom = 3; for (iHeur = 0 ; iHeur < numberHeuristics_ ; iHeur++) { // skip if can't run here if (!heuristic_[iHeur]->shouldHeurRun(whereFrom)) continue; double saveValue = heurValue ; int ifSol = heuristic_[iHeur]->solution(heurValue, newSolution) ; if (ifSol > 0) { // new solution found heuristic_[iHeur]->incrementNumberSolutionsFound(); found = iHeur ; if (parallelMode() > 0) { lockThread(); baseModel->incrementUsed(newSolution); unlockThread(); } else { lastHeuristic_ = heuristic_[found]; #ifdef CLP_INVESTIGATE printf("HEUR %s where %d D\n", lastHeuristic_->heuristicName(), whereFrom); #endif setBestSolution(CBC_ROUNDING, heurValue, newSolution) ; foundSolution = 1; whereFrom |= 8; // say solution found } } else if (ifSol < 0) { // just returning an estimate estValue = CoinMin(heurValue, estValue) ; heurValue = saveValue ; } } if (found >= 0 && parallelMode() > 0) { lastHeuristic_ = heuristic_[found]; #ifdef CLP_INVESTIGATE printf("HEUR %s where %d D\n", lastHeuristic_->heuristicName(), whereFrom); #endif setBestSolution(CBC_ROUNDING, heurValue, newSolution) ; foundSolution = 1; } delete [] newSolution ; newNode->setGuessedObjectiveValue(estValue) ; if (parallelMode() >= 0) { if (!masterThread_) // only if serial tree_->push(newNode) ; } if (statistics_) { if (numberNodes2_ == maximumStatistics_) { maximumStatistics_ = 2 * maximumStatistics_; CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_]; memset(temp, 0, maximumStatistics_*sizeof(CbcStatistics *)); memcpy(temp, statistics_, numberNodes2_*sizeof(CbcStatistics *)); delete [] statistics_; statistics_ = temp; } assert (!statistics_[numberNodes2_]); statistics_[numberNodes2_] = new CbcStatistics(newNode, this); } numberNodes2_++; # ifdef CHECK_NODE printf("Node %x pushed on tree c\n", newNode) ; # endif } else { if (solverCharacteristics_ && //we may be in a non standard bab solverCharacteristics_->solutionAddsCuts()// we are in some kind of OA based bab. ) { std::cerr << "You should never get here" << std::endl; throw CoinError("Nodes should not be fathomed on integer infeasibility in this setting", "branchAndBound", "CbcModel") ; } for (i = 0 ; i < currentNumberCuts_ ; i++) { if (addedCuts_[i]) { if (!addedCuts_[i]->decrement(1)) { delete addedCuts_[i] ; addedCuts_[i] = NULL; } } } double objectiveValue = newNode->objectiveValue(); lastHeuristic_ = NULL; // Just possible solver did not know about a solution from another thread! if (objectiveValue < getCutoff()) { incrementUsed(solver_->getColSolution()); setBestSolution(CBC_SOLUTION, objectiveValue, solver_->getColSolution()) ; // Check if was found if (bestObjective_ < getCutoff()) foundSolution = 1; } //assert(nodeInfo->numberPointingToThis() <= 2) ; if (parallelMode() >= 0) { // avoid accidental pruning, if newNode was final branch arm node->nodeInfo()->increment(); delete newNode ; newNode = NULL; node->nodeInfo()->decrement() ; } else { newNode->setActive(false); } } } if (branchesLeft) { // set nodenumber correctly if (node->nodeInfo()) node->nodeInfo()->setNodeNumber(numberNodes2_); if (parallelMode() >= 0) { if (!masterThread_) // only if serial tree_->push(node) ; } if (statistics_) { if (numberNodes2_ == maximumStatistics_) { maximumStatistics_ = 2 * maximumStatistics_; CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_]; memset(temp, 0, maximumStatistics_*sizeof(CbcStatistics *)); memcpy(temp, statistics_, numberNodes2_*sizeof(CbcStatistics *)); delete [] statistics_; statistics_ = temp; } assert (!statistics_[numberNodes2_]); statistics_[numberNodes2_] = new CbcStatistics(node, this); } numberNodes2_++; //nodeOnTree=true; // back on tree //deleteNode = false ; # ifdef CHECK_NODE printf("Node %x pushed back on tree - %d left, %d count\n", node, node->nodeInfo()->numberBranchesLeft(), node->nodeInfo()->numberPointingToThis()) ; # endif if (parallelMode() > 0) { assert (node->nodeInfo()); node->nodeInfo()->decrement() ; } } else { /* This node has been completely expanded and can be removed from the live set. */ if (parallelMode() > 0) { assert (masterThread_) ; assert (node->nodeInfo()); node->nodeInfo()->decrement() ; } assert (node->nodeInfo()); if (parallelMode() >= 0) { if (!node->nodeInfo()->numberBranchesLeft()) node->nodeInfo()->allBranchesGone(); // can clean up delete node ; node = NULL; } else { node->setActive(false); } } if (locked) unlockThread(); } else { // add cuts found to be infeasible (on bound)! COIN_DETAIL_PRINT(printf("found to be infeas! - branches left %d - cutoff %g\n", node->nodeInfo()->numberBranchesLeft(), getCutoff())); #ifdef COIN_DETAIL node->print(); #endif //abort(); assert (node->nodeInfo()); if (parallelMode() >= 0) { if (!node->nodeInfo()->numberBranchesLeft()) node->nodeInfo()->allBranchesGone(); // can clean up delete node; node = NULL; } else { node->setActive(false); } } /* Delete cuts to get back to the original system. I'm thinking this is redundant --- the call to addCuts that conditions entry to this code block also performs this action. */ #ifndef JJF_ONE //if (numberThreads_) { int numberToDelete = getNumRows() - numberRowsAtContinuous_ ; if (numberToDelete) { int * delRows = new int[numberToDelete] ; int i ; for (i = 0 ; i < numberToDelete ; i++) delRows[i] = i + numberRowsAtContinuous_ ; solver_->deleteRows(numberToDelete, delRows) ; delete [] delRows ; } } #endif delete lastws ; delete [] lowerBefore ; delete [] upperBefore ; if (bestObjective > bestObjective_) foundSolution = 2; if (parallelMode() > 0 && foundSolution) { lockThread(); // might as well mark all including continuous int numberColumns = solver_->getNumCols(); for (int i = 0; i < numberColumns; i++) { baseModel->usedInSolution_[i] += usedInSolution_[i]; usedInSolution_[i] = 0; } baseModel->numberSolutions_++; if (bestObjective_ < baseModel->bestObjective_ && bestObjective_ < baseModel->getCutoff()) { baseModel->bestObjective_ = bestObjective_ ; int numberColumns = solver_->getNumCols(); if (!baseModel->bestSolution_) baseModel->bestSolution_ = new double[numberColumns]; CoinCopyN(bestSolution_, numberColumns, baseModel->bestSolution_); baseModel->setCutoff(getCutoff()); } unlockThread(); } numberCutGenerators_=saveNumberCutGenerators; return foundSolution; } // Adds an update information object void CbcModel::addUpdateInformation(const CbcObjectUpdateData & data) { if (numberUpdateItems_ == maximumNumberUpdateItems_) { maximumNumberUpdateItems_ += 10; CbcObjectUpdateData * temp = new CbcObjectUpdateData [maximumNumberUpdateItems_]; for (int i = 0; i < maximumNumberUpdateItems_ - 10; i++) temp[i] = updateItems_[i]; delete [] updateItems_; updateItems_ = temp; } updateItems_[numberUpdateItems_++] = data; } // Returns bounds just before where - initially original bounds - also sets bounds void CbcModel::previousBounds (CbcNode * node, CbcNodeInfo * where, int iColumn, double & lower, double & upper, int force) { int i; int nNode = 0; CbcNodeInfo * nodeInfo = node->nodeInfo(); int nWhere = -1; /* Accumulate the path from node to the root in walkback_ */ while (nodeInfo) { //printf("nNode = %d, nodeInfo = %x\n",nNode,nodeInfo); walkback_[nNode++] = nodeInfo; nodeInfo = nodeInfo->parent() ; if (nNode == maximumDepth_) { redoWalkBack(); } if (nodeInfo == where) nWhere = nNode; } assert (nWhere >= 0); nWhere = nNode - nWhere; for (i = 0; i < nWhere; i++) { --nNode; walkback_[nNode]->applyBounds(iColumn, lower, upper, 0); } // correct bounds walkback_[nNode]->applyBounds(iColumn, lower, upper, 3); CbcNode * nodeLook = walkback_[nNode]->mutableOwner(); if (nodeLook) { OsiBranchingObject * obj = nodeLook->modifiableBranchingObject(); CbcIntegerBranchingObject * objectI = dynamic_cast (obj); //const OsiObject * object2 = obj->orig #ifndef NDEBUG const CbcSimpleInteger * object2 = dynamic_cast (objectI->object()); assert (object2); assert (iColumn == object2->columnNumber()); #endif double bounds[2]; bounds[0] = lower; bounds[1] = upper; objectI->setDownBounds(bounds); objectI->setUpBounds(bounds); } while (nNode) { --nNode; walkback_[nNode]->applyBounds(iColumn, lower, upper, force); #ifdef JJF_ZERO CbcNode * nodeLook = walkback_[nNode]->mutableOwner(); if (nodeLook) { const OsiBranchingObject * obj = nodeLook->branchingObject(); const CbcIntegerBranchingObject * objectI = dynamic_cast (obj); //const OsiObject * object2 = obj->orig const CbcSimpleInteger * object2 = dynamic_cast (objectI->object()); assert (object2); int iColumn2 = object2->columnNumber(); assert (iColumn != iColumn2); } #endif } } /* Return pseudo costs If not all integers or not pseudo costs - returns all zero Length of arrays are numberIntegers() and entries correspond to integerVariable()[i] User must allocate arrays before call */ void CbcModel::fillPseudoCosts(double * downCosts, double * upCosts, int * priority, int * numberDown, int * numberUp, int * numberDownInfeasible, int * numberUpInfeasible) const { CoinFillN(downCosts, numberIntegers_, 1.0); CoinFillN(upCosts, numberIntegers_, 1.0); if (priority) { CoinFillN(priority, numberIntegers_, 1000000); } if (numberDown) { CoinFillN(numberDown, numberIntegers_, 1); CoinFillN(numberUp, numberIntegers_, 1); } if (numberDownInfeasible) { CoinZeroN(numberDownInfeasible, numberIntegers_); CoinZeroN(numberUpInfeasible, numberIntegers_); } int numberColumns = getNumCols(); int * back = new int[numberColumns]; int i; for (i = 0; i < numberColumns; i++) back[i] = -1; for (i = 0; i < numberIntegers_; i++) back[integerVariable_[i]] = i; #ifdef CLP_INVESTIGATE int numberNot = 0; #endif for ( i = 0; i < numberObjects_; i++) { CbcSimpleIntegerDynamicPseudoCost * obj = dynamic_cast (object_[i]) ; if (!obj) continue; #ifdef CLP_INVESTIGATE if (obj->numberTimesDown() < numberBeforeTrust_ || obj->numberTimesUp() < numberBeforeTrust_) numberNot++; #endif int iColumn = obj->columnNumber(); iColumn = back[iColumn]; assert (iColumn >= 0); if (priority) priority[iColumn] = obj->priority(); downCosts[iColumn] = obj->downDynamicPseudoCost(); upCosts[iColumn] = obj->upDynamicPseudoCost(); if (numberDown) { numberDown[iColumn] = obj->numberTimesDown(); numberUp[iColumn] = obj->numberTimesUp(); } if (numberDownInfeasible) { numberDownInfeasible[iColumn] = obj->numberTimesDownInfeasible(); numberUpInfeasible[iColumn] = obj->numberTimesUpInfeasible(); } } #ifdef CLP_INVESTIGATE4 if (priority) printf("Before fathom %d not trusted out of %d\n", numberNot, numberIntegers_); #endif delete [] back; } // Redo walkback arrays void CbcModel::redoWalkBack() { int nNode = maximumDepth_; maximumDepth_ *= 2; CbcNodeInfo ** temp = new CbcNodeInfo * [maximumDepth_]; CbcNodeInfo ** temp2 = new CbcNodeInfo * [maximumDepth_]; int * temp3 = new int [maximumDepth_]; for (int i = 0; i < nNode; i++) { temp[i] = walkback_[i]; temp2[i] = lastNodeInfo_[i]; temp3[i] = lastNumberCuts_[i]; } delete [] walkback_; walkback_ = temp; delete [] lastNodeInfo_ ; lastNodeInfo_ = temp2; delete [] lastNumberCuts_ ; lastNumberCuts_ = temp3; } /* Return true if we want to do cuts If allowForTopOfTree zero then just does on multiples of depth if 1 then allows for doing at top of tree if 2 then says if cuts allowed anywhere apart from root if 3 then gives smallest valid depth >shallow */ bool CbcModel::doCutsNow(int allowForTopOfTree) const { int whenCutsUse = whenCuts_; int alwaysReturnAt10 = whenCutsUse % 100000; if (whenCutsUse > 0 && alwaysReturnAt10) { whenCutsUse -= alwaysReturnAt10; if (currentDepth_ > 10) return false; } //if (currentDepth_>10) //return false; #define TRY_IDEA1 2 int size = continuousSolver_->getNumRows() + continuousSolver_->getNumCols(); if (true && (whenCutsUse < 0 || (size <= 500 - 500*TRY_IDEA1 && allowForTopOfTree != 3))) { int whenCuts = (size <= 500) ? -1 : 1; //whenCuts = (size<=500) ? 1 :1; if (parentModel_) whenCuts = 1; //int nodeDepth = currentDepth_-1; bool doCuts2 = !(currentDepth_ > 11 && (currentDepth_ & 1) == whenCuts); if (fastNodeDepth_ > 0 && currentDepth_ > 10) doCuts2 = false; //printf("when %d node %d depth %d size %d doing cuts %s\n",whenCutsUse, // numberNodes_,currentDepth_,size,doCuts2 ? "yes" : "no"); return doCuts2; } //if (!parentModel_&¤tDepth_==7) //printf("q\n"); int top = whenCutsUse / 1000000; int shallow = top ? (top - 1) : 9; int when = whenCutsUse - 1000000 * top; #if TRY_IDEA1 if (when<15 && when>1 && size <= 500) when /= 2; #endif if ((when > 15 || (top && top < 5)) && currentDepth_ > when) when = 100000; // off bool doCuts = when ? ((currentDepth_ % when) == 0) || (when == 1) : false; if (allowForTopOfTree == 1 && currentDepth_ <= shallow) { doCuts = true; } else if (allowForTopOfTree == 2 && shallow >= 1) { doCuts = true; #if TRY_IDEA1<2 } else if (allowForTopOfTree == 3 && doCuts) { // only if first if (currentDepth_ <= shallow || currentDepth_ - when > shallow) doCuts = false; #else } else if (allowForTopOfTree == 3) { // only exactly at 10 doCuts = (currentDepth_ == 10); #endif } //if (!doCuts&¤tDepth_&&!parentModel_) //printf("zzz\n"); return doCuts; } // See if can stop on gap bool CbcModel::canStopOnGap() const { bool returnCode=false; if (bestObjective_<1.0e50) { double testGap = CoinMax(dblParam_[CbcAllowableGap], CoinMax(fabs(bestObjective_), fabs(bestPossibleObjective_)) * dblParam_[CbcAllowableFractionGap]); returnCode = (bestObjective_ - bestPossibleObjective_ < testGap && getCutoffIncrement() >= 0.0); } return returnCode; } // Adjust heuristics based on model void CbcModel::adjustHeuristics() { int numberRows = solver_->getNumRows(); int numberColumns = solver_->getNumCols(); int nTree = CoinMax(10000, 2 * numberRows + numberColumns); int nRoot = CoinMax(40000, 8 * numberRows + 4 * numberColumns); for (int i = 0; i < numberHeuristics_; i++) { CbcHeuristicDive * heuristic = dynamic_cast (heuristic_[i]); if (heuristic && heuristic->maxSimplexIterations()!=COIN_INT_MAX) { heuristic->setMaxSimplexIterations(nTree); heuristic->setMaxSimplexIterationsAtRoot(nRoot); } } } // Number of saved solutions (including best) int CbcModel::numberSavedSolutions() const { if (!bestSolution_) return 0; else return numberSavedSolutions_ + 1; } // Set maximum number of extra saved solutions void CbcModel::setMaximumSavedSolutions(int value) { if (value < maximumSavedSolutions_) { for (int i = value; i < maximumSavedSolutions_; i++) delete [] savedSolutions_[i]; maximumSavedSolutions_ = value; numberSavedSolutions_ = CoinMin(numberSavedSolutions_, maximumSavedSolutions_); if (!maximumSavedSolutions_) delete [] savedSolutions_; } else if (value > maximumSavedSolutions_) { double ** temp = new double * [value]; int i; for ( i = 0; i < maximumSavedSolutions_; i++) temp[i] = savedSolutions_[i]; for ( ; i < value; i++) temp[i] = NULL; delete [] savedSolutions_; maximumSavedSolutions_ = value; savedSolutions_ = temp; } } // Return a saved solution objective (0==best) - COIN_DBL_MAX if off end double CbcModel::savedSolutionObjective(int which) const { if (which == 0) { return bestObjective_; } else if (which <= numberSavedSolutions_) { double * sol = savedSolutions_[which-1]; assert (static_cast(sol[0]) == solver_->getNumCols()); return sol[1]; } else { return COIN_DBL_MAX; } } // Return a saved solution (0==best) - NULL if off end const double * CbcModel::savedSolution(int which) const { if (which == 0) { return bestSolution_; } else if (which <= numberSavedSolutions_) { double * sol = savedSolutions_[which-1]; assert (static_cast(sol[0]) == solver_->getNumCols()); return sol + 2; } else { return NULL; } } // Save a solution void CbcModel::saveExtraSolution(const double * solution, double objectiveValue) { double * save = NULL; if (maximumSavedSolutions_) { if (!savedSolutions_) { savedSolutions_ = new double * [maximumSavedSolutions_]; for (int i = 0; i < maximumSavedSolutions_; i++) savedSolutions_[i] = NULL; } int n = solver_->getNumCols(); int k; for (k = numberSavedSolutions_ - 1; k >= 0; k--) { double * sol = savedSolutions_[k]; assert (static_cast(sol[0]) == n); if (objectiveValue > sol[1]) break; } k++; // where to put if (k < maximumSavedSolutions_) { if (numberSavedSolutions_ == maximumSavedSolutions_) { save = savedSolutions_[numberSavedSolutions_-1]; } else { save = new double [n+2]; numberSavedSolutions_++; } // move up for (int j = maximumSavedSolutions_ - 1; j > k; j--) savedSolutions_[j] = savedSolutions_[j-1]; savedSolutions_[k] = save; save[0] = n; save[1] = objectiveValue; memcpy(save + 2, solution, n*sizeof(double)); } } } // Save a solution to best and move current to saved void CbcModel::saveBestSolution(const double * solution, double objectiveValue) { int n = solver_->getNumCols(); if (bestSolution_) saveExtraSolution(bestSolution_, bestObjective_); else bestSolution_ = new double [n]; bestObjective_ = objectiveValue; memcpy(bestSolution_, solution, n*sizeof(double)); } // Delete best and saved solutions void CbcModel::deleteSolutions() { delete [] bestSolution_; bestSolution_ = NULL; for (int i = 0; i < maximumSavedSolutions_; i++) { delete [] savedSolutions_[i]; savedSolutions_[i] = NULL; } numberSavedSolutions_ = 0; } // Delete a saved solution and move others up void CbcModel::deleteSavedSolution(int which) { if (which >0 && which <= numberSavedSolutions_) { delete [] savedSolutions_[which-1]; // move up numberSavedSolutions_--; for (int j = which-1; j (solver_); if (clpSolver && numberNodes_ >= numberNodes && numberNodes_ < 2*numberNodes) { if (numberIterations_ < (numberSolves_ + numberNodes_)*10) { //if (numberIterations_getModelPtr(); ClpDualRowPivot * pivotMethod = simplex->dualRowPivot(); ClpDualRowDantzig * pivot = dynamic_cast< ClpDualRowDantzig*>(pivotMethod); if (!pivot) { savePivotMethod = pivotMethod->clone(true); ClpDualRowDantzig dantzig; simplex->setDualRowPivotAlgorithm(dantzig); #ifdef COIN_DEVELOP printf("%d node, %d iterations ->Dantzig\n", numberNodes_, numberIterations_); #endif #ifdef CBC_THREAD if (master_) master_->setDantzigState(); #endif } } } } } #else CbcModel::goToDantzig(int numberNodes, ClpDualRowPivot *& savePivotMethod) { printf("Need Clp to go to Dantzig\n"); abort(); } #endif // Below this is deprecated or at least fairly deprecated /* Do Integer Presolve. Returns new model. I have to work out cleanest way of getting solution to original problem at end. So this is very preliminary. */ CbcModel * CbcModel::integerPresolve(bool weak) { status_ = 0; // solve LP //solver_->writeMps("bad"); bool feasible = (resolve(NULL, 3) != 0); CbcModel * newModel = NULL; if (feasible) { // get a new model newModel = new CbcModel(*this); newModel->messageHandler()->setLogLevel(messageHandler()->logLevel()); feasible = newModel->integerPresolveThisModel(solver_, weak); } if (!feasible) { handler_->message(CBC_INFEAS, messages_) << CoinMessageEol; status_ = 0; secondaryStatus_ = 1; delete newModel; return NULL; } else { newModel->synchronizeModel(); // make sure everything that needs solver has it return newModel; } } /* Do Integer Presolve - destroying current model */ bool CbcModel::integerPresolveThisModel(OsiSolverInterface * originalSolver, bool weak) { printf("DEPRECATED\n"); status_ = 0; // solve LP bool feasible = (resolve(NULL, 3) != 0); bestObjective_ = 1.0e50; numberSolutions_ = 0; numberHeuristicSolutions_ = 0; double cutoff = getCutoff() ; double direction = solver_->getObjSense(); if (cutoff < 1.0e20 && direction < 0.0) messageHandler()->message(CBC_CUTOFF_WARNING1, messages()) << cutoff << -cutoff << CoinMessageEol ; if (cutoff > bestObjective_) cutoff = bestObjective_ ; setCutoff(cutoff) ; int iColumn; int numberColumns = getNumCols(); int originalNumberColumns = numberColumns; currentPassNumber_ = 0; synchronizeModel(); // make sure everything that needs solver has it if (!solverCharacteristics_) { OsiBabSolver * solverCharacteristics = dynamic_cast (solver_->getAuxiliaryInfo()); if (solverCharacteristics) { solverCharacteristics_ = solverCharacteristics; } else { // replace in solver OsiBabSolver defaultC; solver_->setAuxiliaryInfo(&defaultC); solverCharacteristics_ = dynamic_cast (solver_->getAuxiliaryInfo()); } } solverCharacteristics_->setSolver(solver_); // just point to solver_ delete continuousSolver_; continuousSolver_ = solver_; // get a copy of original so we can fix bounds OsiSolverInterface * cleanModel = originalSolver->clone(); #ifdef CBC_DEBUG std::string problemName; cleanModel->getStrParam(OsiProbName, problemName); printf("Problem name - %s\n", problemName.c_str()); cleanModel->activateRowCutDebugger(problemName.c_str()); const OsiRowCutDebugger * debugger = cleanModel->getRowCutDebugger(); #endif // array which points from original columns to presolved int * original = new int[numberColumns]; // arrays giving bounds - only ones found by probing // rest will be found by presolve double * originalLower = new double[numberColumns]; double * originalUpper = new double[numberColumns]; { const double * lower = getColLower(); const double * upper = getColUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { original[iColumn] = iColumn; originalLower[iColumn] = lower[iColumn]; originalUpper[iColumn] = upper[iColumn]; } } findIntegers(true); // save original integers int * originalIntegers = new int[numberIntegers_]; int originalNumberIntegers = numberIntegers_; memcpy(originalIntegers, integerVariable_, numberIntegers_*sizeof(int)); int todo = 20; if (weak) todo = 1; while (currentPassNumber_ < todo) { currentPassNumber_++; numberSolutions_ = 0; // this will be set false to break out of loop with presolved problem bool doIntegerPresolve = (currentPassNumber_ != 20); // Current number of free integer variables // Get increment in solutions { const double * objective = cleanModel->getObjCoefficients(); const double * lower = cleanModel->getColLower(); const double * upper = cleanModel->getColUpper(); double maximumCost = 0.0; bool possibleMultiple = true; int numberChanged = 0; for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) { if (originalUpper[iColumn] > originalLower[iColumn]) { if ( cleanModel->isInteger(iColumn)) { maximumCost = CoinMax(maximumCost, fabs(objective[iColumn])); } else if (objective[iColumn]) { possibleMultiple = false; } } if (originalUpper[iColumn] < upper[iColumn]) { #ifdef CBC_DEBUG printf("Changing upper bound on %d from %g to %g\n", iColumn, upper[iColumn], originalUpper[iColumn]); #endif cleanModel->setColUpper(iColumn, originalUpper[iColumn]); numberChanged++; } if (originalLower[iColumn] > lower[iColumn]) { #ifdef CBC_DEBUG printf("Changing lower bound on %d from %g to %g\n", iColumn, lower[iColumn], originalLower[iColumn]); #endif cleanModel->setColLower(iColumn, originalLower[iColumn]); numberChanged++; } } // if first pass - always try if (currentPassNumber_ == 1) numberChanged += 1; if (possibleMultiple && maximumCost) { int increment = 0; double multiplier = 2520.0; while (10.0*multiplier*maximumCost < 1.0e8) multiplier *= 10.0; for (int j = 0; j < originalNumberIntegers; j++) { iColumn = originalIntegers[j]; if (originalUpper[iColumn] > originalLower[iColumn]) { if (objective[iColumn]) { double value = fabs(objective[iColumn]) * multiplier; int nearest = static_cast (floor(value + 0.5)); if (fabs(value - floor(value + 0.5)) > 1.0e-8 || value > 2.1e9) { increment = 0; break; // no good } else if (!increment) { // first increment = nearest; } else { increment = gcd(increment, nearest); } } } } if (increment) { double value = increment; value /= multiplier; if (value*0.999 > dblParam_[CbcCutoffIncrement]) { messageHandler()->message(CBC_INTEGERINCREMENT, messages()) << value << CoinMessageEol; dblParam_[CbcCutoffIncrement] = value * 0.999; } } } if (!numberChanged) { doIntegerPresolve = false; // not doing any better } } #ifdef CBC_DEBUG if (debugger) assert(debugger->onOptimalPath(*cleanModel)); #endif #ifdef COIN_HAS_CLP // do presolve - for now just clp but easy to get osi interface OsiClpSolverInterface * clpSolver = dynamic_cast (cleanModel); if (clpSolver) { ClpSimplex * clp = clpSolver->getModelPtr(); clp->messageHandler()->setLogLevel(cleanModel->messageHandler()->logLevel()); ClpPresolve pinfo; //printf("integerPresolve - temp switch off doubletons\n"); //pinfo.setPresolveActions(4); ClpSimplex * model2 = pinfo.presolvedModel(*clp, 1.0e-8); if (!model2) { // presolve found to be infeasible feasible = false; } else { // update original array const int * originalColumns = pinfo.originalColumns(); // just slot in new solver OsiClpSolverInterface * temp = new OsiClpSolverInterface(model2, true); numberColumns = temp->getNumCols(); for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) original[iColumn] = -1; for (iColumn = 0; iColumn < numberColumns; iColumn++) original[originalColumns[iColumn]] = iColumn; // copy parameters temp->copyParameters(*solver_); // and specialized ones temp->setSpecialOptions(clpSolver->specialOptions()); delete solver_; solver_ = temp; setCutoff(cutoff); deleteObjects(); if (!numberObjects_) { // Nothing left doIntegerPresolve = false; weak = true; break; } synchronizeModel(); // make sure everything that needs solver has it // just point to solver_ continuousSolver_ = solver_; feasible = (resolve(NULL, 3) != 0); if (!feasible || !doIntegerPresolve || weak) break; // see if we can get solution by heuristics int found = -1; int iHeuristic; double * newSolution = new double [numberColumns]; double heuristicValue = getCutoff(); int whereFrom = 0; for (iHeuristic = 0; iHeuristic < numberHeuristics_; iHeuristic++) { // skip if can't run here if (!heuristic_[iHeuristic]->shouldHeurRun(whereFrom)) continue; double saveValue = heuristicValue; int ifSol = heuristic_[iHeuristic]->solution(heuristicValue, newSolution); if (ifSol > 0) { // better solution found heuristic_[iHeuristic]->incrementNumberSolutionsFound(); found = iHeuristic; incrementUsed(newSolution); whereFrom |= 8; // say solution found } else if (ifSol < 0) { heuristicValue = saveValue; } } if (found >= 0) { // We probably already have a current solution, but just in case ... int numberColumns = getNumCols() ; if (!currentSolution_) currentSolution_ = new double[numberColumns] ; testSolution_ = currentSolution_; // better solution save lastHeuristic_ = heuristic_[found]; #ifdef CLP_INVESTIGATE printf("HEUR %s where %d oddE\n", lastHeuristic_->heuristicName(), whereFrom); #endif setBestSolution(CBC_ROUNDING, heuristicValue, newSolution); // update cutoff cutoff = getCutoff(); } delete [] newSolution; // Space for type of cuts maximumWhich_ = 1000; delete [] whichGenerator_ ; whichGenerator_ = new int[maximumWhich_]; // save number of rows numberRowsAtContinuous_ = getNumRows(); maximumNumberCuts_ = 0; currentNumberCuts_ = 0; delete [] addedCuts_; addedCuts_ = NULL; // maximum depth for tree walkback maximumDepth_ = 10; delete [] walkback_; walkback_ = new CbcNodeInfo * [maximumDepth_]; lastDepth_ = 0; delete [] lastNodeInfo_ ; lastNodeInfo_ = new CbcNodeInfo * [maximumDepth_] ; delete [] lastNumberCuts_ ; lastNumberCuts_ = new int [maximumDepth_] ; maximumCuts_ = 100; delete [] lastCut_; lastCut_ = new const OsiRowCut * [maximumCuts_]; OsiCuts cuts; numberOldActiveCuts_ = 0; numberNewCuts_ = 0; feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, NULL); currentNumberCuts_ = numberNewCuts_; delete [] whichGenerator_; whichGenerator_ = NULL; delete [] walkback_; walkback_ = NULL; delete [] addedCuts_; addedCuts_ = NULL; if (feasible) { // fix anything in original which integer presolve fixed // for now just integers const double * lower = solver_->getColLower(); const double * upper = solver_->getColUpper(); int i; for (i = 0; i < originalNumberIntegers; i++) { iColumn = originalIntegers[i]; int jColumn = original[iColumn]; if (jColumn >= 0) { if (upper[jColumn] < originalUpper[iColumn]) originalUpper[iColumn] = upper[jColumn]; if (lower[jColumn] > originalLower[iColumn]) originalLower[iColumn] = lower[jColumn]; } } } } } #endif if (!feasible || !doIntegerPresolve) { break; } } //solver_->writeMps("xx"); delete cleanModel; delete [] originalIntegers; numberColumns = getNumCols(); delete [] originalColumns_; originalColumns_ = new int[numberColumns]; numberColumns = 0; for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) { int jColumn = original[iColumn]; if (jColumn >= 0) originalColumns_[numberColumns++] = iColumn; } delete [] original; delete [] originalLower; delete [] originalUpper; deleteObjects(); synchronizeModel(); // make sure everything that needs solver has it continuousSolver_ = NULL; currentNumberCuts_ = 0; return feasible; } // Put back information into original model - after integerpresolve void CbcModel::originalModel(CbcModel * presolvedModel, bool weak) { solver_->copyParameters(*(presolvedModel->solver_)); bestObjective_ = presolvedModel->bestObjective_; delete [] bestSolution_; findIntegers(true); if (presolvedModel->bestSolution_) { int numberColumns = getNumCols(); int numberOtherColumns = presolvedModel->getNumCols(); //bestSolution_ = new double[numberColumns]; // set up map int * back = new int[numberColumns]; int i; for (i = 0; i < numberColumns; i++) back[i] = -1; for (i = 0; i < numberOtherColumns; i++) back[presolvedModel->originalColumns_[i]] = i; int iColumn; // set ones in presolved model to values double * otherSolution = presolvedModel->bestSolution_; //const double * lower = getColLower(); for (i = 0; i < numberIntegers_; i++) { iColumn = integerVariable_[i]; int jColumn = back[iColumn]; //bestSolution_[iColumn]=lower[iColumn]; if (jColumn >= 0) { double value = floor(otherSolution[jColumn] + 0.5); solver_->setColLower(iColumn, value); solver_->setColUpper(iColumn, value); //bestSolution_[iColumn]=value; } } delete [] back; #ifdef JJF_ZERO // ** looks as if presolve needs more intelligence // do presolve - for now just clp but easy to get osi interface OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); assert (clpSolver); ClpSimplex * clp = clpSolver->getModelPtr(); Presolve pinfo; ClpSimplex * model2 = pinfo.presolvedModel(*clp, 1.0e-8); model2->primal(1); pinfo.postsolve(true); const double * solution = solver_->getColSolution(); for (i = 0; i < numberIntegers_; i++) { iColumn = integerVariable_[i]; double value = floor(solution[iColumn] + 0.5); solver_->setColLower(iColumn, value); solver_->setColUpper(iColumn, value); } #else if (!weak) { // for now give up int save = numberCutGenerators_; numberCutGenerators_ = 0; bestObjective_ = 1.0e100; branchAndBound(); numberCutGenerators_ = save; } #endif if (bestSolution_) { // solve problem resolve(NULL, 3); // should be feasible if (!currentSolution_) currentSolution_ = new double[numberColumns] ; testSolution_ = currentSolution_; #ifndef NDEBUG int numberIntegerInfeasibilities; int numberObjectInfeasibilities; assert(feasibleSolution(numberIntegerInfeasibilities, numberObjectInfeasibilities)); #endif } } else { bestSolution_ = NULL; } numberSolutions_ = presolvedModel->numberSolutions_; numberHeuristicSolutions_ = presolvedModel->numberHeuristicSolutions_; numberNodes_ = presolvedModel->numberNodes_; numberIterations_ = presolvedModel->numberIterations_; status_ = presolvedModel->status_; secondaryStatus_ = presolvedModel->secondaryStatus_; synchronizeModel(); } void CbcModel::setOptionalInteger(int index) { #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver_); if (clpSolver) clpSolver->setOptionalInteger(index); else #endif solver_->setInteger(index); } // Return true if maximum time reached bool CbcModel::maximumSecondsReached() const { double totalTime = getCurrentSeconds() ; double maxSeconds = getMaximumSeconds(); bool hitMaxTime = (totalTime >= maxSeconds); if (parentModel_ && !hitMaxTime) { // In a sub tree assert (parentModel_); maxSeconds = parentModel_->getMaximumSeconds(); hitMaxTime = (totalTime >= maxSeconds); } if (hitMaxTime) { // Set eventHappened_ so will by-pass as much stuff as possible eventHappened_ = true; } return hitMaxTime; } // Check original model before it gets messed up void CbcModel::checkModel() { int iColumn ; int numberColumns = getNumCols() ; const double *lower = getColLower() ; const double *upper = getColUpper() ; int setFlag = 65536; for (iColumn = 0 ; iColumn < numberColumns ; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8) { double value; value = fabs(lower[iColumn]); if (floor(value + 0.5) != value) { setFlag = 0; break; } value = fabs(upper[iColumn]); if (floor(value + 0.5) != value) { setFlag = 0; break; } } } specialOptions_ |= setFlag; } static void flipSolver(OsiSolverInterface * solver, double newCutoff) { if (solver) { double objValue = solver->getObjValue(); double objectiveOffset; solver->setObjSense(-solver->getObjSense()); solver->getDblParam(OsiObjOffset,objectiveOffset); solver->setDblParam(OsiObjOffset,-objectiveOffset); int numberColumns = solver->getNumCols(); double * array = CoinCopyOfArray(solver->getObjCoefficients(),numberColumns); for (int i=0;isetObjective(array); delete [] array; solver->setDblParam(OsiDualObjectiveLimit,newCutoff); #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (solver); if (clpSolver) { double * dj = clpSolver->getModelPtr()->dualColumnSolution(); for (int i=0;igetNumRows(); double * pi = clpSolver->getModelPtr()->dualRowSolution(); for (int i=0;igetModelPtr()->setObjectiveValue(-objValue); } else { #endif // update values solver->resolve(); #ifdef COIN_HAS_CLP } #endif } } /* Flip direction of optimization on all models */ void CbcModel::flipModel() { if (parentModel_) return; // I think cutoff is always minimization double cutoff=getCutoff(); flipSolver(referenceSolver_,cutoff); flipSolver(continuousSolver_,cutoff); flipSolver(solver_,cutoff); } #ifdef CBC_KEEP_DEPRECATED /* preProcess problem - replacing solver If makeEquality true then <= cliques converted to ==. Presolve will be done numberPasses times. Returns NULL if infeasible If makeEquality is 1 add slacks to get cliques, if 2 add slacks to get sos (but only if looks plausible) and keep sos info */ CglPreProcess * CbcModel::preProcess( int makeEquality, int numberPasses, int tuning) { CglPreProcess * process = new CglPreProcess(); // Default set of cut generators CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); generator1.setMaxProbeRoot(solver_->getNumCols()); generator1.setMaxElements(100); generator1.setMaxLookRoot(50); generator1.setRowCuts(3); // Add in generators process->addCutGenerator(&generator1); process->messageHandler()->setLogLevel(this->logLevel()); /* model may not have created objects If none then create */ if (!numberIntegers_ || !numberObjects_) { this->findIntegers(true, 1); } // Do SOS int i; int numberSOS2 = 0; for (i = 0; i < numberObjects_; i++) { CbcSOS * objSOS = dynamic_cast (object_[i]) ; if (objSOS) { int type = objSOS->sosType(); if (type == 2) numberSOS2++; } } if (numberSOS2) { // SOS int numberColumns = solver_->getNumCols(); char * prohibited = new char[numberColumns]; memset(prohibited, 0, numberColumns); for (i = 0; i < numberObjects_; i++) { CbcSOS * objSOS = dynamic_cast (object_[i]) ; if (objSOS) { int type = objSOS->sosType(); if (type == 2) { int n = objSOS->numberMembers(); const int * which = objSOS->members(); for (int j = 0; j < n; j++) { int iColumn = which[j]; prohibited[iColumn] = 1; } } } } process->passInProhibited(prohibited, numberColumns); delete [] prohibited; } // Tell solver we are not in Branch and Cut solver_->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ; OsiSolverInterface * newSolver = process->preProcessNonDefault(*solver_, makeEquality, numberPasses, tuning); // Tell solver we are not in Branch and Cut solver_->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (newSolver) { int numberOriginalObjects = numberObjects_; OsiSolverInterface * originalSolver = solver_; solver_ = newSolver->clone(); // clone as process owns solver // redo sequence numberIntegers_ = 0; int numberColumns = solver_->getNumCols(); int nOrig = originalSolver->getNumCols(); const int * originalColumns = process->originalColumns(); // allow for cliques etc nOrig = CoinMax(nOrig, originalColumns[numberColumns-1] + 1); OsiObject ** originalObject = object_; // object number or -1 int * temp = new int[nOrig]; int iColumn; for (iColumn = 0; iColumn < nOrig; iColumn++) temp[iColumn] = -1; int iObject; numberObjects_ = 0; int nNonInt = 0; for (iObject = 0; iObject < numberOriginalObjects; iObject++) { iColumn = originalObject[iObject]->columnNumber(); if (iColumn < 0) { nNonInt++; } else { temp[iColumn] = iObject; } } int numberNewIntegers = 0; int numberOldIntegers = 0; int numberOldOther = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; CbcSimpleInteger * obj = dynamic_cast (originalObject[iObject]) ; if (obj) numberOldIntegers++; else numberOldOther++; } else if (isInteger(iColumn)) { numberNewIntegers++; } } /* Allocate an array to hold the indices of the integer variables. Make a large enough array for all objects */ numberObjects_ = numberNewIntegers + numberOldIntegers + numberOldOther + nNonInt; object_ = new OsiObject * [numberObjects_]; delete [] integerVariable_; integerVariable_ = new int [numberNewIntegers+numberOldIntegers]; /* Walk the variables again, filling in the indices and creating objects for the integer variables. Initially, the objects hold the index and upper & lower bounds. */ numberIntegers_ = 0; int n = originalColumns[numberColumns-1] + 1; int * backward = new int[n]; int i; for ( i = 0; i < n; i++) backward[i] = -1; for (i = 0; i < numberColumns; i++) backward[originalColumns[i]] = i; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; CbcSimpleInteger * obj = dynamic_cast (originalObject[iObject]) ; if (obj) { object_[numberIntegers_] = originalObject[iObject]->clone(); // redo ids etc //object_[numberIntegers_]->resetSequenceEtc(numberColumns,originalColumns); object_[numberIntegers_]->resetSequenceEtc(numberColumns, backward); integerVariable_[numberIntegers_++] = iColumn; } } else if (isInteger(iColumn)) { object_[numberIntegers_] = new CbcSimpleInteger(this, iColumn); integerVariable_[numberIntegers_++] = iColumn; } } delete [] backward; numberObjects_ = numberIntegers_; // Now append other column stuff for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = originalColumns[iColumn]; if (temp[jColumn] >= 0) { int iObject = temp[jColumn]; CbcSimpleInteger * obj = dynamic_cast (originalObject[iObject]) ; if (!obj) { object_[numberObjects_] = originalObject[iObject]->clone(); // redo ids etc CbcObject * obj = dynamic_cast (object_[numberObjects_]) ; assert (obj); obj->redoSequenceEtc(this, numberColumns, originalColumns); numberObjects_++; } } } // now append non column stuff for (iObject = 0; iObject < numberOriginalObjects; iObject++) { iColumn = originalObject[iObject]->columnNumber(); if (iColumn < 0) { object_[numberObjects_] = originalObject[iObject]->clone(); // redo ids etc CbcObject * obj = static_cast (object_[numberObjects_]) ; assert (obj); obj->redoSequenceEtc(this, numberColumns, originalColumns); numberObjects_++; } delete originalObject[iObject]; } delete [] originalObject; delete [] temp; if (!numberObjects_) handler_->message(CBC_NOINT, messages_) << CoinMessageEol ; return process; } else { // infeasible delete process; return NULL; } } /* Does postprocessing - original solver back. User has to delete process */ void CbcModel::postProcess(CglPreProcess * process) { process->postProcess(*solver_); delete solver_; solver_ = process->originalModel(); } /* Process root node and return a strengthened model The method assumes that initialSolve() has been called to solve the LP relaxation. It processes the root node and then returns a pointer to the strengthened model (or NULL if infeasible) */ OsiSolverInterface * CbcModel::strengthenedModel() { /* Switch off heuristics */ int saveNumberHeuristics = numberHeuristics_; numberHeuristics_ = 0; /* Scan the variables, noting the integer variables. Create an CbcSimpleInteger object for each integer variable. */ findIntegers(false) ; /* Ensure that objects on the lists of OsiObjects, heuristics, and cut generators attached to this model all refer to this model. */ synchronizeModel() ; // Set so we can tell we are in initial phase in resolve continuousObjective_ = -COIN_DBL_MAX ; /* Solve the relaxation. Apparently there are circumstances where this will be non-trivial --- i.e., we've done something since initialSolve that's trashed the solution to the continuous relaxation. */ bool feasible = resolve(NULL, 0) != 0 ; /* If the linear relaxation of the root is infeasible, bail out now. Otherwise, continue with processing the root node. */ if (!feasible) { handler_->message(CBC_INFEAS, messages_) << CoinMessageEol ; return NULL; } // Save objective (just so user can access it) originalContinuousObjective_ = solver_->getObjValue(); /* Begin setup to process a feasible root node. */ bestObjective_ = CoinMin(bestObjective_, 1.0e50) ; numberSolutions_ = 0 ; numberHeuristicSolutions_ = 0 ; // Everything is minimization double cutoff = getCutoff() ; double direction = solver_->getObjSense() ; if (cutoff < 1.0e20 && direction < 0.0) messageHandler()->message(CBC_CUTOFF_WARNING1, messages()) << cutoff << -cutoff << CoinMessageEol ; if (cutoff > bestObjective_) cutoff = bestObjective_ ; setCutoff(cutoff) ; /* We probably already have a current solution, but just in case ... */ int numberColumns = getNumCols() ; if (!currentSolution_) currentSolution_ = new double[numberColumns] ; testSolution_ = currentSolution_; /* Create a copy of the solver, thus capturing the original (root node) constraint system (aka the continuous system). */ continuousSolver_ = solver_->clone() ; numberRowsAtContinuous_ = getNumRows() ; /* Check the objective to see if we can deduce a nontrivial increment. If it's better than the current value for CbcCutoffIncrement, it'll be installed. */ analyzeObjective() ; /* Set up for cut generation. addedCuts_ holds the cuts which are relevant for the active subproblem. whichGenerator will be used to record the generator that produced a given cut. */ maximumWhich_ = 1000 ; delete [] whichGenerator_ ; whichGenerator_ = new int[maximumWhich_] ; maximumNumberCuts_ = 0 ; currentNumberCuts_ = 0 ; delete [] addedCuts_ ; addedCuts_ = NULL ; /* Generate cuts at the root node and reoptimise. solveWithCuts does the heavy lifting. It will iterate a generate/reoptimise loop (including reduced cost fixing) until no cuts are generated, the change in objective falls off, or the limit on the number of rounds of cut generation is exceeded. At the end of all this, any cuts will be recorded in cuts and also installed in the solver's constraint system. We'll have reoptimised, and removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been adjusted accordingly). Tell cut generators they can be a bit more aggressive at root node */ int iCutGenerator; for (iCutGenerator = 0; iCutGenerator < numberCutGenerators_; iCutGenerator++) { CglCutGenerator * generator = generator_[iCutGenerator]->generator(); generator->setAggressiveness(generator->getAggressiveness() + 100); } OsiCuts cuts ; numberOldActiveCuts_ = 0 ; numberNewCuts_ = 0 ; { int iObject ; int preferredWay ; int numberUnsatisfied = 0 ; memcpy(currentSolution_, solver_->getColSolution(), numberColumns*sizeof(double)) ; // point to useful information OsiBranchingInformation usefulInfo = usefulInformation(); for (iObject = 0 ; iObject < numberObjects_ ; iObject++) { double infeasibility = object_[iObject]->infeasibility(&usefulInfo, preferredWay) ; if (infeasibility) numberUnsatisfied++ ; } if (numberUnsatisfied) { feasible = solveWithCuts(cuts, maximumCutPassesAtRoot_, NULL) ; } } /* We've taken the continuous relaxation as far as we can. */ OsiSolverInterface * newSolver = NULL; if (feasible) { // make copy of current solver newSolver = solver_->clone(); } /* Clean up dangling objects. continuousSolver_ may already be toast. */ delete [] whichGenerator_ ; whichGenerator_ = NULL; delete [] walkback_ ; walkback_ = NULL ; delete [] lastNodeInfo_ ; lastNodeInfo_ = NULL; delete [] lastNumberCuts_ ; lastNumberCuts_ = NULL; delete [] lastCut_; lastCut_ = NULL; delete [] addedCuts_ ; addedCuts_ = NULL ; if (continuousSolver_) { delete continuousSolver_ ; continuousSolver_ = NULL ; } /* Destroy global cuts by replacing with an empty OsiCuts object. */ globalCuts_ = OsiCuts() ; delete globalConflictCuts_; globalConflictCuts_=NULL; numberHeuristics_ = saveNumberHeuristics; return newSolver; } /* create a submodel from partially fixed problem The method creates a new clean model with given bounds. */ CbcModel * CbcModel::cleanModel(const double * lower, const double * upper) { OsiSolverInterface * solver = continuousSolver_->clone(); int numberIntegers = numberIntegers_; const int * integerVariable = integerVariable_; int i; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = object_[i]; #ifndef NDEBUG const CbcSimpleInteger * integerObject = dynamic_cast (object); assert(integerObject); #else const CbcSimpleInteger * integerObject = static_cast (object); #endif // get original bounds double originalLower = integerObject->originalLowerBound(); double originalUpper = integerObject->originalUpperBound(); solver->setColLower(iColumn, CoinMax(lower[iColumn], originalLower)); solver->setColUpper(iColumn, CoinMin(upper[iColumn], originalUpper)); } CbcModel * model = new CbcModel(*solver); // off some messages if (handler_->logLevel() <= 1) { model->messagesPointer()->setDetailMessage(3, 9); model->messagesPointer()->setDetailMessage(3, 6); model->messagesPointer()->setDetailMessage(3, 4); model->messagesPointer()->setDetailMessage(3, 1); model->messagesPointer()->setDetailMessage(3, 13); model->messagesPointer()->setDetailMessage(3, 14); model->messagesPointer()->setDetailMessage(3, 3007); } // Cuts for ( i = 0; i < numberCutGenerators_; i++) { int howOften = generator_[i]->howOftenInSub(); if (howOften > -100) { CbcCutGenerator * generator = virginGenerator_[i]; CglCutGenerator * cglGenerator = generator->generator(); model->addCutGenerator(cglGenerator, howOften, generator->cutGeneratorName(), generator->normal(), generator->atSolution(), generator->whenInfeasible(), -100, generator->whatDepthInSub(), -1); } } double cutoff = getCutoff(); model->setCutoff(cutoff); return model; } /* Invoke the branch & cut algorithm on partially fixed problem The method uses a subModel created by cleanModel. The search ends when the tree is exhausted or maximum nodes is reached. If better solution found then it is saved. Returns 0 if search completed and solution, 1 if not completed and solution, 2 if completed and no solution, 3 if not completed and no solution. Normally okay to do subModel immediately followed by subBranchandBound (== other form of subBranchAndBound) but may need to get at model for advanced features. Deletes model */ int CbcModel::subBranchAndBound(CbcModel * model, CbcModel * presolvedModel, int maximumNodes) { int i; double cutoff = model->getCutoff(); CbcModel * model2; if (presolvedModel) model2 = presolvedModel; else model2 = model; // Do complete search for (i = 0; i < numberHeuristics_; i++) { model2->addHeuristic(heuristic_[i]); model2->heuristic(i)->resetModel(model2); } // Definition of node choice model2->setNodeComparison(nodeCompare_->clone()); //model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); model2->messageHandler()->setLogLevel(CoinMax(0, handler_->logLevel() - 1)); //model2->solver()->messageHandler()->setLogLevel(2); model2->setMaximumCutPassesAtRoot(maximumCutPassesAtRoot_); model2->setPrintFrequency(50); model2->setIntParam(CbcModel::CbcMaxNumNode, maximumNodes); model2->branchAndBound(); delete model2->nodeComparison(); if (model2->getMinimizationObjValue() > cutoff) { // no good if (model != model2) delete model2; delete model; return 2; } if (model != model2) { // get back solution model->originalModel(model2, false); delete model2; } int status; if (model->getMinimizationObjValue() < cutoff && model->bestSolution()) { double objValue = model->getObjValue(); const double * solution = model->bestSolution(); setBestSolution(CBC_TREE_SOL, objValue, solution); status = 0; } else { status = 2; } if (model->status()) status ++ ; // not finished search delete model; return status; } /* Invoke the branch & cut algorithm on partially fixed problem The method creates a new model with given bounds, presolves it then proceeds to explore the branch & cut search tree. The search ends when the tree is exhausted or maximum nodes is reached. Returns 0 if search completed and solution, 1 if not completed and solution, 2 if completed and no solution, 3 if not completed and no solution. */ int CbcModel::subBranchAndBound(const double * lower, const double * upper, int maximumNodes) { OsiSolverInterface * solver = continuousSolver_->clone(); int numberIntegers = numberIntegers_; const int * integerVariable = integerVariable_; int i; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = object_[i]; #ifndef NDEBUG const CbcSimpleInteger * integerObject = dynamic_cast (object); assert(integerObject); #else const CbcSimpleInteger * integerObject = static_cast (object); #endif // get original bounds double originalLower = integerObject->originalLowerBound(); double originalUpper = integerObject->originalUpperBound(); solver->setColLower(iColumn, CoinMax(lower[iColumn], originalLower)); solver->setColUpper(iColumn, CoinMin(upper[iColumn], originalUpper)); } CbcModel model(*solver); // off some messages if (handler_->logLevel() <= 1) { model.messagesPointer()->setDetailMessage(3, 9); model.messagesPointer()->setDetailMessage(3, 6); model.messagesPointer()->setDetailMessage(3, 4); model.messagesPointer()->setDetailMessage(3, 1); model.messagesPointer()->setDetailMessage(3, 3007); } double cutoff = getCutoff(); model.setCutoff(cutoff); // integer presolve CbcModel * model2 = model.integerPresolve(false); if (!model2 || !model2->getNumRows()) { delete model2; delete solver; return 2; } if (handler_->logLevel() > 1) printf("Reduced model has %d rows and %d columns\n", model2->getNumRows(), model2->getNumCols()); // Do complete search // Cuts for ( i = 0; i < numberCutGenerators_; i++) { int howOften = generator_[i]->howOftenInSub(); if (howOften > -100) { CbcCutGenerator * generator = virginGenerator_[i]; CglCutGenerator * cglGenerator = generator->generator(); model2->addCutGenerator(cglGenerator, howOften, generator->cutGeneratorName(), generator->normal(), generator->atSolution(), generator->whenInfeasible(), -100, generator->whatDepthInSub(), -1); } } for (i = 0; i < numberHeuristics_; i++) { model2->addHeuristic(heuristic_[i]); model2->heuristic(i)->resetModel(model2); } // Definition of node choice model2->setNodeComparison(nodeCompare_->clone()); //model2->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); model2->messageHandler()->setLogLevel(CoinMax(0, handler_->logLevel() - 1)); //model2->solver()->messageHandler()->setLogLevel(2); model2->setMaximumCutPassesAtRoot(maximumCutPassesAtRoot_); model2->setPrintFrequency(50); model2->setIntParam(CbcModel::CbcMaxNumNode, maximumNodes); model2->branchAndBound(); delete model2->nodeComparison(); if (model2->getMinimizationObjValue() > cutoff) { // no good delete model2; delete solver; return 2; } // get back solution model.originalModel(model2, false); delete model2; int status; if (model.getMinimizationObjValue() < cutoff && model.bestSolution()) { double objValue = model.getObjValue(); const double * solution = model.bestSolution(); setBestSolution(CBC_TREE_SOL, objValue, solution); status = 0; } else { status = 2; } if (model.status()) status ++ ; // not finished search delete solver; return status; } #endif static void * doRootCbcThread(void * voidInfo) { CbcModel * model = reinterpret_cast (voidInfo); #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast (model->solver()); char general[200]; if (clpSolver) { clpSolver->getModelPtr()->dual(); // probably not needed clpSolver->setWarmStart(NULL); sprintf(general,"Starting multiple root solver"); } else { #endif #ifdef COIN_HAS_CLP model->initialSolve(); sprintf(general,"Solver did %d iterations in initialSolve\n", model->solver()->getIterationCount()); } #endif model->messageHandler()->message(CBC_GENERAL, model->messages()) << general << CoinMessageEol ; model->branchAndBound(); sprintf(general,"Ending multiple root solver"); model->messageHandler()->message(CBC_GENERAL, model->messages()) << general << CoinMessageEol ; return NULL; } OsiRowCut * CbcModel::conflictCut(const OsiSolverInterface * solver, bool & localCuts) { OsiRowCut * cut=NULL; localCuts=false; # ifdef COIN_HAS_CLP const OsiClpSolverInterface * clpSolver = dynamic_cast (solver); if (clpSolver&&topOfTree_) { int debugMode=0; const double * originalLower = topOfTree_->lower(); const double * originalUpper = topOfTree_->upper(); int typeCut = 1; ClpSimplex * simplex = clpSolver->getModelPtr(); assert(simplex->status()==1); if(simplex->ray()) { { int numberRows=simplex->numberRows(); double * saveRay=CoinCopyOfArray(simplex->ray(),numberRows); #define SAFE_RAY #ifdef SAFE_RAY ClpSimplex & tempSimplex=*simplex; #else ClpSimplex tempSimplex=*simplex; #endif int logLevel=simplex->logLevel(); tempSimplex.setLogLevel(63); tempSimplex.scaling(0); tempSimplex.dual(); tempSimplex.setLogLevel(logLevel); if (!tempSimplex.numberIterations()) { double * ray = tempSimplex.ray(); int nBad=0; for (int i=0;i1.0e-3) { if (debugMode) printf("row %d true %g bad %g - diff %g\n", i,ray[i],saveRay[i],ray[i]-saveRay[i]); nBad++; } } if (nBad) printf("%d mismatch crunch ray values\n",nBad); } delete [] saveRay; } // make sure we use non-scaled versions ClpPackedMatrix * saveMatrix = simplex->swapScaledMatrix(NULL); double * saveScale = simplex->swapRowScale(NULL); //printf("Could do normal cut\n"); // could use existing arrays int numberRows=simplex->numberRows(); int numberColumns=simplex->numberColumns(); double * farkas = new double [2*numberColumns+numberRows]; double * bound = farkas + numberColumns; double * effectiveRhs = bound + numberColumns; // sign as internally for dual - so swap if primal /*const*/ double * ray = simplex->ray(); // have to get rid of local cut rows if (whichGenerator_) { const int * whichGenerator = whichGenerator_ - numberRowsAtContinuous_; int badRows=0; for (int iRow=numberRowsAtContinuous_;iRow=0&&iType<10000)||iType<-1) { if (fabs(ray[iRow])>1.0e-10) { badRows++; } else { ray[iRow]=0.0; } } } if (badRows) { if ((debugMode&1)!=0) printf("%d rows from local cuts\n",badRows); localCuts=true; } } // get farkas row memset(farkas,0,(2*numberColumns+numberRows)*sizeof(double)); simplex->transposeTimes(-1.0,ray,farkas); //const char * integerInformation = simplex->integerType_; //assert (integerInformation); int sequenceOut = simplex->sequenceOut(); // Put nonzero bounds in bound const double * columnLower = simplex->columnLower(); const double * columnUpper = simplex->columnUpper(); int numberBad=0; for (int i=0;igetStatus(i)==ClpSimplex::basic) { // treat as zero if small if (fabs(value)<1.0e-8) { value=0.0; farkas[i]=0.0; } if (value) { //printf("basic %d direction %d farkas %g\n", // i,simplex->directionOut(),value); if (value<0.0) boundValue=columnLower[i]; else boundValue=columnUpper[i]; } } else if (fabs(value)>1.0e-10) { if (value<0.0) boundValue=columnLower[i]; else boundValue=columnUpper[i]; } bound[i]=boundValue; if (fabs(boundValue)>1.0e10) numberBad++; } const double * rowLower = simplex->rowLower(); const double * rowUpper = simplex->rowUpper(); //int pivotRow = simplex->spareIntArray_[3]; //bool badPivot=pivotRow<0; for (int i=0;igetRowStatus(i)==ClpSimplex::basic) { // treat as zero if small if (fabs(value)<1.0e-8) { value=0.0; ray[i]=0.0; } if (value) { //printf("row basic %d direction %d ray %g\n", // i,simplex->directionOut(),value); if (value<0.0) rhsValue=rowLower[i]; else rhsValue=rowUpper[i]; } } else if (fabs(value)>1.0e-10) { if (value<0.0) rhsValue=rowLower[i]; else rhsValue=rowUpper[i]; } effectiveRhs[i]=rhsValue; } simplex->times(-1.0,bound,effectiveRhs); simplex->swapRowScale(saveScale); simplex->swapScaledMatrix(saveMatrix); double bSum=0.0; for (int i=0;i-1.0e-4) { #ifndef NDEBUG printf("bad BOUND bSum %g - %d bad\n", bSum,numberBad); #endif } else { const char * integerInformation = simplex->integerInformation(); assert (integerInformation); int * conflict = new int[numberColumns]; double * sort = new double [numberColumns]; double relax=0.0; int nConflict=0; int nOriginal=0; int nFixed=0; for (int iColumn=0;iColumngetStatus(iColumn),columnLower[iColumn], simplex->primalColumnSolution()[iColumn],columnUpper[iColumn], originalLower[iColumn],originalUpper[iColumn], farkas[iColumn]); double gap = originalUpper[iColumn]-originalLower[iColumn]; if (!gap) continue; if (gap==columnUpper[iColumn]-columnLower[iColumn]) nOriginal++; if (columnUpper[iColumn]==columnLower[iColumn]) nFixed++; if (fabs(farkas[iColumn])<1.0e-15) { farkas[iColumn]=0.0; continue; } // temp if (gap>=20000.0&&false) { // can't use if (farkas[iColumn]<0.0) { assert(originalLower[iColumn]-columnLower[iColumn]<=0.0); // farkas is negative - relax lower bound all way relax += farkas[iColumn]*(originalLower[iColumn]-columnLower[iColumn]); } else { assert(originalUpper[iColumn]-columnUpper[iColumn]>=0.0); // farkas is positive - relax upper bound all way relax += farkas[iColumn]*(originalUpper[iColumn]-columnUpper[iColumn]); } continue; } if (originalLower[iColumn]==columnLower[iColumn]) { if (farkas[iColumn]>0.0&&(simplex->getStatus(iColumn)==ClpSimplex::atUpperBound ||simplex->getStatus(iColumn)==ClpSimplex::isFixed ||iColumn==sequenceOut)) { // farkas is positive - add to list gap=originalUpper[iColumn]-columnUpper[iColumn]; if (gap) { sort[nConflict]=-farkas[iColumn]*gap; conflict[nConflict++]=iColumn; } //assert (gap>columnUpper[iColumn]-columnLower[iColumn]); } } else if (originalUpper[iColumn]==columnUpper[iColumn]) { if (farkas[iColumn]<0.0&&(simplex->getStatus(iColumn)==ClpSimplex::atLowerBound ||simplex->getStatus(iColumn)==ClpSimplex::isFixed ||iColumn==sequenceOut)) { // farkas is negative - add to list gap=columnLower[iColumn]-originalLower[iColumn]; if (gap) { sort[nConflict]=farkas[iColumn]*gap; conflict[nConflict++]=iColumn; } //assert (gap>columnUpper[iColumn]-columnLower[iColumn]); } } else { // can't use if (farkas[iColumn]<0.0) { assert(originalLower[iColumn]-columnLower[iColumn]<=0.0); // farkas is negative - relax lower bound all way relax += farkas[iColumn]*(originalLower[iColumn]-columnLower[iColumn]); } else { assert(originalUpper[iColumn]-columnUpper[iColumn]>=0.0); // farkas is positive - relax upper bound all way relax += farkas[iColumn]*(originalUpper[iColumn]-columnUpper[iColumn]); } } assert(relax>=0.0); } else { // not integer - but may have been got at double gap = originalUpper[iColumn]-originalLower[iColumn]; if (gap>columnUpper[iColumn]-columnLower[iColumn]) { // can't use if (farkas[iColumn]<0.0) { assert(originalLower[iColumn]-columnLower[iColumn]<=0.0); // farkas is negative - relax lower bound all way relax += farkas[iColumn]*(originalLower[iColumn]-columnLower[iColumn]); } else { assert(originalUpper[iColumn]-columnUpper[iColumn]>=0.0); // farkas is positive - relax upper bound all way relax += farkas[iColumn]*(originalUpper[iColumn]-columnUpper[iColumn]); } } } } if (relax+bSum>-1.0e-4||!nConflict) { if (relax+bSum>-1.0e-4) { #ifndef NDEBUG printf("General integers relax bSum to %g\n",relax+bSum); #endif } else { printf("All variables relaxed and still infeasible - what does this mean?\n"); int nR=0; for (int i=0;i1.0e-10) nR++; else ray[i]=0.0; } int nC=0; for (int i=0;i1.0e-10) nC++; else farkas[i]=0.0; } if (nR<3&&nC<5) { printf("BAD %d nonzero rows, %d nonzero columns\n",nR,nC); } } } else { printf("BOUNDS violation bSum %g (relaxed %g) - %d at original bounds, %d fixed - %d in conflict\n",bSum, relax+bSum,nOriginal,nFixed,nConflict); CoinSort_2(sort,sort+nConflict,conflict); int nC=nConflict; bSum+=relax; double saveBsum = bSum; while (nConflict) { //int iColumn=conflict[nConflict-1]; double change=-sort[nConflict-1]; if (bSum+change>-1.0e-4) break; nConflict--; bSum += change; } if (!nConflict) { int nR=0; for (int i=0;i1.0e-10) nR++; else ray[i]=0.0; } int nC=0; for (int i=0;i1.0e-10) nC++; else farkas[i]=0.0; } if (nR<3&&nC<5) { printf("BAD2 %d nonzero rows, %d nonzero columns\n",nR,nC); } } // no point doing if no reduction (or big?) ? if (nConflictsetUb(COIN_DBL_MAX); if (!typeCut) { double lo=1.0; for (int i=0;isetLb(lo); cut->setRow(nConflict,conflict,sort); printf("CUT has %d (started at %d) - final bSum %g\n",nConflict,nC,bSum); } else { // just save for use later // first take off small int nC2=nC; while (nC2) { //int iColumn=conflict[nConflict-1]; double change=-sort[nC2-1]; if (saveBsum+change>-1.0e-4||change>1.0e-4) break; nC2--; saveBsum += change; } cut->setLb(saveBsum); for (int i=0;isetRow(nC2,conflict,sort); printf("Stem CUT has %d (greedy %d - with small %d) - saved bSum %g final greedy bSum %g\n", nC2,nConflict,nC,saveBsum,bSum); } } } delete [] conflict; delete [] sort; } delete [] farkas; } else { printf("No dual ray\n"); } } #endif return cut; } Cbc-2.8.12/src/CbcHeuristicGreedy.cpp0000644000076600007660000017205212130105453015754 0ustar coincoin/* $Id: CbcHeuristicGreedy.cpp 1888 2013-04-06 20:52:59Z stefan $ */ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include #include "OsiSolverInterface.hpp" #include "CbcModel.hpp" #include "CbcStrategy.hpp" #include "CbcHeuristicGreedy.hpp" #include "CoinSort.hpp" #include "CglPreProcess.hpp" // Default Constructor CbcHeuristicGreedyCover::CbcHeuristicGreedyCover() : CbcHeuristic() { // matrix will automatically be empty originalNumberRows_ = 0; algorithm_ = 0; numberTimes_ = 100; } // Constructor from model CbcHeuristicGreedyCover::CbcHeuristicGreedyCover(CbcModel & model) : CbcHeuristic(model) { gutsOfConstructor(&model); algorithm_ = 0; numberTimes_ = 100; whereFrom_ = 1; } // Destructor CbcHeuristicGreedyCover::~CbcHeuristicGreedyCover () { } // Clone CbcHeuristic * CbcHeuristicGreedyCover::clone() const { return new CbcHeuristicGreedyCover(*this); } // Guts of constructor from a CbcModel void CbcHeuristicGreedyCover::gutsOfConstructor(CbcModel * model) { model_ = model; // Get a copy of original matrix assert(model->solver()); if (model->solver()->getNumRows()) { matrix_ = *model->solver()->getMatrixByCol(); } originalNumberRows_ = model->solver()->getNumRows(); } // Create C++ lines to get to current state void CbcHeuristicGreedyCover::generateCpp( FILE * fp) { CbcHeuristicGreedyCover other; fprintf(fp, "0#include \"CbcHeuristicGreedy.hpp\"\n"); fprintf(fp, "3 CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicGreedyCover"); if (algorithm_ != other.algorithm_) fprintf(fp, "3 heuristicGreedyCover.setAlgorithm(%d);\n", algorithm_); else fprintf(fp, "4 heuristicGreedyCover.setAlgorithm(%d);\n", algorithm_); if (numberTimes_ != other.numberTimes_) fprintf(fp, "3 heuristicGreedyCover.setNumberTimes(%d);\n", numberTimes_); else fprintf(fp, "4 heuristicGreedyCover.setNumberTimes(%d);\n", numberTimes_); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicGreedyCover);\n"); } // Copy constructor CbcHeuristicGreedyCover::CbcHeuristicGreedyCover(const CbcHeuristicGreedyCover & rhs) : CbcHeuristic(rhs), matrix_(rhs.matrix_), originalNumberRows_(rhs.originalNumberRows_), algorithm_(rhs.algorithm_), numberTimes_(rhs.numberTimes_) { } // Assignment operator CbcHeuristicGreedyCover & CbcHeuristicGreedyCover::operator=( const CbcHeuristicGreedyCover & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); matrix_ = rhs.matrix_; originalNumberRows_ = rhs.originalNumberRows_; algorithm_ = rhs.algorithm_; numberTimes_ = rhs.numberTimes_; } return *this; } // Returns 1 if solution, 0 if not int CbcHeuristicGreedyCover::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; if (!model_) return 0; // See if to do if (!when() || (when() == 1 && model_->phase() != 1)) return 0; // switched off if (model_->getNodeCount() > numberTimes_) return 0; // See if at root node bool atRoot = model_->getNodeCount() == 0; int passNumber = model_->getCurrentPassNumber(); if (atRoot && passNumber != 1) return 0; OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); // And original upper bounds in case we want to use them const double * originalUpper = model_->continuousSolver()->getColUpper(); // But not if algorithm says so if ((algorithm_ % 10) == 0) originalUpper = columnUpper; const double * rowLower = solver->getRowLower(); const double * solution = solver->getColSolution(); const double * objective = solver->getObjCoefficients(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // This is number of rows when matrix was passed in int numberRows = originalNumberRows_; if (!numberRows) return 0; // switched off numRuns_++; assert (numberRows == matrix_.getNumRows()); int iRow, iColumn; double direction = solver->getObjSense(); double offset; solver->getDblParam(OsiObjOffset, offset); double newSolutionValue = -offset; int returnCode = 0; // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Get solution array for heuristic solution int numberColumns = solver->getNumCols(); double * newSolution = new double [numberColumns]; double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); bool allOnes = true; // Get rounded down solution for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double value = solution[iColumn]; if (solver->isInteger(iColumn)) { // Round down integer if (fabs(floor(value + 0.5) - value) < integerTolerance) { value = floor(CoinMax(value + 1.0e-3, columnLower[iColumn])); } else { value = CoinMax(floor(value), columnLower[iColumn]); } } // make sure clean value = CoinMin(value, columnUpper[iColumn]); value = CoinMax(value, columnLower[iColumn]); newSolution[iColumn] = value; double cost = direction * objective[iColumn]; newSolutionValue += value * cost; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; if (element[j] != 1.0) allOnes = false; } } // See if we round up bool roundup = ((algorithm_ % 100) != 0); if (roundup && allOnes) { // Get rounded up solution for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double value = solution[iColumn]; if (solver->isInteger(iColumn)) { // but round up if no activity if (roundup && value >= 0.499999 && !newSolution[iColumn]) { bool choose = true; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (rowActivity[iRow]) { choose = false; break; } } if (choose) { newSolution[iColumn] = 1.0; double cost = direction * objective[iColumn]; newSolutionValue += cost; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += 1.0; } } } } } } // Get initial list int * which = new int [numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) which[iColumn] = iColumn; int numberLook = numberColumns; // See if we want to perturb more double perturb = ((algorithm_ % 10) == 0) ? 0.1 : 0.25; // Keep going round until a solution while (true) { // Get column with best ratio int bestColumn = -1; double bestRatio = COIN_DBL_MAX; double bestStepSize = 0.0; int newNumber = 0; for (int jColumn = 0; jColumn < numberLook; jColumn++) { int iColumn = which[jColumn]; CoinBigIndex j; double value = newSolution[iColumn]; double cost = direction * objective[iColumn]; if (solver->isInteger(iColumn)) { // use current upper or original upper if (value + 0.99 < originalUpper[iColumn]) { double sum = 0.0; int numberExact = 0; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double gap = rowLower[iRow] - rowActivity[iRow]; double elementValue = allOnes ? 1.0 : element[j]; if (gap > 1.0e-7) { sum += CoinMin(elementValue, gap); if (fabs(elementValue - gap) < 1.0e-7) numberExact++; } } // could bias if exact if (sum > 0.0) { // add to next time which[newNumber++] = iColumn; double ratio = (cost / sum) * (1.0 + perturb * randomNumberGenerator_.randomDouble()); // If at root choose first if (atRoot) ratio = iColumn; if (ratio < bestRatio) { bestRatio = ratio; bestColumn = iColumn; bestStepSize = 1.0; } } } } else { // continuous if (value < columnUpper[iColumn]) { // Go through twice - first to get step length double step = 1.0e50; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (rowActivity[iRow] < rowLower[iRow] - 1.0e-10 && element[j]*step + rowActivity[iRow] >= rowLower[iRow]) { step = (rowLower[iRow] - rowActivity[iRow]) / element[j];; } } // now ratio if (step < 1.0e50) { // add to next time which[newNumber++] = iColumn; assert (step > 0.0); double sum = 0.0; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double newActivity = element[j] * step + rowActivity[iRow]; if (rowActivity[iRow] < rowLower[iRow] - 1.0e-10 && newActivity >= rowLower[iRow] - 1.0e-12) { sum += element[j]; } } assert (sum > 0.0); double ratio = (cost / sum) * (1.0 + perturb * randomNumberGenerator_.randomDouble()); if (ratio < bestRatio) { bestRatio = ratio; bestColumn = iColumn; bestStepSize = step; } } } } } if (bestColumn < 0) break; // we have finished // Increase chosen column newSolution[bestColumn] += bestStepSize; double cost = direction * objective[bestColumn]; newSolutionValue += bestStepSize * cost; for (CoinBigIndex j = columnStart[bestColumn]; j < columnStart[bestColumn] + columnLength[bestColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += bestStepSize * element[j]; } } delete [] which; if (newSolutionValue < solutionValue) { // check feasible memset(rowActivity, 0, numberRows*sizeof(double)); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double value = newSolution[iColumn]; if (value) { for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } // check was approximately feasible bool feasible = true; for (iRow = 0; iRow < numberRows; iRow++) { if (rowActivity[iRow] < rowLower[iRow]) { if (rowActivity[iRow] < rowLower[iRow] - 10.0*primalTolerance) feasible = false; } } if (feasible) { // new solution memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); solutionValue = newSolutionValue; //printf("** Solution of %g found by rounding\n",newSolutionValue); returnCode = 1; } else { // Can easily happen //printf("Debug CbcHeuristicGreedyCover giving bad solution\n"); } } delete [] newSolution; delete [] rowActivity; return returnCode; } // update model void CbcHeuristicGreedyCover::setModel(CbcModel * model) { gutsOfConstructor(model); validate(); } // Resets stuff if model changes void CbcHeuristicGreedyCover::resetModel(CbcModel * model) { gutsOfConstructor(model); } // Validate model i.e. sets when_ to 0 if necessary (may be NULL) void CbcHeuristicGreedyCover::validate() { if (model_ && when() < 10) { if (model_->numberIntegers() != model_->numberObjects() && (model_->numberObjects() || (model_->specialOptions()&1024) == 0)) { int numberOdd = 0; for (int i = 0; i < model_->numberObjects(); i++) { if (!model_->object(i)->canDoHeuristics()) numberOdd++; } if (numberOdd) setWhen(0); } // Only works if costs positive, coefficients positive and all rows G OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); const double * rowUpper = solver->getRowUpper(); const double * objective = solver->getObjCoefficients(); double direction = solver->getObjSense(); int numberRows = solver->getNumRows(); int numberColumns = solver->getNumCols(); // Column copy matrix_.setDimensions(numberRows,numberColumns); const double * element = matrix_.getElements(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); bool good = true; for (int iRow = 0; iRow < numberRows; iRow++) { if (rowUpper[iRow] < 1.0e30) good = false; } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (objective[iColumn]*direction < 0.0) good = false; if (columnLower[iColumn] < 0.0) good = false; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { if (element[j] < 0.0) good = false; } } if (!good) setWhen(0); // switch off } } // Default Constructor CbcHeuristicGreedyEquality::CbcHeuristicGreedyEquality() : CbcHeuristic() { // matrix will automatically be empty fraction_ = 1.0; // no branch and bound originalNumberRows_ = 0; algorithm_ = 0; numberTimes_ = 100; whereFrom_ = 1; } // Constructor from model CbcHeuristicGreedyEquality::CbcHeuristicGreedyEquality(CbcModel & model) : CbcHeuristic(model) { // Get a copy of original matrix gutsOfConstructor(&model); fraction_ = 1.0; // no branch and bound algorithm_ = 0; numberTimes_ = 100; whereFrom_ = 1; } // Destructor CbcHeuristicGreedyEquality::~CbcHeuristicGreedyEquality () { } // Clone CbcHeuristic * CbcHeuristicGreedyEquality::clone() const { return new CbcHeuristicGreedyEquality(*this); } // Guts of constructor from a CbcModel void CbcHeuristicGreedyEquality::gutsOfConstructor(CbcModel * model) { model_ = model; // Get a copy of original matrix assert(model->solver()); if (model->solver()->getNumRows()) { matrix_ = *model->solver()->getMatrixByCol(); } originalNumberRows_ = model->solver()->getNumRows(); } // Create C++ lines to get to current state void CbcHeuristicGreedyEquality::generateCpp( FILE * fp) { CbcHeuristicGreedyEquality other; fprintf(fp, "0#include \"CbcHeuristicGreedy.hpp\"\n"); fprintf(fp, "3 CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicGreedyEquality"); if (algorithm_ != other.algorithm_) fprintf(fp, "3 heuristicGreedyEquality.setAlgorithm(%d);\n", algorithm_); else fprintf(fp, "4 heuristicGreedyEquality.setAlgorithm(%d);\n", algorithm_); if (fraction_ != other.fraction_) fprintf(fp, "3 heuristicGreedyEquality.setFraction(%g);\n", fraction_); else fprintf(fp, "4 heuristicGreedyEquality.setFraction(%g);\n", fraction_); if (numberTimes_ != other.numberTimes_) fprintf(fp, "3 heuristicGreedyEquality.setNumberTimes(%d);\n", numberTimes_); else fprintf(fp, "4 heuristicGreedyEquality.setNumberTimes(%d);\n", numberTimes_); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicGreedyEquality);\n"); } // Copy constructor CbcHeuristicGreedyEquality::CbcHeuristicGreedyEquality(const CbcHeuristicGreedyEquality & rhs) : CbcHeuristic(rhs), matrix_(rhs.matrix_), fraction_(rhs.fraction_), originalNumberRows_(rhs.originalNumberRows_), algorithm_(rhs.algorithm_), numberTimes_(rhs.numberTimes_) { } // Assignment operator CbcHeuristicGreedyEquality & CbcHeuristicGreedyEquality::operator=( const CbcHeuristicGreedyEquality & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); matrix_ = rhs.matrix_; fraction_ = rhs.fraction_; originalNumberRows_ = rhs.originalNumberRows_; algorithm_ = rhs.algorithm_; numberTimes_ = rhs.numberTimes_; } return *this; } // Returns 1 if solution, 0 if not int CbcHeuristicGreedyEquality::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; if (!model_) return 0; // See if to do if (!when() || (when() == 1 && model_->phase() != 1)) return 0; // switched off if (model_->getNodeCount() > numberTimes_) return 0; // See if at root node bool atRoot = model_->getNodeCount() == 0; int passNumber = model_->getCurrentPassNumber(); if (atRoot && passNumber != 1) return 0; OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); // And original upper bounds in case we want to use them const double * originalUpper = model_->continuousSolver()->getColUpper(); // But not if algorithm says so if ((algorithm_ % 10) == 0) originalUpper = columnUpper; const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); const double * solution = solver->getColSolution(); const double * objective = solver->getObjCoefficients(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // This is number of rows when matrix was passed in int numberRows = originalNumberRows_; if (!numberRows) return 0; // switched off numRuns_++; assert (numberRows == matrix_.getNumRows()); int iRow, iColumn; double direction = solver->getObjSense(); double offset; solver->getDblParam(OsiObjOffset, offset); double newSolutionValue = -offset; int returnCode = 0; // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); // Get solution array for heuristic solution int numberColumns = solver->getNumCols(); double * newSolution = new double [numberColumns]; double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); double rhsNeeded = 0; for (iRow = 0; iRow < numberRows; iRow++) rhsNeeded += rowUpper[iRow]; rhsNeeded *= fraction_; bool allOnes = true; // Get rounded down solution for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double value = solution[iColumn]; if (solver->isInteger(iColumn)) { // Round down integer if (fabs(floor(value + 0.5) - value) < integerTolerance) { value = floor(CoinMax(value + 1.0e-3, columnLower[iColumn])); } else { value = CoinMax(floor(value), columnLower[iColumn]); } } // make sure clean value = CoinMin(value, columnUpper[iColumn]); value = CoinMax(value, columnLower[iColumn]); newSolution[iColumn] = value; double cost = direction * objective[iColumn]; newSolutionValue += value * cost; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; rhsNeeded -= value * element[j]; if (element[j] != 1.0) allOnes = false; } } // See if we round up bool roundup = ((algorithm_ % 100) != 0); if (roundup && allOnes) { // Get rounded up solution for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double value = solution[iColumn]; if (solver->isInteger(iColumn)) { // but round up if no activity if (roundup && value >= 0.6 && !newSolution[iColumn]) { bool choose = true; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (rowActivity[iRow]) { choose = false; break; } } if (choose) { newSolution[iColumn] = 1.0; double cost = direction * objective[iColumn]; newSolutionValue += cost; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += 1.0; rhsNeeded -= 1.0; } } } } } } // Get initial list int * which = new int [numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) which[iColumn] = iColumn; int numberLook = numberColumns; // See if we want to perturb more double perturb = ((algorithm_ % 10) == 0) ? 0.1 : 0.25; // Keep going round until a solution while (true) { // Get column with best ratio int bestColumn = -1; double bestRatio = COIN_DBL_MAX; double bestStepSize = 0.0; int newNumber = 0; for (int jColumn = 0; jColumn < numberLook; jColumn++) { int iColumn = which[jColumn]; CoinBigIndex j; double value = newSolution[iColumn]; double cost = direction * objective[iColumn]; if (solver->isInteger(iColumn)) { // use current upper or original upper if (value + 0.9999 < originalUpper[iColumn]) { double movement = 1.0; double sum = 0.0; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double gap = rowUpper[iRow] - rowActivity[iRow]; double elementValue = allOnes ? 1.0 : element[j]; sum += elementValue; if (movement*elementValue > gap) { movement = gap / elementValue; } } if (movement > 0.999999) { // add to next time which[newNumber++] = iColumn; double ratio = (cost / sum) * (1.0 + perturb * randomNumberGenerator_.randomDouble()); // If at root if (atRoot) { if (fraction_ == 1.0) ratio = iColumn; // choose first else ratio = - solution[iColumn]; // choose largest } if (ratio < bestRatio) { bestRatio = ratio; bestColumn = iColumn; bestStepSize = 1.0; } } } } else { // continuous if (value < columnUpper[iColumn]) { double movement = 1.0e50; double sum = 0.0; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (element[j]*movement + rowActivity[iRow] > rowUpper[iRow]) { movement = (rowUpper[iRow] - rowActivity[iRow]) / element[j];; } sum += element[j]; } // now ratio if (movement > 1.0e-7) { // add to next time which[newNumber++] = iColumn; double ratio = (cost / sum) * (1.0 + perturb * randomNumberGenerator_.randomDouble()); if (ratio < bestRatio) { bestRatio = ratio; bestColumn = iColumn; bestStepSize = movement; } } } } } if (bestColumn < 0) break; // we have finished // Increase chosen column newSolution[bestColumn] += bestStepSize; double cost = direction * objective[bestColumn]; newSolutionValue += bestStepSize * cost; for (CoinBigIndex j = columnStart[bestColumn]; j < columnStart[bestColumn] + columnLength[bestColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += bestStepSize * element[j]; rhsNeeded -= bestStepSize * element[j]; } if (rhsNeeded < 1.0e-8) break; } delete [] which; if (fraction_ < 1.0 && rhsNeeded < 1.0e-8 && newSolutionValue < solutionValue) { // do branch and cut // fix all nonzero OsiSolverInterface * newSolver = model_->continuousSolver()->clone(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (newSolver->isInteger(iColumn)) newSolver->setColLower(iColumn, newSolution[iColumn]); } int returnCode = smallBranchAndBound(newSolver, 200, newSolution, newSolutionValue, solutionValue, "CbcHeuristicGreedy"); if (returnCode < 0) returnCode = 0; // returned on size if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } rhsNeeded = 1.0 - returnCode; delete newSolver; } if (newSolutionValue < solutionValue && rhsNeeded < 1.0e-8) { // check feasible memset(rowActivity, 0, numberRows*sizeof(double)); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double value = newSolution[iColumn]; if (value) { for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } // check was approximately feasible bool feasible = true; for (iRow = 0; iRow < numberRows; iRow++) { if (rowActivity[iRow] < rowLower[iRow]) { if (rowActivity[iRow] < rowLower[iRow] - 10.0*primalTolerance) feasible = false; } } if (feasible) { // new solution memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); solutionValue = newSolutionValue; returnCode = 1; } } delete [] newSolution; delete [] rowActivity; if (atRoot && fraction_ == 1.0) { // try quick search fraction_ = 0.4; int newCode = this->solution(solutionValue, betterSolution); if (newCode) returnCode = 1; fraction_ = 1.0; } return returnCode; } // update model void CbcHeuristicGreedyEquality::setModel(CbcModel * model) { gutsOfConstructor(model); validate(); } // Resets stuff if model changes void CbcHeuristicGreedyEquality::resetModel(CbcModel * model) { gutsOfConstructor(model); } // Validate model i.e. sets when_ to 0 if necessary (may be NULL) void CbcHeuristicGreedyEquality::validate() { if (model_ && when() < 10) { if (model_->numberIntegers() != model_->numberObjects()) setWhen(0); // Only works if costs positive, coefficients positive and all rows E or L // And if values are integer OsiSolverInterface * solver = model_->solver(); const double * columnLower = solver->getColLower(); const double * rowUpper = solver->getRowUpper(); const double * rowLower = solver->getRowLower(); const double * objective = solver->getObjCoefficients(); double direction = solver->getObjSense(); int numberRows = solver->getNumRows(); int numberColumns = solver->getNumCols(); matrix_.setDimensions(numberRows,numberColumns); // Column copy const double * element = matrix_.getElements(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); bool good = true; for (int iRow = 0; iRow < numberRows; iRow++) { if (rowUpper[iRow] > 1.0e30) good = false; if (rowLower[iRow] > 0.0 && rowLower[iRow] != rowUpper[iRow]) good = false; if (floor(rowUpper[iRow] + 0.5) != rowUpper[iRow]) good = false; } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (objective[iColumn]*direction < 0.0) good = false; if (columnLower[iColumn] < 0.0) good = false; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { if (element[j] < 0.0) good = false; if (floor(element[j] + 0.5) != element[j]) good = false; } } if (!good) setWhen(0); // switch off } } // Default Constructor CbcHeuristicGreedySOS::CbcHeuristicGreedySOS() : CbcHeuristic() { originalRhs_ = NULL; // matrix will automatically be empty originalNumberRows_ = 0; algorithm_ = 0; numberTimes_ = 100; } // Constructor from model CbcHeuristicGreedySOS::CbcHeuristicGreedySOS(CbcModel & model) : CbcHeuristic(model) { gutsOfConstructor(&model); algorithm_ = 2; numberTimes_ = 100; whereFrom_ = 1; } // Destructor CbcHeuristicGreedySOS::~CbcHeuristicGreedySOS () { delete [] originalRhs_; } // Clone CbcHeuristic * CbcHeuristicGreedySOS::clone() const { return new CbcHeuristicGreedySOS(*this); } // Guts of constructor from a CbcModel void CbcHeuristicGreedySOS::gutsOfConstructor(CbcModel * model) { model_ = model; // Get a copy of original matrix assert(model->solver()); if (model->solver()->getNumRows()) { matrix_ = *model->solver()->getMatrixByCol(); } originalNumberRows_ = model->solver()->getNumRows(); originalRhs_ = new double [originalNumberRows_]; } // Create C++ lines to get to current state void CbcHeuristicGreedySOS::generateCpp( FILE * fp) { CbcHeuristicGreedySOS other; fprintf(fp, "0#include \"CbcHeuristicGreedy.hpp\"\n"); fprintf(fp, "3 CbcHeuristicGreedySOS heuristicGreedySOS(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicGreedySOS"); if (algorithm_ != other.algorithm_) fprintf(fp, "3 heuristicGreedySOS.setAlgorithm(%d);\n", algorithm_); else fprintf(fp, "4 heuristicGreedySOS.setAlgorithm(%d);\n", algorithm_); if (numberTimes_ != other.numberTimes_) fprintf(fp, "3 heuristicGreedySOS.setNumberTimes(%d);\n", numberTimes_); else fprintf(fp, "4 heuristicGreedySOS.setNumberTimes(%d);\n", numberTimes_); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicGreedySOS);\n"); } // Copy constructor CbcHeuristicGreedySOS::CbcHeuristicGreedySOS(const CbcHeuristicGreedySOS & rhs) : CbcHeuristic(rhs), matrix_(rhs.matrix_), originalNumberRows_(rhs.originalNumberRows_), algorithm_(rhs.algorithm_), numberTimes_(rhs.numberTimes_) { originalRhs_ = CoinCopyOfArray(rhs.originalRhs_,originalNumberRows_); } // Assignment operator CbcHeuristicGreedySOS & CbcHeuristicGreedySOS::operator=( const CbcHeuristicGreedySOS & rhs) { if (this != &rhs) { CbcHeuristic::operator=(rhs); matrix_ = rhs.matrix_; originalNumberRows_ = rhs.originalNumberRows_; algorithm_ = rhs.algorithm_; numberTimes_ = rhs.numberTimes_; delete [] originalRhs_; originalRhs_ = CoinCopyOfArray(rhs.originalRhs_,originalNumberRows_); } return *this; } // Returns 1 if solution, 0 if not int CbcHeuristicGreedySOS::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; if (!model_) return 0; // See if to do if (!when() || (when() == 1 && model_->phase() != 1)) return 0; // switched off if (model_->getNodeCount() > numberTimes_) return 0; // See if at root node bool atRoot = model_->getNodeCount() == 0; int passNumber = model_->getCurrentPassNumber(); if (atRoot && passNumber != 1) return 0; OsiSolverInterface * solver = model_->solver(); int numberColumns = solver->getNumCols(); // This is number of rows when matrix was passed in int numberRows = originalNumberRows_; if (!numberRows) return 0; // switched off const double * columnLower = solver->getColLower(); const double * columnUpper = solver->getColUpper(); // modified rhs double * rhs = CoinCopyOfArray(originalRhs_,numberRows); // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); int * sosRow = new int [numberColumns]; int nonSOS=0; // If bit set then use current if ((algorithm_&1)!=0) { const CoinPackedMatrix * matrix = solver->getMatrixByCol(); element = matrix->getElements(); row = matrix->getIndices(); columnStart = matrix->getVectorStarts(); columnLength = matrix->getVectorLengths(); //rhs = new double [numberRows]; const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); bool good = true; for (int iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0) { // SOS rhs[iRow]=-1.0; } else if (rowLower[iRow] > 0.0 && rowUpper[iRow] < 1.0e10) { good = false; } else if (rowUpper[iRow] < 0.0) { good = false; } else if (rowUpper[iRow] < 1.0e10) { rhs[iRow]=rowUpper[iRow]; } else { rhs[iRow]=rowLower[iRow]; } } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!columnLength[iColumn]) continue; if (columnLower[iColumn] < 0.0 || columnUpper[iColumn] > 1.0) good = false; CoinBigIndex j; int nSOS=0; int iSOS=-1; if (!solver->isInteger(iColumn)) good = false; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { if (element[j] < 0.0) good = false; int iRow = row[j]; if (rhs[iRow]==-1.0) { if (element[j] != 1.0) good = false; iSOS=iRow; nSOS++; } } if (nSOS>1) good = false; else if (!nSOS) nonSOS++; sosRow[iColumn] = iSOS; } if (!good) { delete [] sosRow; delete [] rhs; setWhen(0); // switch off return 0; } } else { abort(); // not allowed yet } const double * solution = solver->getColSolution(); const double * objective = solver->getObjCoefficients(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); numRuns_++; assert (numberRows == matrix_.getNumRows()); // set up linked list for sets int * firstGub = new int [numberRows]; int * nextGub = new int [numberColumns]; int iRow, iColumn; double direction = solver->getObjSense(); double * slackCost = new double [numberRows]; double * modifiedCost = CoinCopyOfArray(objective,numberColumns); for (int iRow = 0;iRow < numberRows; iRow++) { slackCost[iRow]=1.0e30; firstGub[iRow]=-1; } // Take off cost of gub slack for (int iColumn = 0; iColumn < numberColumns; iColumn++) { nextGub[iColumn]=-1; int iRow = sosRow[iColumn]; if (columnLength[iColumn] == 1&&iRow>=0) { // SOS slack double cost = direction*objective[iColumn]; assert (rhs[iRow]<0.0); slackCost[iRow]=CoinMin(slackCost[iRow],cost); } } double offset2 = 0.0; char * sos = new char [numberRows]; for (int iRow = 0;iRow < numberRows; iRow++) { sos[iRow]=0; if (rhs[iRow]<0.0) { sos[iRow]=1; rhs[iRow]=1.0; } else if (rhs[iRow] != rowUpper[iRow]) { // G row sos[iRow]=-1; } if( slackCost[iRow] == 1.0e30) { slackCost[iRow]=0.0; } else { offset2 += slackCost[iRow]; sos[iRow] = 2; } } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double cost = direction * modifiedCost[iColumn]; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (sos[iRow]>0) { cost -= slackCost[iRow]; if (firstGub[iRow]<0) { firstGub[iRow]=iColumn; } else { int jColumn = firstGub[iRow]; while (nextGub[jColumn]>=0) jColumn=nextGub[jColumn]; nextGub[jColumn]=iColumn; } // Only in one sos break; } } modifiedCost[iColumn] = cost; } delete [] slackCost; double offset; solver->getDblParam(OsiObjOffset, offset); double newSolutionValue = -offset+offset2; int returnCode = 0; // Get solution array for heuristic solution double * newSolution = new double [numberColumns]; double * rowActivity = new double[numberRows]; double * contribution = new double [numberColumns]; int * which = new int [numberColumns]; double * newSolution0 = new double [numberColumns]; if ((algorithm_&(2|4))==0) { // get solution as small as possible for (iColumn = 0; iColumn < numberColumns; iColumn++) newSolution0[iColumn] = columnLower[iColumn]; } else { // Get rounded down solution for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = solution[iColumn]; // Round down integer if (fabs(floor(value + 0.5) - value) < integerTolerance) { value = floor(CoinMax(value + 1.0e-3, columnLower[iColumn])); } else { value = CoinMax(floor(value), columnLower[iColumn]); } // make sure clean value = CoinMin(value, columnUpper[iColumn]); value = CoinMax(value, columnLower[iColumn]); newSolution0[iColumn] = value; } } double * rowWeight = new double [numberRows]; for (int i=0;irowWeight[iRow]||(algorithm_&(2|4))!=0) forSort += element[j]; else forSort += 0.1*element[j]; #else forSort += rowWeight[iRow]*element[j]; #endif break; case 0: // L row if (gap 1.0e-24) forSort=1.0; // Use smallest cost if will fit if (willFit && (hasSlack||gRow) && value == 0.0 && columnUpper[iColumn]) { if (hasSlack && !gRow) { if (cost>1.0e-12) { forSort = 2.0e30; } else if (cost==1.0e-12) { if (!isSlack) forSort = 1.0e29; else forSort = 1.0e28; } else { forSort = cost/forSort; } } else { if (!gRow||true) forSort = (cost+costBias)/forSort; else forSort = 1.0e-12/forSort; } } else { // put at end forSort = 1.0e30; } which[iColumn]=iColumn; contribution[iColumn]= forSort; } CoinSort_2(contribution,contribution+numberColumns,which); // Go through columns int nAdded=0; int nSlacks=0; for (int jColumn = 0; jColumn < numberColumns; jColumn++) { if (contribution[jColumn]>=1.0e30) break; int iColumn = which[jColumn]; double value = newSolution[iColumn]; if (value) continue; bool possible = true; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (sos[iRow]>0&&rowActivity[iRow]) { possible = false; } else { double gap = rhs[iRow] - rowActivity[iRow]+1.0e-8; if (gap=0) possible = false; } } if (possible) { //#define REPORT 1 #ifdef REPORT if ((nAdded%1000)==0) { double gap=0.0; for (int i=0;i1.0e20) gap += CoinMax(rowLower[i]-rowActivity[i],0.0); } if (gap) printf("after %d added gap %g - %d slacks\n", nAdded,gap,nSlacks); } #endif nAdded++; if (columnLength[iColumn]==1) nSlacks++; // Increase chosen column newSolution[iColumn] = 1.0; double cost = modifiedCost[iColumn]; newSolutionValue += cost; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += element[j]; } } } #ifdef REPORT { double under=0.0; double over=0.0; double gap = 0.0; int nUnder=0; int nOver=0; int nGap=0; for (iRow = 0; iRow < numberRows; iRow++) { if (rowActivity[iRow] < rowLower[iRow] - 10.0*primalTolerance) { double value = rowLower[iRow]-rowActivity[iRow]; #if REPORT>1 printf("below on %d is %g - activity %g lower %g\n", iRow,value,rowActivity[iRow],rowLower[iRow]); #endif under += value; nUnder++; } else if (rowActivity[iRow] > rowUpper[iRow] + 10.0*primalTolerance) { double value = rowActivity[iRow]-rowUpper[iRow]; #if REPORT>1 printf("above on %d is %g - activity %g upper %g\n", iRow,value,rowActivity[iRow],rowUpper[iRow]); #endif over += value; nOver++; } else { double value = rowActivity[iRow]-rowLower[iRow]; if (value && value < 1.0e20) { #if REPORT>1 printf("gap on %d is %g - activity %g lower %g\n", iRow,value,rowActivity[iRow],rowLower[iRow]); #endif gap += value; nGap++; } } } printf("final under %g (%d) - over %g (%d) - free %g (%d) - %d added - solvalue %g\n", under,nUnder,over,nOver,gap,nGap,nAdded,newSolutionValue); } #endif double gap = 0.0; double over = 0.0; int nL=0; int nG=0; int nUnder=0; for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow]<-1.0e20) nL++; if (rowUpper[iRow]>1.0e20) nG++; if (rowActivity[iRow] < rowLower[iRow] - 10.0*primalTolerance) { gap += rowLower[iRow]-rowActivity[iRow]; nUnder++; rowWeight[iRow] *= 1.1; } else if (rowActivity[iRow] > rowUpper[iRow] + 10.0*primalTolerance) { gap += rowActivity[iRow]-rowUpper[iRow]; } else { over += rowActivity[iRow]-rowLower[iRow]; //rowWeight[iRow] *= 0.9; } } if (nG&&!nL) { // can we fix // get list of columns which can go down without making // things much worse int nPossible=0; int nEasyDown=0; int nSlackDown=0; for (int iColumn=0;iColumncolumnLower[iColumn]) { bool canGoDown=true; bool under = false; int iSos=-1; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (sos[iRow]<0) { double over = rowActivity[iRow]-rowLower[iRow]; if (over>=0.0&&element[j]>over+1.0e-12) { canGoDown=false; break; } else if (over<0.0) { under = true; } } else { iSos=iRow; } } if (canGoDown) { if (!under) { if (iSos>=0) { // find cheapest double cheapest=modifiedCost[iColumn]; int iCheapest = -1; int jColumn = firstGub[iSos]; assert (jColumn>=0); while (jColumn>=0) { if (modifiedCost[jColumn]=0) { // Decrease column newSolution[iColumn] = 0.0; newSolutionValue -= modifiedCost[iColumn]; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] -= element[j]; } // Increase chosen column newSolution[iCheapest] = 1.0; newSolutionValue += modifiedCost[iCheapest]; for (CoinBigIndex j = columnStart[iCheapest]; j < columnStart[iCheapest] + columnLength[iCheapest]; j++) { int iRow = row[j]; rowActivity[iRow] += element[j]; } nEasyDown++; if (columnLength[iColumn]>1) { //printf("%d is easy down\n",iColumn); } else { nSlackDown++; } } } else if (modifiedCost[iColumn]>0.0) { // easy down // Decrease column newSolution[iColumn] = 0.0; newSolutionValue -= modifiedCost[iColumn]; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] -= element[j]; } nEasyDown++; } } else { which[nPossible++]=iColumn; } } } } #ifdef REPORT printf("%d possible down, %d easy down of which %d are slacks\n", nPossible,nEasyDown,nSlackDown); #endif double * needed = new double [numberRows]; for (int i=0;icolumnLower[iColumn]) { int iSos=-1; double value=0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (sos[iRow]<0) { if (needed[iRow]) value += CoinMin(element[j]/needed[iRow],1.0); } else { iSos=iRow; } } if (value && iSos<0) { weight[nPossible]=-value; sort[nPossible++]=iColumn; } } } CoinSort_2(weight,weight+nPossible,sort); for (int i=0;ibestSolution()) { double * weight = new double [numberColumns]; int * sort = new int [numberColumns]; // look at ones in sets const double * goodSolution = model_->bestSolution(); int nPossible=0; double largestWeight=0.0; for (int iColumn=0;iColumncolumnLower[iColumn]) { int iSos=-1; double value=0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (sos[iRow]<0) { if (needed[iRow]) value += CoinMin(element[j]/needed[iRow],1.0); } else { iSos=iRow; } } if (value&&iSos>=0) { // see if value bigger than current int jColumn = firstGub[iSos]; assert (jColumn>=0); while (jColumn>=0) { if (newSolution[jColumn]) break; jColumn = nextGub[jColumn]; } assert (jColumn>=0); double value2=0.0; for (CoinBigIndex j = columnStart[jColumn]; j < columnStart[jColumn] + columnLength[jColumn]; j++) { int iRow = row[j]; if (needed[iRow]) value2 += CoinMin(element[j]/needed[iRow],1.0); } if (value>value2) { weight[nPossible]=-(value-value2); largestWeight = CoinMax(largestWeight,(value-value2)); sort[nPossible++]=iColumn; } } } } if (nPossible) { double * temp = new double [numberRows]; int * which2 = new int [numberRows]; memset(temp,0,numberRows*sizeof(double)); // modify so ones just more than gap best if (largestWeight>gap&&nUnder==1) { double offset = 4*largestWeight; for (int i=0;igap-1.0e-12) weight[i] = -(offset-(value-gap)); } } CoinSort_2(weight,weight+nPossible,sort); for (int i=0;i=0) { iSos=iRow; } } int jColumn = firstGub[iSos]; assert (jColumn>=0); while (jColumn>=0) { if (newSolution[jColumn]) break; jColumn = nextGub[jColumn]; } assert (jColumn>=0); for (CoinBigIndex j = columnStart[jColumn]; j < columnStart[jColumn] + columnLength[jColumn]; j++) { int iRow = row[j]; if (!temp[iRow]) which2[n++]=iRow; temp[iRow] -= element[j]; } double helps = 0.0; for (int i=0;i1.0e-8) { if (rowActivity[iRow]0.0) { newSolution[iColumn]=1.0; newSolution[jColumn]=0.0; newSolutionValue += modifiedCost[iColumn]-modifiedCost[jColumn]; for (int i=0;i1 printf("below on %d is %g - activity %g lower %g\n", iRow,value,rowActivity[iRow],rowLower[iRow]); #endif gap += value; } else if (rowActivity[iRow] > rowUpper[iRow] + 10.0*primalTolerance) { double value = rowActivity[iRow]-rowUpper[iRow]; #if REPORT>1 printf("above on %d is %g - activity %g upper %g\n", iRow,value,rowActivity[iRow],rowUpper[iRow]); #endif gap += value; } else { double value = rowActivity[iRow]-rowLower[iRow]; if (value) { #if REPORT>1 printf("over on %d is %g - activity %g lower %g\n", iRow,value,rowActivity[iRow],rowLower[iRow]); #endif over += value; } } } printf("modified final gap %g - over %g - %d added - solvalue %g\n", gap,over,nAdded,newSolutionValue); } #endif if (!gap) { break; } else { if (iPass==0) { costBias = 10.0*newSolutionValue/static_cast(nAdded); } else { costBias *= 10.0; } } } delete [] newSolution0; delete [] rowWeight; delete [] sos; delete [] firstGub; delete [] nextGub; if (newSolutionValue < solutionValue) { // check feasible memset(rowActivity, 0, numberRows*sizeof(double)); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double value = newSolution[iColumn]; if (value) { for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } // check was approximately feasible bool feasible = true; for (iRow = 0; iRow < numberRows; iRow++) { if (rowActivity[iRow] < rowLower[iRow]) { if (rowActivity[iRow] < rowLower[iRow] - 10.0*primalTolerance) feasible = false; } else if (rowActivity[iRow] > rowUpper[iRow]) { if (rowActivity[iRow] > rowUpper[iRow] + 10.0*primalTolerance) feasible = false; } } if (feasible) { // new solution memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); solutionValue = newSolutionValue; //printf("** Solution of %g found by rounding\n",newSolutionValue); returnCode = 1; } else { // Can easily happen //printf("Debug CbcHeuristicGreedySOS giving bad solution\n"); } } delete [] sosRow; delete [] newSolution; delete [] rowActivity; delete [] modifiedCost; delete [] contribution; delete [] which; delete [] rhs; return returnCode; } // update model void CbcHeuristicGreedySOS::setModel(CbcModel * model) { delete [] originalRhs_; gutsOfConstructor(model); validate(); } // Resets stuff if model changes void CbcHeuristicGreedySOS::resetModel(CbcModel * model) { delete [] originalRhs_; gutsOfConstructor(model); } // Validate model i.e. sets when_ to 0 if necessary (may be NULL) void CbcHeuristicGreedySOS::validate() { if (model_ && when() < 10) { if (model_->numberIntegers() != model_->numberObjects() && (model_->numberObjects() || (model_->specialOptions()&1024) == 0)) { int numberOdd = 0; for (int i = 0; i < model_->numberObjects(); i++) { if (!model_->object(i)->canDoHeuristics()) numberOdd++; } if (numberOdd) setWhen(0); } // Only works if coefficients positive and all rows L/G or SOS OsiSolverInterface * solver = model_->solver(); const double * columnUpper = solver->getColUpper(); const double * columnLower = solver->getColLower(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); int numberRows = solver->getNumRows(); // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); bool good = true; assert (originalRhs_); for (int iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0) { // SOS originalRhs_[iRow]=-1.0; } else if (rowLower[iRow] > 0.0 && rowUpper[iRow] < 1.0e10) { good = false; } else if (rowUpper[iRow] < 0.0) { good = false; } else if (rowUpper[iRow] < 1.0e10) { originalRhs_[iRow]=rowUpper[iRow]; } else { originalRhs_[iRow]=rowLower[iRow]; } } int numberColumns = solver->getNumCols(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!columnLength[iColumn]) continue; if (columnLower[iColumn] < 0.0 || columnUpper[iColumn] > 1.0) good = false; CoinBigIndex j; int nSOS=0; if (!solver->isInteger(iColumn)) good = false; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { if (element[j] < 0.0) good = false; int iRow = row[j]; if (originalRhs_[iRow]==-1.0) { if (element[j] != 1.0) good = false; nSOS++; } } if (nSOS > 1) good = false; } if (!good) setWhen(0); // switch off } } Cbc-2.8.12/src/CbcCompareActual.hpp0000644000076600007660000000070411510742604015402 0ustar coincoin/* $Id: CbcCompareActual.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcCompareActual_H #define CbcCompareActual_H #include "CbcNode.hpp" #include "CbcCompareBase.hpp" #include "CbcCompare.hpp" #include "CbcCompareDepth.hpp" #include "CbcCompareDefault.hpp" #endif Cbc-2.8.12/src/CbcGenParamUtils.cpp0000644000076600007660000015541712131315050015373 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenParamUtils.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include "CoinFileIO.hpp" #include "CoinFinite.hpp" #include "CoinParam.hpp" #include "CbcModel.hpp" #include "CbcGenParam.hpp" #include "CbcGenCtlBlk.hpp" /*! \file CbcGenParamUtils \brief Implementation functions for CbcGenParam parameters. */ namespace { char svnid[] = "$Id: CbcGenParamUtils.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } namespace CbcGenSolvers { void setupSolverParam(CbcGenParam &solverParam) ; } namespace CbcGenParamUtils { /* Function to add cbc-generic control parameters to the cbc-generic parameter vector. Were needed, defaults are drawn from ctlBlk-> This function is a friend of CbcGenCtlBlk. */ void addCbcGenParams (int &numberParameters, CoinParamVec ¶meters, CbcGenCtlBlk *ctlBlk) { CbcGenParam *param ; std::string empty = "" ; param = new CbcGenParam(CbcGenParam::GENERALQUERY, "?", "Print a list of commands", false) ; param->setPushFunc(doHelpParam) ; param->setObj(ctlBlk) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::FULLGENERALQUERY, "???", "Print a list with *all* commands, even those hidden with `?'", false) ; param->setPushFunc(doHelpParam) ; param->setObj(ctlBlk) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::PRINTVERSION, "version", "Print version") ; param->setPushFunc(doVersionParam) ; param->setObj(ctlBlk) ; parameters.push_back(param) ; /* Built into CoinParam parsing. No additional actions required. doNothingParam simply prevents them from being reported as unimplemented. */ param = new CbcGenParam(CbcGenParam::STDIN, "-", "Switch to interactive command line mode", false) ; param->setPushFunc(doNothingParam) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::STDIN, "stdin", "Switch to interactive command line mode", false) ; param->setPushFunc(doNothingParam) ; param->setObj(ctlBlk) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::BAB, "branch!AndCut", "Do Branch and Cut") ; param->setPushFunc(doBaCParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "This does branch and cut. There are many parameters which can affect the performance. First just try with default settings and look carefully at the log file. Did cuts help? Did they take too long? Look at output to see which cuts were effective and then do some tuning. You will see that the options for cuts are off, on, root and ifmove. Off is obvious, on means that this cut generator will be tried in the branch and cut tree (you can fine tune using 'depth'). Root means just at the root node while 'ifmove' means that cuts will be used in the tree if they look as if they are doing some good and moving the objective value. If pre-processing reduced the size of the problem or strengthened many coefficients then it is probably wise to leave it on. Switch off heuristics which did not provide solutions. The other major area to look at is the search. Hopefully good solutions were obtained fairly early in the search so the important point is to select the best variable to branch on. See whether strong branching did a good job - or did it just take a lot of iterations. Adjust the strongBranching and trustPseudoCosts parameters." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::CPP, "cpp!Generate", "Generates C++ code", -1, 50000) ; param->setObj(ctlBlk) ; param->setLongHelp( "Once you like what the stand-alone solver does then this allows you to generate user_driver.cpp which approximates the code. 0 gives simplest driver, 1 generates saves and restores, 2 generates saves and restores even for variables at default value. 4 bit in cbc generates size dependent code rather than computed values." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::CLIQUECUTS, "clique!Cuts", "Whether to use clique cuts", "off", ctlBlk->clique_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenCutParam) ; param->setLongHelp( "This switches on clique cuts (either at root or in entire tree). See branchAndCut for information on options." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::CUTDEPTH, "cutD!epth", "Depth in tree at which to do cuts", -1, 999999, ctlBlk->cutDepth_) ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenIntParam) ; param->setLongHelp( "Cut generators may be off, on only at the root, on if they look useful, and on at some interval. If they are done every node then that is that, but it may be worth doing them every so often. The original method was every so many nodes but it is more logical to do it whenever depth in tree is a multiple of K. This option does that and defaults to -1 (off)." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::CUTSTRATEGY, "cuts!OnOff", "Switches all cuts on or off", "off", 0) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->setObj(ctlBlk) ; param->setLongHelp( "This can be used to switch on or off all cuts (apart from Reduce and Split). Then you can set individual ones off or on. See branchAndCut for information on options." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::COMBINE, "combine!Solutions", "Whether to use combine solution heuristic", "off", ctlBlk->combine_.action_) ; param->appendKwd("on") ; param->setObj(ctlBlk) ; param->setLongHelp( "This switches on a heuristic which does branch and cut on the problem given by just using variables which have appeared in one or more solutions. It is obviously only tried after two or more solutions." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::COSTSTRATEGY, "cost!Strategy", "Whether to use costs or column order as priorities", "off", 0) ; param->appendKwd("pri!orities") ; param->appendKwd("column!Order") ; param->setObj(ctlBlk) ; param->setLongHelp( "This orders the variables in order of their absolute costs - with largest cost ones being branched on first. This primitive strategy can be surprisingly effective. The column order option is obviously not on costs but it's easy to implement." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::DEBUG, "debug!In", "Read/write valid solution from/to file", "", false) ; param->setObj(ctlBlk) ; param->setPushFunc(doDebugParam) ; param->setLongHelp( "This will read a solution file from the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to '', i.e. it must be set.\n\nIf set to create it will create a file called debug.file after B&C search; if set to createAfterPre it will create the file before undoing preprocessing.\n\nThe idea is that if you suspect a bad cut generator and you did not use preprocessing you can do a good run with debug set to 'create' and then switch on the cuts you suspect and re-run with debug set to 'debug.file' Similarly if you do use preprocessing, but use createAfterPre. The create case has the same effect as saveSolution." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::DIRECTORY, "directory", "Set Default directory for import etc.", ctlBlk->dfltDirectory_) ; param->setObj(ctlBlk) ; param->setLongHelp( "This sets the directory which import, export, saveModel, restoreModel etc. will use. It is initialized to the current directory." ) ; param->setPushFunc(pushCbcGenStrParam) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::EXIT, "end", "Stops execution") ; param->setPushFunc(doExitParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "This stops execution; end, exit, quit and stop are synonyms." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::ERRORSALLOWED, "error!sAllowed", "Whether to allow import errors", "off", 0) ; param->appendKwd("on") ; param->setObj(ctlBlk) ; param->setLongHelp( "The default is not to use any model which had errors when reading the mps file. Setting this to 'on' will allow all errors from which the code can recover simply by ignoring the error. There are some errors from which the code can not recover, e.g., no ENDATA. This has to be set before import, i.e., -errorsAllowed on -import xxxxxx.mps." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::EXIT, "exit", "Stops execution") ; param->setPushFunc(doExitParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "This stops execution; end, exit, quit and stop are synonyms." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::EXPORT, "export", "Export model as mps file", std::string("default.mps")) ; param->setObj(ctlBlk) ; param->setLongHelp( "This will write an MPS format file to the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to 'default.mps'." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::DJFIX, "fix!OnDj", "Try heuristic that fixes variables based on reduced costs", -1.0e20, 1.0e20, ctlBlk->djFix_.threshold_) ; param->setPushFunc(pushCbcGenDblParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "If set, integer variables with reduced costs greater than the specified value will be fixed before branch and bound - use with extreme caution!" ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::FPUMP, "feas!ibilityPump", "Whether to try Feasibility Pump", "off", ctlBlk->fpump_.action_) ; param->appendKwd("on") ; param->setObj(ctlBlk) ; param->setLongHelp( "This switches on feasibility pump heuristic at root. This is due to Fischetti and Lodi and uses a sequence of LPs to try and get an integer feasible solution. Some fine tuning is available by passFeasibilityPump." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::FPUMPITS, "passF!easibilityPump", "How many passes in feasibility pump", 0, 10000, ctlBlk->fpump_.iters_) ; param->setObj(ctlBlk) ; param->setLongHelp( "This fine tunes the Feasibility Pump heuristic by doing more or fewer passes." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::FLOWCUTS, "flow!CoverCuts", "Whether to use Flow Cover cuts", "off", ctlBlk->flow_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenCutParam) ; param->setLongHelp( "This switches on flow cover cuts (either at root or in entire tree). See branchAndCut for information on options." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::GOMORYCUTS, "gomory!Cuts", "Whether to use Gomory cuts", "off", ctlBlk->gomory_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenCutParam) ; param->setLongHelp( "The original cuts - beware of imitations! Having gone out of favor, they are now more fashionable as LP solvers are more robust and they interact well with other cuts. They will almost always give cuts (although in this executable they are limited as to number of variables in cut). However the cuts may be dense so it is worth experimenting. See branchAndCut for information on options." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::GREEDY, "greedy!Heuristic", "Whether to use a greedy heuristic", "off", ctlBlk->greedyCover_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->setObj(ctlBlk) ; param->setLongHelp( "Switches on a pair of greedy heuristic which will try and obtain a solution. It may just fix a percentage of variables and then try a small branch and cut run." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::HEURISTICSTRATEGY, "heur!isticsOnOff", "Switches most heuristics on or off", "off", 0) ; param->appendKwd("on") ; param->setObj(ctlBlk) ; param->setLongHelp( "This can be used to switch on or off all heuristics. Then you can set individual ones off or on. CbcTreeLocal is not included as it dramatically alters search." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::KNAPSACKCUTS, "knapsack!Cuts", "Whether to use Knapsack cuts", "off", ctlBlk->knapsack_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenCutParam) ; param->setLongHelp( "This switches on knapsack cuts (either at root or in entire tree). See branchAndCut for information on options." ) ; parameters.push_back(param) ; /* param = new CbcGenParam(CbcGenParam::LANDPCUTS, "lift!AndProjectCuts","Whether to use lift-and-project cuts","off", ctlBlk->landp_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->setObj(ctlBlk) ; param->setLongHelp( "This switches on lift-and-project cuts (either at root or in entire tree). See branchAndCut for information on options." ) ; parameters.push_back(param) ; */ param = new CbcGenParam(CbcGenParam::LOCALTREE, "local!TreeSearch", "Whether to use local tree search", "off", ctlBlk->localTree_.action_) ; param->appendKwd("on") ; param->setObj(ctlBlk) ; param->setLongHelp( "This switches on a local search algorithm when a solution is found. This is from Fischetti and Lodi and is not really a heuristic although it can be used as one. When used from this program it has limited functionality. It is not controlled by heuristicsOnOff." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::LOGLEVEL, "log!Level", "Level of detail in cbc-generic output.", -1, 999999, ctlBlk->logLvl_) ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenIntParam) ; param->setLongHelp( "If set to 0 then there should be no output in normal circumstances. A value of 1 is probably the best value for most uses, while 2 and 3 give more information." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::MIXEDCUTS, "mixed!IntegerRoundingCuts", "Whether to use Mixed Integer Rounding cuts", "off", ctlBlk->mir_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenCutParam) ; param->setLongHelp( "This switches on mixed integer rounding cuts (either at root or in entire tree). See branchAndCut for information on options." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::USESOLUTION, "force!Solution", "Whether to use given solution as crash for BAB", "off", 0) ; param->appendKwd("on") ; param->setObj(ctlBlk) ; param->setLongHelp( "If on then tries to branch to solution given by AMPL or priorities file." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::HELP, "help", "Print out version, non-standard options and some help") ; param->setPushFunc(doHelpParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "This prints out some help to get a user started. If you're seeing this message, you should be past that stage." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::IMPORT, "import", "Import model from mps file", ctlBlk->lastMpsIn_) ; param->setPushFunc(doImportParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "This will read an MPS format file from the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to '', i.e., it must be set. If you have libgz then it can read compressed files 'xxxxxxxx.gz'." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::SOLVECONTINUOUS, "initialS!olve", "Solve to continuous optimum") ; param->setObj(ctlBlk) ; param->setLongHelp( "This just solves the problem to the continuous optimum, without adding any cuts." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::MESSAGES, "mess!ages", "Controls whether standardised message prefix is printed", "off", 0) ; param->appendKwd("on") ; param->setObj(ctlBlk) ; param->setLongHelp( "By default, messages have a standard prefix, such as:\n Clp0005 2261 Objective 109.024 Primal infeas 944413 (758)\nbut this program turns this off to make it look more friendly. It can be useful to turn them back on if you want to be able to 'grep' for particular messages or if you intend to override the behavior of a particular message." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::MIPLIB, "miplib", "Do some of miplib test set") ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::OUTDUPROWS, "outDup!licates", "Takes duplicate rows, etc., out of the integer model", false) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::OUTPUTFORMAT, "output!Format", "Which output format to use", 1, 6, 2) ; param->setObj(ctlBlk) ; param->setLongHelp( "Normally export will be done using normal representation for numbers and two values per line. You may want to do just one per line (for grep or suchlike) and you may wish to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal. Otherwise, odd values give one value per line, even values two. Values of 1 and 2 give normal format, 3 and 4 give greater precision, 5 and 6 give IEEE values. When exporting a basis, 1 does not save values, 2 saves values, 3 saves with greater accuracy and 4 saves in IEEE format." ) ; parameters.push_back(param) ; /* In order for initialisation to work properly, the order of the keywords here must match the order of the enum IPPControl in CbcGenCtlBlk.hpp. */ param = new CbcGenParam(CbcGenParam::PREPROCESS, "preprocess", "Whether to use integer preprocessing", "off", ctlBlk->preProcess_) ; param->appendKwd("on") ; param->appendKwd("save") ; param->appendKwd("equal") ; param->appendKwd("sos") ; param->appendKwd("trysos") ; param->appendKwd("equalall") ; param->appendKwd("strategy") ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenKwdParam) ; param->setLongHelp( "This tries to reduce size of the model in a similar way to presolve and it also tries to strengthen the model. This can be very useful and is worth trying. save option saves on file presolved.mps. equal will turn <= cliques into ==. sos will create sos sets if all 0-1 in sets (well one extra is allowed) and no overlaps. trysos is same but allows any number extra. equalall will turn all valid inequalities into equalities with integer slacks. strategy is as on but uses CbcStrategy." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::PRINTOPTIONS, "pO!ptions", "Dubious print options", 0, COIN_INT_MAX, 0, false) ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenIntParam) ; param->setLongHelp( "If this is greater than 0 then presolve will give more information and branch and cut will give statistics" ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::PROBINGCUTS, "probing!Cuts", "Whether to use Probing cuts", "off", ctlBlk->probing_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->appendKwd("forceOnBut") ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenCutParam) ; param->setLongHelp( "This switches on probing cuts (either at root or in entire tree). See branchAndCut for information on options." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::INTPRINT, "printi!ngOptions", "Print options", "normal", 0) ; param->appendKwd("integer") ; param->appendKwd("special") ; param->appendKwd("rows") ; param->appendKwd("all") ; param->setPushFunc(pushCbcGenKwdParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \ninteger - nonzero integer column variables\nspecial - in format suitable for OsiRowCutDebugger\nrows - nonzero column variables and row activities\nall - all column variables and row activities.\n\nFor non-integer problems 'integer' and 'special' act like 'normal'. Also see printMask for controlling output." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::PRINTMASK, "printM!ask", "Control printing of solution with a regular expression", empty) ; param->setPushFunc(doPrintMaskParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "If set then only those names which match mask are printed in a solution. '?' matches any character and '*' matches any set of characters. The default is '' (unset) so all variables are printed. This is only active if model has names." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::PRIORITYIN, "prio!rityIn", "Import priorities etc from file", empty) ; param->setObj(ctlBlk) ; param->setLongHelp( "This will read a file with priorities from the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to '', i.e. it must be set. This can not read from compressed files. File is in csv format with allowed headings - name, number, priority, direction, up, down, solution. Exactly one of name and number must be given." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::REDSPLITCUTS, "reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts", "off", ctlBlk->redSplit_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenCutParam) ; param->setLongHelp( "This switches on reduce and split cuts (either at root or in entire tree). See branchAndCut for information on options." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::ROUNDING, "round!ingHeuristic", "Whether to use Rounding heuristic", "off", ctlBlk->rounding_.action_) ; param->appendKwd("on") ; param->setObj(ctlBlk) ; param->setLongHelp( "This switches on a simple (but effective) rounding heuristic at each node of tree." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::EXIT, "quit", "Stops execution") ; param->setPushFunc(doExitParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "This stops execution; end, exit, quit and stop are synonyms." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::DUMMY, "sleep", "for debug", 0, 9999, 0, false) ; param->setObj(ctlBlk) ; param->setLongHelp( "If passed to solver from ampl, then ampl will wait so that you can copy .nl file for debug." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::SOLUTION, "solu!tion", "Prints solution to file", std::string("stdout")) ; param->setPushFunc(doSolutionParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "This will write a primitive solution file to the given file name. It will use the default directory given by 'directory'. A name of '$' will use the previous value for the name. This is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask." ) ; parameters.push_back(param) ; param = new CbcGenParam ; CbcGenSolvers::setupSolverParam(*param) ; param->setObj(ctlBlk) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::SOS, "sos!Options", "Whether to use SOS from AMPL", "off", 0) ; param->appendKwd("on") ; param->setObj(ctlBlk) ; param->setLongHelp( "Normally if AMPL says there are SOS variables they should be used, but sometimes they should be turned off - this does so." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::EXIT, "stop", "Stops execution") ; param->setPushFunc(doExitParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "This stops execution; end, exit, quit and stop are synonyms." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::STRENGTHEN, "strengthen", "Create strengthened problem") ; param->setObj(ctlBlk) ; param->setLongHelp( "This creates a new problem by applying the root node cuts. All tight constraints will be in resulting problem." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::TIGHTENFACTOR, "tighten!Factor", "Tighten bounds using value times largest activity at continuous solution", 1.0, 1.0e20) ; param->setObj(ctlBlk) ; param->setLongHelp( "This sleazy trick can help on some problems." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::TWOMIRCUTS, "two!MirCuts", "Whether to use Two phase Mixed Integer Rounding cuts", "off", ctlBlk->twomir_.action_) ; param->appendKwd("on") ; param->appendKwd("root") ; param->appendKwd("ifmove") ; param->appendKwd("forceOn") ; param->setObj(ctlBlk) ; param->setPushFunc(pushCbcGenCutParam) ; param->setLongHelp( "This switches on two phase mixed integer rounding cuts (either at root or in entire tree). See branchAndCut for information on options." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::UNITTEST, "unitTest", "Do unit test") ; param->setObj(ctlBlk) ; param->setLongHelp( "This exercises the unit test." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::USERCBC, "userCbc", "Hand coded Cbc stuff", 0, COIN_INT_MAX, 0, false) ; param->setObj(ctlBlk) ; param->setLongHelp( "There are times (e.g., when using AMPL interface) when you may wish to do something unusual. Look for USERCBC in main driver and modify sample code." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::VERBOSE, "verbose", "Switches on longer help on single ?", 0, 15, ctlBlk->verbose_, false) ; param->setPushFunc(pushCbcGenIntParam) ; param->setObj(ctlBlk) ; param->setLongHelp( "Set to 1 to get short help with ? list, 2 to get long help." ) ; parameters.push_back(param) ; param = new CbcGenParam(CbcGenParam::SHOWUNIMP, "unimp!lemented", "Report unimplemented commands.", false) ; param->setPushFunc(doUnimplementedParam) ; param->setObj(ctlBlk) ; parameters.push_back(param) ; numberParameters = parameters.size() ; assert (((unsigned) numberParameters) <= parameters.capacity()) ; return ; } void loadGenParamObj (const CoinParamVec paramVec, int first, int last, CbcGenCtlBlk *ctlBlk) { int i ; /* Load the cbc-generic object into the parameters */ for (i = first ; i <= last ; i++) { CbcGenParam *genParam = dynamic_cast(paramVec[i]) ; assert (genParam != 0) ; genParam->setObj(ctlBlk) ; } return ; } /* Functions to implement cbc-generic (CbcGenParam) parameters */ /* Maintainer's utility, scan the parameters and report the ones that are unimplemented (i.e., have no pushFunc). */ int doUnimplementedParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; assert (ctlBlk->paramVec_ != 0) ; CoinParamVec ¶mVec = *ctlBlk->paramVec_ ; int unimpCnt = 0 ; int maxAcross = 5 ; for (unsigned i = 0 ; i < paramVec.size() ; i++) { CoinParam *param = paramVec[i] ; if (param->pushFunc() == 0) { if (unimpCnt % maxAcross == 0) { std::cout << std::endl ; } else { std::cout << " " ; } std::cout << param->name() ; unimpCnt++ ; } } if (unimpCnt % maxAcross != 1) { std::cout << std::endl ; } std::cout << unimpCnt << " unimplemented parameters." << std::endl ; return (0) ; } /* Noop function. Mainly to eliminate commands from the list returned by doUnimplmentedParam. */ int doNothingParam (CoinParam *param) { return (0) ; } /* Function to terminate command parsing by returning -1. */ int doExitParam (CoinParam *param) { return (-1) ; } /* Function to print the current version. */ int doVersionParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; std::cout << "cbc-generic version " << ctlBlk->version_ << std::endl ; std::cout << "cbc-generic is experimental software. If you want a stable MIP " << "solver, please" << std::endl << "use cbc. If you discover bugs while using cbc-generic " << "please specify" << std::endl << "cbc-generic in the ticket description or email subject line." << std::endl ; return (0) ; } /* Function to handle help (HELP), `?' (GENERALQUERY), and `???' (FULLGENERALQUERY). */ int doHelpParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; CbcGenParam::CbcGenParamCode code = genParam->paramCode() ; int verbose = ctlBlk->verbose_ ; bool shortHelp = ((verbose & 0x01) ? true : false) ; bool longHelp = ((verbose & 0x02) ? true : false) ; bool hidden = ((verbose & 0x08) ? true : false) ; CoinParamVec *paramVec = ctlBlk->paramVec_ ; assert (paramVec != 0) ; /* Tune up the initial settings. FULLGENERALQUERY will print normally hidden params, and a request for long help overrules a request for short help. */ if (code == CbcGenParam::FULLGENERALQUERY) { hidden = true ; } if (longHelp) { shortHelp = false ; } CoinParamUtils::printGenericHelp() ; std::cout << "\nAvailable commands are:" ; std::string pfx(" ") ; CoinParamUtils::printHelp(*paramVec, 0, paramVec->size() - 1, pfx, shortHelp, longHelp, hidden) ; return (0) ; } /* Function to push a double-valued parameter. */ int pushCbcGenDblParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; double val = genParam->dblVal() ; CbcGenParam::CbcGenParamCode code = genParam->paramCode() ; int retval = 0 ; /* Figure out what we're doing and set the relevant field. */ switch (code) { case CbcGenParam::DJFIX: { ctlBlk->djFix_.action_ = true ; ctlBlk->djFix_.threshold_ = val ; break ; } default: { std::cerr << "pushCbcGenDbl: no equivalent CbcGenCtlBlk field for " << "parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } return (retval) ; } /* Function to push an integer-valued parameter. */ int pushCbcGenIntParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; int val = genParam->intVal() ; CbcGenParam::CbcGenParamCode code = genParam->paramCode() ; int retval = 0 ; /* Figure out what we're doing and set the relevant field. */ switch (code) { case CbcGenParam::CUTDEPTH: { ctlBlk->setCutDepth(val) ; break ; } case CbcGenParam::LOGLEVEL: { ctlBlk->setLogLevel(val) ; break ; } case CbcGenParam::PRINTOPTIONS: { ctlBlk->printOpt_ = val ; break ; } case CbcGenParam::VERBOSE: { ctlBlk->verbose_ = val ; break ; } default: { std::cerr << "pushCbcGenInt: no equivalent CbcGenCtlBlk field for " << "parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } return (retval) ; } /* Function to push a keyword-valued parameter. This is the catch-all function for keyword parameters that don't belong to any other useful grouping. */ int pushCbcGenKwdParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; std::string str = genParam->kwdVal() ; CbcGenParam::CbcGenParamCode code = genParam->paramCode() ; int retval = 0 ; /* Figure out what we're doing and set the relevant field. */ switch (code) { case CbcGenParam::PREPROCESS: { if (str == "off") { ctlBlk->setIPPAction(CbcGenCtlBlk::IPPOff) ; } else if (str == "on") { ctlBlk->setIPPAction(CbcGenCtlBlk::IPPOn) ; } else if (str == "save") { ctlBlk->setIPPAction(CbcGenCtlBlk::IPPSave) ; } else if (str == "equal") { ctlBlk->setIPPAction(CbcGenCtlBlk::IPPEqual) ; } else if (str == "sos") { ctlBlk->setIPPAction(CbcGenCtlBlk::IPPSOS) ; } else if (str == "trysos") { ctlBlk->setIPPAction(CbcGenCtlBlk::IPPTrySOS) ; } else if (str == "equalall") { ctlBlk->setIPPAction(CbcGenCtlBlk::IPPEqualAll) ; } else if (str == "strategy") { ctlBlk->setIPPAction(CbcGenCtlBlk::IPPStrategy) ; } else { std::cerr << "pushCbcGenKwdParam(PREPROCESS): unrecognised keyword `" << str << "'." << std::endl ; retval = -1 ; } break ; } case CbcGenParam::COSTSTRATEGY: { if (str == "off") { ctlBlk->priorityAction_ = CbcGenCtlBlk::BPOff ; } else if (str == "priorities") { ctlBlk->priorityAction_ = CbcGenCtlBlk::BPCost ; } if (str == "columnOrder") { ctlBlk->priorityAction_ = CbcGenCtlBlk::BPOrder ; } else { std::cerr << "pushCbcGenKwdParam(COSTSTRATEGY): unrecognised keyword `" << str << "'." << std::endl ; retval = -1 ; } break ; } case CbcGenParam::INTPRINT: { if (str == "normal") { ctlBlk->printMode_ = 0 ; } else if (str == "integer") { ctlBlk->printMode_ = 1 ; } else if (str == "special") { ctlBlk->printMode_ = 2 ; } else if (str == "rows") { ctlBlk->printMode_ = 3 ; } else if (str == "all") { ctlBlk->printMode_ = 4 ; } else { std::cerr << "pushCbcGenKwdParam(INTPRINT): unrecognised keyword `" << str << "'." << std::endl ; retval = -1 ; } break ; } default: { std::cerr << "pushCbcGenKwdParam: unrecognised parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } return (retval) ; } /* Function to push a string-valued parameter */ int pushCbcGenStrParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; std::string str = genParam->strVal() ; CbcGenParam::CbcGenParamCode code = genParam->paramCode() ; int retval = 0 ; /* Figure out what we're doing and set the relevant field. */ switch (code) { case CbcGenParam::DIRECTORY: { char dirSep = CoinFindDirSeparator() ; if (str[str.length()-1] != dirSep) { str += dirSep ; } ctlBlk->dfltDirectory_ = str ; break ; } default: { std::cerr << "pushCbcGenStr: no equivalent CbcGenCtlBlk field for " << "parameter code `" << code << "'." << std::endl ; retval = -1 ; break ; } } return (retval) ; } /* The various parameters to control cut generators can be grouped, as they all use the same set of keywords. */ int pushCbcGenCutParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; std::string str = genParam->kwdVal() ; CbcGenParam::CbcGenParamCode code = genParam->paramCode() ; /* Setup to return nonfatal/fatal error (1/-1) by default, so that all we need to do is correct to 0 (no error) if we're successful. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* First translate the keyword into the correct CGControl enum value. */ CbcGenCtlBlk::CGControl action ; if (str == "off") { action = CbcGenCtlBlk::CGOff ; } else if (str == "on") { action = CbcGenCtlBlk::CGOn ; } else if (str == "root") { action = CbcGenCtlBlk::CGRoot ; } else if (str == "ifmove") { action = CbcGenCtlBlk::CGIfMove ; } else if (str == "forceOn") { action = CbcGenCtlBlk::CGForceOn ; } else if (str == "forceOnBut") { action = CbcGenCtlBlk::CGForceBut ; } else { std::cerr << "pushCbcGenCutParam: unrecognised keyword `" << str << "'." << std::endl ; return (retval) ; } /* Validate the parameter code and set a variable to separate cuts from heuristics. */ bool isCut = false ; bool isHeuristic = false ; switch (code) { case CbcGenParam::CLIQUECUTS: case CbcGenParam::FLOWCUTS: case CbcGenParam::GOMORYCUTS: case CbcGenParam::KNAPSACKCUTS: case CbcGenParam::MIXEDCUTS: case CbcGenParam::PROBINGCUTS: case CbcGenParam::REDSPLITCUTS: case CbcGenParam::TWOMIRCUTS: case CbcGenParam::CUTSTRATEGY: { isCut = true ; break ; } case CbcGenParam::COMBINE: case CbcGenParam::FPUMP: case CbcGenParam::ROUNDING: case CbcGenParam::LOCALTREE: case CbcGenParam::HEURISTICSTRATEGY: { isHeuristic = true ; break ; } default: { std::cerr << "pushCbcGenCutParam: unrecognised parameter code `" << code << "'." << std::endl ; return (retval) ; } } /* See if the action is valid for the specified type. Heuristics are on or off; cuts can be any of the other codes. Only probing can use forceOnBut. */ if (isHeuristic) { if (!(action == CbcGenCtlBlk::CGOff || action == CbcGenCtlBlk::CGOn)) { std::cerr << "pushCbcGenCutParam: only on or off is valid for a heuristic." << std::endl ; return (retval) ; } } else if (isCut) { if (action == CbcGenCtlBlk::CGForceBut && code != CbcGenParam::PROBINGCUTS) { std::cerr << "pushCbcGenCutParam: forceOnBut is valid only for probing." << std::endl ; return (retval) ; } } /* We've done the basic checks; go ahead and set the relevant field in the control block. We shouldn't need the default case, but some compilers will complain if it's missing. */ switch (code) { case CbcGenParam::CLIQUECUTS: { ctlBlk->setCliqueAction(action) ; break ; } case CbcGenParam::FLOWCUTS: { ctlBlk->setFlowAction(action) ; break ; } case CbcGenParam::GOMORYCUTS: { ctlBlk->setGomoryAction(action) ; break ; } case CbcGenParam::KNAPSACKCUTS: { ctlBlk->setKnapsackAction(action) ; break ; } case CbcGenParam::MIXEDCUTS: { ctlBlk->setMirAction(action) ; break ; } case CbcGenParam::PROBINGCUTS: { ctlBlk->setProbingAction(action) ; break ; } case CbcGenParam::REDSPLITCUTS: { ctlBlk->setRedSplitAction(action) ; break ; } case CbcGenParam::TWOMIRCUTS: { ctlBlk->setTwomirAction(action) ; break ; } case CbcGenParam::CUTSTRATEGY: { ctlBlk->setCliqueAction(action) ; ctlBlk->setFlowAction(action) ; ctlBlk->setGomoryAction(action) ; ctlBlk->setKnapsackAction(action) ; ctlBlk->setMirAction(action) ; ctlBlk->setProbingAction(action) ; ctlBlk->setRedSplitAction(action) ; ctlBlk->setTwomirAction(action) ; break ; } case CbcGenParam::COMBINE: { ctlBlk->setCombineAction(action) ; break ; } case CbcGenParam::FPUMP: { ctlBlk->setFPumpAction(action) ; break ; } case CbcGenParam::GREEDY: { ctlBlk->setGreedyCoverAction(action) ; ctlBlk->setGreedyEqualityAction(action) ; break ; } case CbcGenParam::LOCALTREE: { ctlBlk->setTreeLocalAction(action) ; break ; } case CbcGenParam::ROUNDING: { ctlBlk->setRoundingAction(action) ; break ; } case CbcGenParam::HEURISTICSTRATEGY: { ctlBlk->setCombineAction(action) ; ctlBlk->setFPumpAction(action) ; ctlBlk->setGreedyCoverAction(action) ; ctlBlk->setRoundingAction(action) ; ctlBlk->setTreeLocalAction(action) ; break ; } default: { std::cerr << "pushCbcGenCutParam: internal confusion!" << std::endl ; return (-1) ; } } return (0) ; } /* This routine imports a new constraint system into the solver. */ int doImportParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default, so that all we need to do is correct to 0 (no error) if we're successful. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* Figure out where we're going to acquire this new model. As special cases, `$' says `use the previous input source' and `-' says `use stdin'. */ std::string field = genParam->strVal() ; std::string fileName ; if (field == "$") { fileName = ctlBlk->lastMpsIn_ ; field = fileName ; } else if (field == "-") { fileName = "stdin" ; field = fileName ; } else { fileName = field ; } /* See if we can open a file. fileCoinReadable understands a fair bit about platforms and compressed files and will try variations of the file name (see the doxygen doc'n for details). The file name returned in field wil be the one that actually worked. */ bool canOpen = fileCoinReadable(fileName, ctlBlk->dfltDirectory_) ; if (canOpen == false) { std::cout << "Unable to open file `" << fileName << "', original name '" << genParam->strVal() << "'." << std::endl ; return (retval) ; } /* We can find the file. Record the name. This requires a little finesse: what we want is the base file name (and extension(s), if present) but not the prefix, unless it's an absolute path. */ if (!fileAbsPath(fileName)) { std::string::size_type pos = fileName.rfind(field) ; ctlBlk->lastMpsIn_ = fileName.substr(pos) ; } else { ctlBlk->lastMpsIn_ = fileName ; } /* Try to read the file. Standard OSI doesn't support the Clp extensions for keepImportNames and allowImportErrors. It should at least support keepImportNames. Status will be zero for a successful read. */ OsiSolverInterface *lpSolver = ctlBlk->model_->solver() ; int status = lpSolver->readMps(fileName.c_str(), "") ; if (status) { std::cout << "There were " << status << " errors on input." << std::endl ; return (retval) ; } /* We have a model! Return success. */ ctlBlk->goodModel_ = true ; return (0) ; } /* This routine imports a debug file into the solver, or arranges for its creation. Import works in the standard way, using the file name provided with the command. As special cases, if the file name is `create' or `createAfterPre', the action here sets up to cause a debug file containing the solution to be dumped after branch-and-cut is completed. `createAfterPre' will dump the solution before undoing the presolve transforms. `create' will dump the solution after integer presolve is backed out. */ int doDebugParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default, so that all we need to do is correct to 0 (no error) if we're successful. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* If the file name is `create' or `createAfterPre', we're just setting up to make a debug file the next time we do branch-and-cut. */ std::string field = genParam->strVal() ; if (field == "create" || field == "createAfterPre") { ctlBlk->debugCreate_ = field ; return (0) ; } /* Figure out where we're going to acquire the debug file. As special cases, `$' says `use the previous input source' and `-' says `use stdin'. */ std::string fileName ; if (field == "$") { fileName = ctlBlk->debugFile_ ; field = fileName ; } else if (field == "-") { fileName = "stdin" ; field = fileName ; } else { fileName = field ; } /* See if we can open a file. fileCoinReadable understands a fair bit about platforms and compressed files and will try variations of the file name (see the doxygen doc'n for details). The file name returned in field wil be the one that actually worked. No default prefix --- a debug file is assumed to always be in the current directory. */ bool canOpen = fileCoinReadable(fileName, ctlBlk->dfltDirectory_) ; if (canOpen == false) { std::cout << "Unable to open file `" << fileName << "', original name '" << genParam->strVal() << "'." << std::endl ; return (retval) ; } /* We can find the file. Record the name. This requires a little finesse: what we want is the base file name (and extension(s), if present) but not the prefix, unless it's an absolute path. */ if (!fileAbsPath(fileName)) { std::string::size_type pos = fileName.rfind(field) ; ctlBlk->lastMpsIn_ = fileName.substr(pos) ; } else { ctlBlk->lastMpsIn_ = fileName ; } /* Load the primal variable values into the debug solution vector. */ int intUnused, numCols ; double dblUnused ; double *primals ; bool readOK = readSolution(fileName, intUnused, numCols, dblUnused, 0, 0, &primals, 0) ; if (readOK) { if (ctlBlk->debugSol_.values_) { delete[] ctlBlk->debugSol_.values_ ; } ctlBlk->debugSol_.numCols_ = numCols ; ctlBlk->debugSol_.values_ = primals ; retval = 0 ; } else { if (primals) { delete[] primals ; } } return (retval) ; } /* Utility routine to save the current solution to a file. No formatting, and not intended to be portable in any way, shape, or form. */ void saveSolution (const OsiSolverInterface *osi, std::string fileName) { FILE *fp = fopen(fileName.c_str(), "wb") ; if (fp) { int numberRows = osi->getNumRows() ; int numberColumns = osi->getNumCols() ; double objectiveValue = osi->getObjValue() ; fwrite(&numberRows, sizeof(int), 1, fp) ; fwrite(&numberColumns, sizeof(int), 1, fp) ; fwrite(&objectiveValue, sizeof(double), 1, fp) ; const double *primalRowSolution = osi->getRowActivity() ; const double *dualRowSolution = osi->getRowPrice() ; const double *primalColumnSolution = osi->getColSolution() ; const double *dualColumnSolution = osi->getReducedCost() ; fwrite(primalRowSolution, sizeof(double), numberRows, fp) ; fwrite(dualRowSolution, sizeof(double), numberRows, fp) ; fwrite(primalColumnSolution, sizeof(double), numberColumns, fp) ; fwrite(dualColumnSolution, sizeof(double), numberColumns, fp) ; fclose(fp) ; } else { std::cout << "saveSolution: Unable to open file `" << fileName << "'." << std::endl ; } return ; } /* Utility routine to read in a solution dump created by saveSolution. Generally we don't need all the info in this file, so the routine accepts a bunch of reference/pointer paramaters and fills in any that are non-null. It's the client's responsibility to dispose of space allocated for solution vectors. The parameters fileName, numRows, numCols, and objVal are mandatory. The rest can be null. */ bool readSolution (std::string fileName, int &numRows, int &numCols, double &objVal, double **rowActivity, double **dualVars, double **primalVars, double **reducedCosts) { FILE *fp = fopen(fileName.c_str(), "rb") ; bool retval = true ; numRows = -1 ; numCols = -1 ; objVal = 0 ; *rowActivity = 0 ; *dualVars = 0 ; *primalVars = 0 ; *reducedCosts = 0 ; if (fp) { fread(&numRows, sizeof(int), 1, fp) ; fread(&numCols, sizeof(int), 1, fp) ; fread(&objVal, sizeof(double), 1, fp) ; if (rowActivity != NULL) { *rowActivity = new double [numRows] ; fread(*rowActivity, sizeof(double), numRows, fp) ; } else { fseek(fp, numRows*sizeof(double), SEEK_CUR) ; } if (dualVars != NULL) { *dualVars = new double [numRows] ; fread(*dualVars, sizeof(double), numRows, fp) ; } else { fseek(fp, numRows*sizeof(double), SEEK_CUR) ; } if (primalVars != NULL) { *primalVars = new double [numCols] ; fread(*primalVars, sizeof(double), numCols, fp) ; } else { fseek(fp, numCols*sizeof(double), SEEK_CUR) ; } if (reducedCosts != NULL) { *reducedCosts = new double [numCols] ; fread(*reducedCosts, sizeof(double), numCols, fp) ; } else { fseek(fp, numCols*sizeof(double), SEEK_CUR) ; } fclose(fp) ; } else { std::cout << "readSolution: Unable to open file `" << fileName << "'." << std::endl ; retval = false ; } return (retval) ; } } // end namespace CbcGenParamUtils Cbc-2.8.12/src/CbcStrategy.hpp0000644000076600007660000001640511510742604014471 0ustar coincoin/* $Id: CbcStrategy.hpp 1573 2011-01-05 01:12:36Z lou $ */ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CbcStrategy_H #define CbcStrategy_H #include "CbcModel.hpp" class CglPreProcess; class CbcNodeInfo; class CbcNode; class CoinWarmStartDiff; //############################################################################# /** Strategy base class */ class CbcStrategy { public: // Default Constructor CbcStrategy (); virtual ~CbcStrategy(); /// Clone virtual CbcStrategy * clone() const = 0; /// Setup cut generators virtual void setupCutGenerators(CbcModel & model) = 0; /// Setup heuristics virtual void setupHeuristics(CbcModel & model) = 0; /// Do printing stuff virtual void setupPrinting(CbcModel & model, int modelLogLevel) = 0; /// Other stuff e.g. strong branching and preprocessing virtual void setupOther(CbcModel & model) = 0; /// Set model depth (i.e. how nested) inline void setNested(int depth) { depth_ = depth; } /// Get model depth (i.e. how nested) inline int getNested() const { return depth_; } /// Say preProcessing done inline void setPreProcessState(int state) { preProcessState_ = state; } /// See what sort of preprocessing was done inline int preProcessState() const { return preProcessState_; } /// Pre-processing object inline CglPreProcess * process() const { return process_; } /// Delete pre-processing object to save memory void deletePreProcess(); /// Return a new Full node information pointer (descendant of CbcFullNodeInfo) virtual CbcNodeInfo * fullNodeInfo(CbcModel * model, int numberRowsAtContinuous) const; /// Return a new Partial node information pointer (descendant of CbcPartialNodeInfo) virtual CbcNodeInfo * partialNodeInfo(CbcModel * model, CbcNodeInfo * parent, CbcNode * owner, int numberChangedBounds, const int * variables, const double * boundChanges, const CoinWarmStartDiff *basisDiff) const; /// Create C++ lines to get to current state virtual void generateCpp( FILE * ) {} /** After a CbcModel::resolve this can return a status -1 no effect 0 treat as optimal 1 as 0 but do not do any more resolves (i.e. no more cuts) 2 treat as infeasible */ virtual int status(CbcModel * model, CbcNodeInfo * parent, int whereFrom); private: /// Illegal Assignment operator CbcStrategy & operator=(const CbcStrategy& rhs); protected: // Data /// Model depth int depth_; /** PreProcessing state - -1 infeasible 0 off 1 was done (so need post-processing) */ int preProcessState_; /// If preprocessing then this is object CglPreProcess * process_; }; /** Null class */ class CbcStrategyNull : public CbcStrategy { public: // Default Constructor CbcStrategyNull () {} // Copy constructor CbcStrategyNull ( const CbcStrategyNull & rhs) : CbcStrategy(rhs) {} // Destructor ~CbcStrategyNull () {} /// Clone virtual CbcStrategy * clone() const { return new CbcStrategyNull(*this); } /// Setup cut generators virtual void setupCutGenerators(CbcModel & ) {} /// Setup heuristics virtual void setupHeuristics(CbcModel & ) {} /// Do printing stuff virtual void setupPrinting(CbcModel & , int ) {} /// Other stuff e.g. strong branching virtual void setupOther(CbcModel & ) {} protected: // Data private: /// Illegal Assignment operator CbcStrategyNull & operator=(const CbcStrategyNull& rhs); }; /** Default class */ class CbcStrategyDefault : public CbcStrategy { public: // Default Constructor CbcStrategyDefault (int cutsOnlyAtRoot = 1, int numberStrong = 5, int numberBeforeTrust = 0, int printLevel = 0); // Copy constructor CbcStrategyDefault ( const CbcStrategyDefault &); // Destructor ~CbcStrategyDefault (); /// Clone virtual CbcStrategy * clone() const; /// Setup cut generators virtual void setupCutGenerators(CbcModel & model); /// Setup heuristics virtual void setupHeuristics(CbcModel & model); /// Do printing stuff virtual void setupPrinting(CbcModel & model, int modelLogLevel) ; /// Other stuff e.g. strong branching virtual void setupOther(CbcModel & model); /// Set up preProcessing - see below inline void setupPreProcessing(int desired = 1, int passes = 10) { desiredPreProcess_ = desired; preProcessPasses_ = passes; } /// See what sort of preprocessing wanted inline int desiredPreProcess() const { return desiredPreProcess_; } /// See how many passes wanted inline int preProcessPasses() const { return preProcessPasses_; } /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; protected: // Data // Whether to do cuts only at root (-1 -> switch off totally) int cutsOnlyAtRoot_; // How much strong branching to do int numberStrong_; // Number branches needed to trust with dynamic pseudo costs int numberBeforeTrust_; // Print level 0 little, 1 medium int printLevel_; /** Desired pre-processing 0 - none 1 - ordinary 2 - find sos 3 - find cliques 4 - more aggressive sos 5 - add integer slacks */ int desiredPreProcess_; /// Number of pre-processing passes int preProcessPasses_; private: /// Illegal Assignment operator CbcStrategyDefault & operator=(const CbcStrategyDefault& rhs); }; /** Default class for sub trees */ class CbcStrategyDefaultSubTree : public CbcStrategy { public: // Default Constructor CbcStrategyDefaultSubTree (CbcModel * parent = NULL, int cutsOnlyAtRoot = 1, int numberStrong = 5, int numberBeforeTrust = 0, int printLevel = 0); // Copy constructor CbcStrategyDefaultSubTree ( const CbcStrategyDefaultSubTree &); // Destructor ~CbcStrategyDefaultSubTree (); /// Clone virtual CbcStrategy * clone() const; /// Setup cut generators virtual void setupCutGenerators(CbcModel & model); /// Setup heuristics virtual void setupHeuristics(CbcModel & model); /// Do printing stuff virtual void setupPrinting(CbcModel & model, int modelLogLevel) ; /// Other stuff e.g. strong branching virtual void setupOther(CbcModel & model); protected: // Data // Parent model CbcModel * parentModel_; // Whether to do cuts only at root (-1 -> switch off totally) int cutsOnlyAtRoot_; // How much strong branching to do int numberStrong_; // Number branches needed to trust with dynamic pseudo costs int numberBeforeTrust_; // Print level 0 little, 1 medium int printLevel_; private: /// Illegal Assignment operator CbcStrategyDefaultSubTree & operator=(const CbcStrategyDefaultSubTree& rhs); }; #endif Cbc-2.8.12/src/CbcSimpleIntegerDynamicPseudoCost.cpp0000644000076600007660000014735712131315050020751 0ustar coincoin// $Id: CbcSimpleIntegerDynamicPseudoCost.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/17/2009 - carved out of CbcBranchDynamic #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG //#define TRACE_ONE 19 #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcBranchDynamic.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" #include "CbcSimpleIntegerDynamicPseudoCost.hpp" #ifdef COIN_DEVELOP typedef struct { double sumUp_; double upEst_; // or change in obj in update double sumDown_; double downEst_; // or movement in value in update int sequence_; int numberUp_; int numberUpInf_; int numberDown_; int numberDownInf_; char where_; char status_; } History; History * history = NULL; int numberHistory = 0; int maxHistory = 0; bool getHistoryStatistics_ = true; static void increaseHistory() { if (numberHistory == maxHistory) { maxHistory = 100 + (3 * maxHistory) / 2; History * temp = new History [maxHistory]; memcpy(temp, history, numberHistory*sizeof(History)); delete [] history; history = temp; } } static bool addRecord(History newOne) { //if (!getHistoryStatistics_) return false; bool fromCompare = false; int i; for ( i = numberHistory - 1; i >= 0; i--) { if (newOne.sequence_ != history[i].sequence_) continue; if (newOne.where_ != history[i].where_) continue; if (newOne.numberUp_ != history[i].numberUp_) continue; if (newOne.sumUp_ != history[i].sumUp_) continue; if (newOne.numberUpInf_ != history[i].numberUpInf_) continue; if (newOne.upEst_ != history[i].upEst_) continue; if (newOne.numberDown_ != history[i].numberDown_) continue; if (newOne.sumDown_ != history[i].sumDown_) continue; if (newOne.numberDownInf_ != history[i].numberDownInf_) continue; if (newOne.downEst_ != history[i].downEst_) continue; // If B knock out previous B if (newOne.where_ == 'C') { fromCompare = true; if (newOne.status_ == 'B') { int j; for (j = i - 1; j >= 0; j--) { if (history[j].where_ == 'C') { if (history[j].status_ == 'I') { break; } else if (history[j].status_ == 'B') { history[j].status_ = ' '; break; } } } } break; } } if (i == -1 || fromCompare) { //add increaseHistory(); history[numberHistory++] = newOne; return true; } else { return false; } } #endif /** Default Constructor Equivalent to an unspecified binary variable. */ CbcSimpleIntegerDynamicPseudoCost::CbcSimpleIntegerDynamicPseudoCost () : CbcSimpleInteger(), downDynamicPseudoCost_(1.0e-5), upDynamicPseudoCost_(1.0e-5), upDownSeparator_(-1.0), sumDownCost_(0.0), sumUpCost_(0.0), sumDownChange_(0.0), sumUpChange_(0.0), downShadowPrice_(0.0), upShadowPrice_(0.0), sumDownDecrease_(0.0), sumUpDecrease_(0.0), lastDownCost_(0.0), lastUpCost_(0.0), lastDownDecrease_(0), lastUpDecrease_(0), numberTimesDown_(0), numberTimesUp_(0), numberTimesDownInfeasible_(0), numberTimesUpInfeasible_(0), numberBeforeTrust_(0), numberTimesDownLocalFixed_(0), numberTimesUpLocalFixed_(0), numberTimesDownTotalFixed_(0.0), numberTimesUpTotalFixed_(0.0), numberTimesProbingTotal_(0), method_(0) { } /** Useful constructor Loads dynamic upper & lower bounds for the specified variable. */ CbcSimpleIntegerDynamicPseudoCost::CbcSimpleIntegerDynamicPseudoCost (CbcModel * model, int iColumn, double breakEven) : CbcSimpleInteger(model, iColumn, breakEven), upDownSeparator_(-1.0), sumDownCost_(0.0), sumUpCost_(0.0), sumDownChange_(0.0), sumUpChange_(0.0), downShadowPrice_(0.0), upShadowPrice_(0.0), sumDownDecrease_(0.0), sumUpDecrease_(0.0), lastDownCost_(0.0), lastUpCost_(0.0), lastDownDecrease_(0), lastUpDecrease_(0), numberTimesDown_(0), numberTimesUp_(0), numberTimesDownInfeasible_(0), numberTimesUpInfeasible_(0), numberBeforeTrust_(0), numberTimesDownLocalFixed_(0), numberTimesUpLocalFixed_(0), numberTimesDownTotalFixed_(0.0), numberTimesUpTotalFixed_(0.0), numberTimesProbingTotal_(0), method_(0) { const double * cost = model->getObjCoefficients(); double costValue = CoinMax(1.0e-5, fabs(cost[iColumn])); // treat as if will cost what it says up upDynamicPseudoCost_ = costValue; // and balance at breakeven downDynamicPseudoCost_ = ((1.0 - breakEven_) * upDynamicPseudoCost_) / breakEven_; // so initial will have some effect sumUpCost_ = 2.0 * upDynamicPseudoCost_; sumUpChange_ = 2.0; numberTimesUp_ = 2; sumDownCost_ = 2.0 * downDynamicPseudoCost_; sumDownChange_ = 2.0; numberTimesDown_ = 2; #if TYPE2==0 // No sumUpCost_ = 0.0; sumUpChange_ = 0.0; numberTimesUp_ = 0; sumDownCost_ = 0.0; sumDownChange_ = 0.0; numberTimesDown_ = 0; #else sumUpCost_ = 1.0 * upDynamicPseudoCost_; sumUpChange_ = 1.0; numberTimesUp_ = 1; sumDownCost_ = 1.0 * downDynamicPseudoCost_; sumDownChange_ = 1.0; numberTimesDown_ = 1; #endif } /** Useful constructor Loads dynamic upper & lower bounds for the specified variable. */ CbcSimpleIntegerDynamicPseudoCost::CbcSimpleIntegerDynamicPseudoCost (CbcModel * model, int iColumn, double downDynamicPseudoCost, double upDynamicPseudoCost) : CbcSimpleInteger(model, iColumn), upDownSeparator_(-1.0), sumDownCost_(0.0), sumUpCost_(0.0), sumDownChange_(0.0), sumUpChange_(0.0), downShadowPrice_(0.0), upShadowPrice_(0.0), sumDownDecrease_(0.0), sumUpDecrease_(0.0), lastDownCost_(0.0), lastUpCost_(0.0), lastDownDecrease_(0), lastUpDecrease_(0), numberTimesDown_(0), numberTimesUp_(0), numberTimesDownInfeasible_(0), numberTimesUpInfeasible_(0), numberBeforeTrust_(0), numberTimesDownLocalFixed_(0), numberTimesUpLocalFixed_(0), numberTimesDownTotalFixed_(0.0), numberTimesUpTotalFixed_(0.0), numberTimesProbingTotal_(0), method_(0) { downDynamicPseudoCost_ = downDynamicPseudoCost; upDynamicPseudoCost_ = upDynamicPseudoCost; breakEven_ = upDynamicPseudoCost_ / (upDynamicPseudoCost_ + downDynamicPseudoCost_); // so initial will have some effect sumUpCost_ = 2.0 * upDynamicPseudoCost_; sumUpChange_ = 2.0; numberTimesUp_ = 2; sumDownCost_ = 2.0 * downDynamicPseudoCost_; sumDownChange_ = 2.0; numberTimesDown_ = 2; #if TYPE2==0 // No sumUpCost_ = 0.0; sumUpChange_ = 0.0; numberTimesUp_ = 0; sumDownCost_ = 0.0; sumDownChange_ = 0.0; numberTimesDown_ = 0; sumUpCost_ = 1.0e-4 * upDynamicPseudoCost_; sumDownCost_ = 1.0e-4 * downDynamicPseudoCost_; #else sumUpCost_ = 1.0 * upDynamicPseudoCost_; sumUpChange_ = 1.0; numberTimesUp_ = 1; sumDownCost_ = 1.0 * downDynamicPseudoCost_; sumDownChange_ = 1.0; numberTimesDown_ = 1; #endif } /** Useful constructor Loads dynamic upper & lower bounds for the specified variable. */ CbcSimpleIntegerDynamicPseudoCost::CbcSimpleIntegerDynamicPseudoCost (CbcModel * model, int /*dummy*/, int iColumn, double downDynamicPseudoCost, double upDynamicPseudoCost) { CbcSimpleIntegerDynamicPseudoCost(model, iColumn, downDynamicPseudoCost, upDynamicPseudoCost); } // Copy constructor CbcSimpleIntegerDynamicPseudoCost::CbcSimpleIntegerDynamicPseudoCost ( const CbcSimpleIntegerDynamicPseudoCost & rhs) : CbcSimpleInteger(rhs), downDynamicPseudoCost_(rhs.downDynamicPseudoCost_), upDynamicPseudoCost_(rhs.upDynamicPseudoCost_), upDownSeparator_(rhs.upDownSeparator_), sumDownCost_(rhs.sumDownCost_), sumUpCost_(rhs.sumUpCost_), sumDownChange_(rhs.sumDownChange_), sumUpChange_(rhs.sumUpChange_), downShadowPrice_(rhs.downShadowPrice_), upShadowPrice_(rhs.upShadowPrice_), sumDownDecrease_(rhs.sumDownDecrease_), sumUpDecrease_(rhs.sumUpDecrease_), lastDownCost_(rhs.lastDownCost_), lastUpCost_(rhs.lastUpCost_), lastDownDecrease_(rhs.lastDownDecrease_), lastUpDecrease_(rhs.lastUpDecrease_), numberTimesDown_(rhs.numberTimesDown_), numberTimesUp_(rhs.numberTimesUp_), numberTimesDownInfeasible_(rhs.numberTimesDownInfeasible_), numberTimesUpInfeasible_(rhs.numberTimesUpInfeasible_), numberBeforeTrust_(rhs.numberBeforeTrust_), numberTimesDownLocalFixed_(rhs.numberTimesDownLocalFixed_), numberTimesUpLocalFixed_(rhs.numberTimesUpLocalFixed_), numberTimesDownTotalFixed_(rhs.numberTimesDownTotalFixed_), numberTimesUpTotalFixed_(rhs.numberTimesUpTotalFixed_), numberTimesProbingTotal_(rhs.numberTimesProbingTotal_), method_(rhs.method_) { } // Clone CbcObject * CbcSimpleIntegerDynamicPseudoCost::clone() const { return new CbcSimpleIntegerDynamicPseudoCost(*this); } // Assignment operator CbcSimpleIntegerDynamicPseudoCost & CbcSimpleIntegerDynamicPseudoCost::operator=( const CbcSimpleIntegerDynamicPseudoCost & rhs) { if (this != &rhs) { CbcSimpleInteger::operator=(rhs); downDynamicPseudoCost_ = rhs.downDynamicPseudoCost_; upDynamicPseudoCost_ = rhs.upDynamicPseudoCost_; upDownSeparator_ = rhs.upDownSeparator_; sumDownCost_ = rhs.sumDownCost_; sumUpCost_ = rhs.sumUpCost_; sumDownChange_ = rhs.sumDownChange_; sumUpChange_ = rhs.sumUpChange_; downShadowPrice_ = rhs.downShadowPrice_; upShadowPrice_ = rhs.upShadowPrice_; sumDownDecrease_ = rhs.sumDownDecrease_; sumUpDecrease_ = rhs.sumUpDecrease_; lastDownCost_ = rhs.lastDownCost_; lastUpCost_ = rhs.lastUpCost_; lastDownDecrease_ = rhs.lastDownDecrease_; lastUpDecrease_ = rhs.lastUpDecrease_; numberTimesDown_ = rhs.numberTimesDown_; numberTimesUp_ = rhs.numberTimesUp_; numberTimesDownInfeasible_ = rhs.numberTimesDownInfeasible_; numberTimesUpInfeasible_ = rhs.numberTimesUpInfeasible_; numberBeforeTrust_ = rhs.numberBeforeTrust_; numberTimesDownLocalFixed_ = rhs.numberTimesDownLocalFixed_; numberTimesUpLocalFixed_ = rhs.numberTimesUpLocalFixed_; numberTimesDownTotalFixed_ = rhs.numberTimesDownTotalFixed_; numberTimesUpTotalFixed_ = rhs.numberTimesUpTotalFixed_; numberTimesProbingTotal_ = rhs.numberTimesProbingTotal_; method_ = rhs.method_; } return *this; } // Destructor CbcSimpleIntegerDynamicPseudoCost::~CbcSimpleIntegerDynamicPseudoCost () { } // Copy some information i.e. just variable stuff void CbcSimpleIntegerDynamicPseudoCost::copySome(const CbcSimpleIntegerDynamicPseudoCost * otherObject) { downDynamicPseudoCost_ = otherObject->downDynamicPseudoCost_; upDynamicPseudoCost_ = otherObject->upDynamicPseudoCost_; sumDownCost_ = otherObject->sumDownCost_; sumUpCost_ = otherObject->sumUpCost_; sumDownChange_ = otherObject->sumDownChange_; sumUpChange_ = otherObject->sumUpChange_; downShadowPrice_ = otherObject->downShadowPrice_; upShadowPrice_ = otherObject->upShadowPrice_; sumDownDecrease_ = otherObject->sumDownDecrease_; sumUpDecrease_ = otherObject->sumUpDecrease_; lastDownCost_ = otherObject->lastDownCost_; lastUpCost_ = otherObject->lastUpCost_; lastDownDecrease_ = otherObject->lastDownDecrease_; lastUpDecrease_ = otherObject->lastUpDecrease_; numberTimesDown_ = otherObject->numberTimesDown_; numberTimesUp_ = otherObject->numberTimesUp_; numberTimesDownInfeasible_ = otherObject->numberTimesDownInfeasible_; numberTimesUpInfeasible_ = otherObject->numberTimesUpInfeasible_; numberTimesDownLocalFixed_ = otherObject->numberTimesDownLocalFixed_; numberTimesUpLocalFixed_ = otherObject->numberTimesUpLocalFixed_; numberTimesDownTotalFixed_ = otherObject->numberTimesDownTotalFixed_; numberTimesUpTotalFixed_ = otherObject->numberTimesUpTotalFixed_; numberTimesProbingTotal_ = otherObject->numberTimesProbingTotal_; } // Updates stuff like pseudocosts before threads void CbcSimpleIntegerDynamicPseudoCost::updateBefore(const OsiObject * rhs) { #ifndef NDEBUG const CbcSimpleIntegerDynamicPseudoCost * rhsObject = dynamic_cast (rhs) ; assert (rhsObject); #else const CbcSimpleIntegerDynamicPseudoCost * rhsObject = static_cast (rhs) ; #endif copySome(rhsObject); } // Updates stuff like pseudocosts after threads finished void CbcSimpleIntegerDynamicPseudoCost::updateAfter(const OsiObject * rhs, const OsiObject * baseObjectX) { #ifndef NDEBUG const CbcSimpleIntegerDynamicPseudoCost * rhsObject = dynamic_cast (rhs) ; assert (rhsObject); const CbcSimpleIntegerDynamicPseudoCost * baseObject = dynamic_cast (baseObjectX) ; assert (baseObject); #else const CbcSimpleIntegerDynamicPseudoCost * rhsObject = static_cast (rhs) ; const CbcSimpleIntegerDynamicPseudoCost * baseObject = static_cast (baseObjectX) ; #endif // compute current double sumDown = downDynamicPseudoCost_ * numberTimesDown_; sumDown -= baseObject->downDynamicPseudoCost_ * baseObject->numberTimesDown_; sumDown = CoinMax(sumDown, 0.0); sumDown += rhsObject->downDynamicPseudoCost_ * rhsObject->numberTimesDown_; assert (rhsObject->numberTimesDown_ >= baseObject->numberTimesDown_); assert (rhsObject->numberTimesDownInfeasible_ >= baseObject->numberTimesDownInfeasible_); assert( rhsObject->sumDownCost_ >= baseObject->sumDownCost_); double sumUp = upDynamicPseudoCost_ * numberTimesUp_; sumUp -= baseObject->upDynamicPseudoCost_ * baseObject->numberTimesUp_; sumUp = CoinMax(sumUp, 0.0); sumUp += rhsObject->upDynamicPseudoCost_ * rhsObject->numberTimesUp_; assert (rhsObject->numberTimesUp_ >= baseObject->numberTimesUp_); assert (rhsObject->numberTimesUpInfeasible_ >= baseObject->numberTimesUpInfeasible_); assert( rhsObject->sumUpCost_ >= baseObject->sumUpCost_); sumDownCost_ += rhsObject->sumDownCost_ - baseObject->sumDownCost_; sumUpCost_ += rhsObject->sumUpCost_ - baseObject->sumUpCost_; sumDownChange_ += rhsObject->sumDownChange_ - baseObject->sumDownChange_; sumUpChange_ += rhsObject->sumUpChange_ - baseObject->sumUpChange_; downShadowPrice_ = 0.0; upShadowPrice_ = 0.0; sumDownDecrease_ += rhsObject->sumDownDecrease_ - baseObject->sumDownDecrease_; sumUpDecrease_ += rhsObject->sumUpDecrease_ - baseObject->sumUpDecrease_; lastDownCost_ += rhsObject->lastDownCost_ - baseObject->lastDownCost_; lastUpCost_ += rhsObject->lastUpCost_ - baseObject->lastUpCost_; lastDownDecrease_ += rhsObject->lastDownDecrease_ - baseObject->lastDownDecrease_; lastUpDecrease_ += rhsObject->lastUpDecrease_ - baseObject->lastUpDecrease_; numberTimesDown_ += rhsObject->numberTimesDown_ - baseObject->numberTimesDown_; numberTimesUp_ += rhsObject->numberTimesUp_ - baseObject->numberTimesUp_; numberTimesDownInfeasible_ += rhsObject->numberTimesDownInfeasible_ - baseObject->numberTimesDownInfeasible_; numberTimesUpInfeasible_ += rhsObject->numberTimesUpInfeasible_ - baseObject->numberTimesUpInfeasible_; numberTimesDownLocalFixed_ += rhsObject->numberTimesDownLocalFixed_ - baseObject->numberTimesDownLocalFixed_; numberTimesUpLocalFixed_ += rhsObject->numberTimesUpLocalFixed_ - baseObject->numberTimesUpLocalFixed_; numberTimesDownTotalFixed_ += rhsObject->numberTimesDownTotalFixed_ - baseObject->numberTimesDownTotalFixed_; numberTimesUpTotalFixed_ += rhsObject->numberTimesUpTotalFixed_ - baseObject->numberTimesUpTotalFixed_; numberTimesProbingTotal_ += rhsObject->numberTimesProbingTotal_ - baseObject->numberTimesProbingTotal_; if (numberTimesDown_ > 0) { setDownDynamicPseudoCost(sumDown / static_cast (numberTimesDown_)); } if (numberTimesUp_ > 0) { setUpDynamicPseudoCost(sumUp / static_cast (numberTimesUp_)); } //printf("XX %d down %d %d %g up %d %d %g\n",columnNumber_,numberTimesDown_,numberTimesDownInfeasible_,downDynamicPseudoCost_, // numberTimesUp_,numberTimesUpInfeasible_,upDynamicPseudoCost_); assert (downDynamicPseudoCost_ > 1.0e-40 && upDynamicPseudoCost_ > 1.0e-40); } // Same - returns true if contents match(ish) bool CbcSimpleIntegerDynamicPseudoCost::same(const CbcSimpleIntegerDynamicPseudoCost * otherObject) const { bool okay = true; if (downDynamicPseudoCost_ != otherObject->downDynamicPseudoCost_) okay = false; if (upDynamicPseudoCost_ != otherObject->upDynamicPseudoCost_) okay = false; if (sumDownCost_ != otherObject->sumDownCost_) okay = false; if (sumUpCost_ != otherObject->sumUpCost_) okay = false; if (sumDownChange_ != otherObject->sumDownChange_) okay = false; if (sumUpChange_ != otherObject->sumUpChange_) okay = false; if (downShadowPrice_ != otherObject->downShadowPrice_) okay = false; if (upShadowPrice_ != otherObject->upShadowPrice_) okay = false; if (sumDownDecrease_ != otherObject->sumDownDecrease_) okay = false; if (sumUpDecrease_ != otherObject->sumUpDecrease_) okay = false; if (lastDownCost_ != otherObject->lastDownCost_) okay = false; if (lastUpCost_ != otherObject->lastUpCost_) okay = false; if (lastDownDecrease_ != otherObject->lastDownDecrease_) okay = false; if (lastUpDecrease_ != otherObject->lastUpDecrease_) okay = false; if (numberTimesDown_ != otherObject->numberTimesDown_) okay = false; if (numberTimesUp_ != otherObject->numberTimesUp_) okay = false; if (numberTimesDownInfeasible_ != otherObject->numberTimesDownInfeasible_) okay = false; if (numberTimesUpInfeasible_ != otherObject->numberTimesUpInfeasible_) okay = false; if (numberTimesDownLocalFixed_ != otherObject->numberTimesDownLocalFixed_) okay = false; if (numberTimesUpLocalFixed_ != otherObject->numberTimesUpLocalFixed_) okay = false; if (numberTimesDownTotalFixed_ != otherObject->numberTimesDownTotalFixed_) okay = false; if (numberTimesUpTotalFixed_ != otherObject->numberTimesUpTotalFixed_) okay = false; if (numberTimesProbingTotal_ != otherObject->numberTimesProbingTotal_) okay = false; return okay; } /* Create an OsiSolverBranch object This returns NULL if branch not represented by bound changes */ OsiSolverBranch * CbcSimpleIntegerDynamicPseudoCost::solverBranch() const { OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); assert (upper[columnNumber_] > lower[columnNumber_]); #ifndef NDEBUG double nearest = floor(value + 0.5); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); assert (fabs(value - nearest) > integerTolerance); #endif OsiSolverBranch * branch = new OsiSolverBranch(); branch->addBranch(columnNumber_, value); return branch; } //#define FUNNY_BRANCHING double CbcSimpleIntegerDynamicPseudoCost::infeasibility(const OsiBranchingInformation * info, int &preferredWay) const { assert (downDynamicPseudoCost_ > 1.0e-40 && upDynamicPseudoCost_ > 1.0e-40); const double * solution = model_->testSolution(); const double * lower = model_->getCbcColLower(); const double * upper = model_->getCbcColUpper(); #ifdef FUNNY_BRANCHING2 const double * dj = model_->getCbcReducedCost(); double djValue = dj[columnNumber_]; lastDownDecrease_++; if (djValue > 1.0e-6) { // wants to go down if (true || lower[columnNumber_] > originalLower_) { // Lower bound active lastUpDecrease_++; } } else if (djValue < -1.0e-6) { // wants to go up if (true || upper[columnNumber_] < originalUpper_) { // Upper bound active lastUpDecrease_++; } } #endif if (upper[columnNumber_] == lower[columnNumber_]) { // fixed preferredWay = 1; return 0.0; } assert (breakEven_ > 0.0 && breakEven_ < 1.0); /* Find nearest integer, and integers above and below current value. Given that we've already forced value within bounds, if (current value)+(integer tolerance) > (upper bound) shouldn't we declare this variable integer? */ double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); /*printf("%d %g %g %g %g\n",columnNumber_,value,lower[columnNumber_], solution[columnNumber_],upper[columnNumber_]);*/ double nearest = floor(value + 0.5); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double below = floor(value + integerTolerance); double above = below + 1.0; if (above > upper[columnNumber_]) { above = below; below = above - 1; } #if INFEAS==1 /* Why do we inflate the distance to the cutoff by a factor of 10 for values that could be considered reachable? Why do we add 100 for values larger than 1e20? */ double distanceToCutoff = 0.0; double objectiveValue = model_->getCurrentMinimizationObjValue(); distanceToCutoff = model_->getCutoff() - objectiveValue; if (distanceToCutoff < 1.0e20) distanceToCutoff *= 10.0; else distanceToCutoff = 1.0e2 + fabs(objectiveValue); distanceToCutoff = CoinMax(distanceToCutoff, 1.0e-12 * (1.0 + fabs(objectiveValue))); #endif double sum; #ifndef INFEAS_MULTIPLIER #define INFEAS_MULTIPLIER 1.0 #endif double number; double downCost = CoinMax(value - below, 0.0); #if TYPE2==0 sum = sumDownCost_; number = numberTimesDown_; #if INFEAS==1 sum += INFEAS_MULTIPLIER*numberTimesDownInfeasible_ * CoinMax(distanceToCutoff / (downCost + 1.0e-12), sumDownCost_); #endif #elif TYPE2==1 sum = sumDownCost_; number = sumDownChange_; #if INFEAS==1 sum += INFEAS_MULTIPLIER*numberTimesDownInfeasible_ * CoinMax(distanceToCutoff / (downCost + 1.0e-12), sumDownCost_); #endif #elif TYPE2==2 abort(); #if INFEAS==1 sum += INFEAS_MULTIPLIER*numberTimesDownInfeasible_ * (distanceToCutoff / (downCost + 1.0e-12)); #endif #endif #if MOD_SHADOW>0 if (!downShadowPrice_) { if (number > 0.0) downCost *= sum / number; else downCost *= downDynamicPseudoCost_; } else if (downShadowPrice_ > 0.0) { downCost *= downShadowPrice_; } else { downCost *= (downDynamicPseudoCost_ - downShadowPrice_); } #else if (downShadowPrice_ <= 0.0) { if (number > 0.0) downCost *= sum / number; else downCost *= downDynamicPseudoCost_; } else { downCost *= downShadowPrice_; } #endif double upCost = CoinMax((above - value), 0.0); #if TYPE2==0 sum = sumUpCost_; number = numberTimesUp_; #if INFEAS==1 sum += INFEAS_MULTIPLIER*numberTimesUpInfeasible_ * CoinMax(distanceToCutoff / (upCost + 1.0e-12), sumUpCost_); #endif #elif TYPE2==1 sum = sumUpCost_; number = sumUpChange_; #if INFEAS==1 sum += INFEAS_MULTIPLIER*numberTimesUpInfeasible_ * CoinMax(distanceToCutoff / (upCost + 1.0e-12), sumUpCost_); #endif #elif TYPE2==1 abort(); #if INFEAS==1 sum += INFEAS_MULTIPLIER*numberTimesUpInfeasible_ * (distanceToCutoff / (upCost + 1.0e-12)); #endif #endif #if MOD_SHADOW>0 if (!upShadowPrice_) { if (number > 0.0) upCost *= sum / number; else upCost *= upDynamicPseudoCost_; } else if (upShadowPrice_ > 0.0) { upCost *= upShadowPrice_; } else { upCost *= (upDynamicPseudoCost_ - upShadowPrice_); } #else if (upShadowPrice_ <= 0.0) { if (number > 0.0) upCost *= sum / number; else upCost *= upDynamicPseudoCost_; } else { upCost *= upShadowPrice_; } #endif if (downCost >= upCost) preferredWay = 1; else preferredWay = -1; // See if up down choice set if (upDownSeparator_ > 0.0) { preferredWay = (value - below >= upDownSeparator_) ? 1 : -1; } #ifdef FUNNY_BRANCHING2 if (fabs(value - nearest) > integerTolerance) { double ratio = (100.0 + lastUpDecrease_) / (100.0 + lastDownDecrease_); downCost *= ratio; upCost *= ratio; if ((lastUpDecrease_ % 100) == -1) printf("col %d total %d djtimes %d\n", columnNumber_, lastDownDecrease_, lastUpDecrease_); } #endif if (preferredWay_) preferredWay = preferredWay_; if (info->hotstartSolution_) { double targetValue = info->hotstartSolution_[columnNumber_]; if (value > targetValue) preferredWay = -1; else preferredWay = 1; } if (fabs(value - nearest) <= integerTolerance) { if (priority_ != -999) return 0.0; else return 1.0e-13; } else { int stateOfSearch = model_->stateOfSearch() % 10; double returnValue = 0.0; double minValue = CoinMin(downCost, upCost); double maxValue = CoinMax(downCost, upCost); #ifdef COIN_DEVELOP char where; #endif // was <= 10 //if (stateOfSearch<=1||model_->currentNode()->depth()<=-10 /* was ||maxValue>0.2*distanceToCutoff*/) { if (stateOfSearch <= 2) { // no branching solution #ifdef COIN_DEVELOP where = 'i'; #endif returnValue = WEIGHT_BEFORE * minValue + (1.0 - WEIGHT_BEFORE) * maxValue; if (0) { double sum; int number; double downCost2 = CoinMax(value - below, 0.0); sum = sumDownCost_; number = numberTimesDown_; if (number > 0) downCost2 *= sum / static_cast (number); else downCost2 *= downDynamicPseudoCost_; double upCost2 = CoinMax((above - value), 0.0); sum = sumUpCost_; number = numberTimesUp_; if (number > 0) upCost2 *= sum / static_cast (number); else upCost2 *= upDynamicPseudoCost_; double minValue2 = CoinMin(downCost2, upCost2); double maxValue2 = CoinMax(downCost2, upCost2); printf("%d value %g downC %g upC %g minV %g maxV %g downC2 %g upC2 %g minV2 %g maxV2 %g\n", columnNumber_, value, downCost, upCost, minValue, maxValue, downCost2, upCost2, minValue2, maxValue2); } } else { // some solution #ifdef COIN_DEVELOP where = 'I'; #endif #ifndef WEIGHT_PRODUCT returnValue = WEIGHT_AFTER * minValue + (1.0 - WEIGHT_AFTER) * maxValue; #else double minProductWeight = model_->getDblParam(CbcModel::CbcSmallChange); returnValue = CoinMax(minValue, minProductWeight) * CoinMax(maxValue, minProductWeight); //returnValue += minProductWeight*minValue; #endif } if (numberTimesUp_ < numberBeforeTrust_ || numberTimesDown_ < numberBeforeTrust_) { //if (returnValue<1.0e10) //returnValue += 1.0e12; //else returnValue *= 1.0e3; if (!numberTimesUp_ && !numberTimesDown_) returnValue *= 1.0e10; } //if (fabs(value-0.5)<1.0e-5) { //returnValue = 3.0*returnValue + 0.2; //} else if (value>0.9) { //returnValue = 2.0*returnValue + 0.1; //} if (method_ == 1) { // probing // average double up = 1.0e-15; double down = 1.0e-15; if (numberTimesProbingTotal_) { up += numberTimesUpTotalFixed_ / static_cast (numberTimesProbingTotal_); down += numberTimesDownTotalFixed_ / static_cast (numberTimesProbingTotal_); } returnValue = 1 + 10.0 * CoinMin(numberTimesDownLocalFixed_, numberTimesUpLocalFixed_) + CoinMin(down, up); returnValue *= 1.0e-3; } #ifdef COIN_DEVELOP History hist; hist.where_ = where; hist.status_ = ' '; hist.sequence_ = columnNumber_; hist.numberUp_ = numberTimesUp_; hist.numberUpInf_ = numberTimesUpInfeasible_; hist.sumUp_ = sumUpCost_; hist.upEst_ = upCost; hist.numberDown_ = numberTimesDown_; hist.numberDownInf_ = numberTimesDownInfeasible_; hist.sumDown_ = sumDownCost_; hist.downEst_ = downCost; if (stateOfSearch) addRecord(hist); #endif return CoinMax(returnValue, 1.0e-15); } } // Creates a branching object CbcBranchingObject * CbcSimpleIntegerDynamicPseudoCost::createCbcBranch(OsiSolverInterface * /*solver*/, const OsiBranchingInformation * info, int way) { double value = info->solution_[columnNumber_]; value = CoinMax(value, info->lower_[columnNumber_]); value = CoinMin(value, info->upper_[columnNumber_]); assert (info->upper_[columnNumber_] > info->lower_[columnNumber_]); if (!info->hotstartSolution_ && priority_ != -999) { #ifndef NDEBUG double nearest = floor(value + 0.5); assert (fabs(value - nearest) > info->integerTolerance_); #endif } else if (info->hotstartSolution_) { double targetValue = info->hotstartSolution_[columnNumber_]; if (way > 0) value = targetValue - 0.1; else value = targetValue + 0.1; } else { if (value <= info->lower_[columnNumber_]) value += 0.1; else if (value >= info->upper_[columnNumber_]) value -= 0.1; } assert (value >= info->lower_[columnNumber_] && value <= info->upper_[columnNumber_]); CbcDynamicPseudoCostBranchingObject * newObject = new CbcDynamicPseudoCostBranchingObject(model_, columnNumber_, way, value, this); double up = upDynamicPseudoCost_ * (ceil(value) - value); double down = downDynamicPseudoCost_ * (value - floor(value)); double changeInGuessed = up - down; if (way > 0) changeInGuessed = - changeInGuessed; changeInGuessed = CoinMax(0.0, changeInGuessed); //if (way>0) //changeInGuessed += 1.0e8; // bias to stay up newObject->setChangeInGuessed(changeInGuessed); newObject->setOriginalObject(this); return newObject; } // Return "up" estimate double CbcSimpleIntegerDynamicPseudoCost::upEstimate() const { const double * solution = model_->testSolution(); const double * lower = model_->getCbcColLower(); const double * upper = model_->getCbcColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); if (upper[columnNumber_] == lower[columnNumber_]) { // fixed return 0.0; } double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double below = floor(value + integerTolerance); double above = below + 1.0; if (above > upper[columnNumber_]) { above = below; below = above - 1; } double upCost = CoinMax((above - value) * upDynamicPseudoCost_, 0.0); return upCost; } // Return "down" estimate double CbcSimpleIntegerDynamicPseudoCost::downEstimate() const { const double * solution = model_->testSolution(); const double * lower = model_->getCbcColLower(); const double * upper = model_->getCbcColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); if (upper[columnNumber_] == lower[columnNumber_]) { // fixed return 0.0; } double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double below = floor(value + integerTolerance); double above = below + 1.0; if (above > upper[columnNumber_]) { above = below; below = above - 1; } double downCost = CoinMax((value - below) * downDynamicPseudoCost_, 0.0); return downCost; } // Set down pseudo cost void CbcSimpleIntegerDynamicPseudoCost::setDownDynamicPseudoCost(double value) { #ifdef TRACE_ONE double oldDown = sumDownCost_; #endif downDynamicPseudoCost_ = value; sumDownCost_ = CoinMax(sumDownCost_, value * numberTimesDown_); #ifdef TRACE_ONE if (columnNumber_ == TRACE_ONE) { double down = downDynamicPseudoCost_ * numberTimesDown_; printf("For %d sumDown %g (%d), inf (%d) - pseudo %g - sumDown was %g -> %g\n", TRACE_ONE, down, numberTimesDown_, numberTimesDownInfeasible_, downDynamicPseudoCost_, oldDown, sumDownCost_); } #endif } // Modify down pseudo cost in a slightly different way void CbcSimpleIntegerDynamicPseudoCost::updateDownDynamicPseudoCost(double value) { sumDownCost_ += value; numberTimesDown_++; downDynamicPseudoCost_ = sumDownCost_ / static_cast(numberTimesDown_); } // Set up pseudo cost void CbcSimpleIntegerDynamicPseudoCost::setUpDynamicPseudoCost(double value) { #ifdef TRACE_ONE double oldUp = sumUpCost_; #endif upDynamicPseudoCost_ = value; sumUpCost_ = CoinMax(sumUpCost_, value * numberTimesUp_); #ifdef TRACE_ONE if (columnNumber_ == TRACE_ONE) { double up = upDynamicPseudoCost_ * numberTimesUp_; printf("For %d sumUp %g (%d), inf (%d) - pseudo %g - sumUp was %g -> %g\n", TRACE_ONE, up, numberTimesUp_, numberTimesUpInfeasible_, upDynamicPseudoCost_, oldUp, sumUpCost_); } #endif } // Modify up pseudo cost in a slightly different way void CbcSimpleIntegerDynamicPseudoCost::updateUpDynamicPseudoCost(double value) { sumUpCost_ += value; numberTimesUp_++; upDynamicPseudoCost_ = sumUpCost_ / static_cast(numberTimesUp_); } /* Pass in information on branch just done and create CbcObjectUpdateData instance. If object does not need data then backward pointer will be NULL. Assumes can get information from solver */ CbcObjectUpdateData CbcSimpleIntegerDynamicPseudoCost::createUpdateInformation(const OsiSolverInterface * solver, const CbcNode * node, const CbcBranchingObject * branchingObject) { double originalValue = node->objectiveValue(); int originalUnsatisfied = node->numberUnsatisfied(); double objectiveValue = solver->getObjValue() * solver->getObjSense(); int unsatisfied = 0; int i; //might be base model - doesn't matter int numberIntegers = model_->numberIntegers();; const double * solution = solver->getColSolution(); //const double * lower = solver->getColLower(); //const double * upper = solver->getColUpper(); double change = CoinMax(0.0, objectiveValue - originalValue); int iStatus; if (solver->isProvenOptimal()) iStatus = 0; // optimal else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) iStatus = 2; // unknown else iStatus = 1; // infeasible bool feasible = iStatus != 1; if (feasible) { double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); const int * integerVariable = model_->integerVariable(); for (i = 0; i < numberIntegers; i++) { int j = integerVariable[i]; double value = solution[j]; double nearest = floor(value + 0.5); if (fabs(value - nearest) > integerTolerance) unsatisfied++; } } int way = branchingObject->way(); way = - way; // because after branch so moved on double value = branchingObject->value(); CbcObjectUpdateData newData (this, way, change, iStatus, originalUnsatisfied - unsatisfied, value); newData.originalObjective_ = originalValue; // Solvers know about direction double direction = solver->getObjSense(); solver->getDblParam(OsiDualObjectiveLimit, newData.cutoff_); newData.cutoff_ *= direction; return newData; } // Just update using feasible branches and keep count of infeasible #undef INFEAS // Update object by CbcObjectUpdateData void CbcSimpleIntegerDynamicPseudoCost::updateInformation(const CbcObjectUpdateData & data) { bool feasible = data.status_ != 1; int way = data.way_; double value = data.branchingValue_; double change = data.change_; #ifdef COIN_DEVELOP History hist; hist.where_ = 'U'; // need to tell if hot #endif double movement = 0.0; if (way < 0) { // down movement = value - floor(value); if (feasible) { #ifdef COIN_DEVELOP hist.status_ = 'D'; #endif movement = CoinMax(movement, MINIMUM_MOVEMENT); //printf("(down change %g value down %g ",change,movement); incrementNumberTimesDown(); addToSumDownChange(1.0e-30 + movement); addToSumDownDecrease(data.intDecrease_); #if TYPE2==0 addToSumDownCost(change / (1.0e-30 + movement)); setDownDynamicPseudoCost(sumDownCost() / static_cast( numberTimesDown())); #elif TYPE2==1 addToSumDownCost(change); setDownDynamicPseudoCost(sumDownCost() / sumDownChange()); #elif TYPE2==2 addToSumDownCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement)); setDownDynamicPseudoCost(sumDownCost()*(TYPERATIO / sumDownChange() + (1.0 - TYPERATIO) / (double) numberTimesDown())); #endif } else { #ifdef COIN_DEVELOP hist.status_ = 'd'; #endif //printf("(down infeasible value down %g ",change,movement); incrementNumberTimesDown(); incrementNumberTimesDownInfeasible(); #if INFEAS==2 double distanceToCutoff = 0.0; double objectiveValue = model->getCurrentMinimizationObjValue(); distanceToCutoff = model->getCutoff() - originalValue; if (distanceToCutoff < 1.0e20) change = distanceToCutoff * 2.0; else change = downDynamicPseudoCost() * movement * 10.0; change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change); addToSumDownChange(1.0e-30 + movement); addToSumDownDecrease(data.intDecrease_); #if TYPE2==0 addToSumDownCost(change / (1.0e-30 + movement)); setDownDynamicPseudoCost(sumDownCost() / (double) numberTimesDown()); #elif TYPE2==1 addToSumDownCost(change); setDownDynamicPseudoCost(sumDownCost() / sumDownChange()); #elif TYPE2==2 addToSumDownCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement)); setDownDynamicPseudoCost(sumDownCost()*(TYPERATIO / sumDownChange() + (1.0 - TYPERATIO) / (double) numberTimesDown())); #endif #endif } #if INFEAS==1 double sum = sumDownCost_; int number = numberTimesDown_; double originalValue = data.originalObjective_; assert (originalValue != COIN_DBL_MAX); double distanceToCutoff = data.cutoff_ - originalValue; if (distanceToCutoff > 1.0e20) distanceToCutoff = 10.0 + fabs(originalValue); sum += INFEAS_MULTIPLIER*numberTimesDownInfeasible_ * CoinMax(distanceToCutoff, 1.0e-12 * (1.0 + fabs(originalValue))); setDownDynamicPseudoCost(sum / static_cast (number)); #endif } else { // up movement = ceil(value) - value; if (feasible) { #ifdef COIN_DEVELOP hist.status_ = 'U'; #endif movement = CoinMax(movement, MINIMUM_MOVEMENT); //printf("(up change %g value down %g ",change,movement); incrementNumberTimesUp(); addToSumUpChange(1.0e-30 + movement); addToSumUpDecrease(data.intDecrease_); #if TYPE2==0 addToSumUpCost(change / (1.0e-30 + movement)); setUpDynamicPseudoCost(sumUpCost() / static_cast (numberTimesUp())); #elif TYPE2==1 addToSumUpCost(change); setUpDynamicPseudoCost(sumUpCost() / sumUpChange()); #elif TYPE2==2 addToSumUpCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement)); setUpDynamicPseudoCost(sumUpCost()*(TYPERATIO / sumUpChange() + (1.0 - TYPERATIO) / (double) numberTimesUp())); #endif } else { #ifdef COIN_DEVELOP hist.status_ = 'u'; #endif //printf("(up infeasible value down %g ",change,movement); incrementNumberTimesUp(); incrementNumberTimesUpInfeasible(); #if INFEAS==2 double distanceToCutoff = 0.0; double objectiveValue = model->getCurrentMinimizationObjValue(); distanceToCutoff = model->getCutoff() - originalValue; if (distanceToCutoff < 1.0e20) change = distanceToCutoff * 2.0; else change = upDynamicPseudoCost() * movement * 10.0; change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change); addToSumUpChange(1.0e-30 + movement); addToSumUpDecrease(data.intDecrease_); #if TYPE2==0 addToSumUpCost(change / (1.0e-30 + movement)); setUpDynamicPseudoCost(sumUpCost() / (double) numberTimesUp()); #elif TYPE2==1 addToSumUpCost(change); setUpDynamicPseudoCost(sumUpCost() / sumUpChange()); #elif TYPE2==2 addToSumUpCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement)); setUpDynamicPseudoCost(sumUpCost()*(TYPERATIO / sumUpChange() + (1.0 - TYPERATIO) / (double) numberTimesUp())); #endif #endif } #if INFEAS==1 double sum = sumUpCost_; int number = numberTimesUp_; double originalValue = data.originalObjective_; assert (originalValue != COIN_DBL_MAX); double distanceToCutoff = data.cutoff_ - originalValue; if (distanceToCutoff > 1.0e20) distanceToCutoff = 10.0 + fabs(originalValue); sum += INFEAS_MULTIPLIER*numberTimesUpInfeasible_ * CoinMax(distanceToCutoff, 1.0e-12 * (1.0 + fabs(originalValue))); setUpDynamicPseudoCost(sum / static_cast (number)); #endif } if (data.way_ < 0) assert (numberTimesDown_ > 0); else assert (numberTimesUp_ > 0); assert (downDynamicPseudoCost_ >= 0.0 && downDynamicPseudoCost_ < 1.0e100); downDynamicPseudoCost_ = CoinMax(1.0e-10, downDynamicPseudoCost_); assert (upDynamicPseudoCost_ >= 0.0 && upDynamicPseudoCost_ < 1.0e100); upDynamicPseudoCost_ = CoinMax(1.0e-10, upDynamicPseudoCost_); #ifdef COIN_DEVELOP hist.sequence_ = columnNumber_; hist.numberUp_ = numberTimesUp_; hist.numberUpInf_ = numberTimesUpInfeasible_; hist.sumUp_ = sumUpCost_; hist.upEst_ = change; hist.numberDown_ = numberTimesDown_; hist.numberDownInf_ = numberTimesDownInfeasible_; hist.sumDown_ = sumDownCost_; hist.downEst_ = movement; addRecord(hist); #endif //print(1,0.5); assert (downDynamicPseudoCost_ > 1.0e-40 && upDynamicPseudoCost_ > 1.0e-40); #if MOD_SHADOW>1 if (upShadowPrice_ > 0.0 && numberTimesDown_ >= numberBeforeTrust_ && numberTimesUp_ >= numberBeforeTrust_) { // Set negative upShadowPrice_ = -upShadowPrice_; assert (downShadowPrice_ > 0.0); downShadowPrice_ = - downShadowPrice_; } #endif } // Updates stuff like pseudocosts after mini branch and bound void CbcSimpleIntegerDynamicPseudoCost::updateAfterMini(int numberDown, int numberDownInfeasible, double sumDown, int numberUp, int numberUpInfeasible, double sumUp) { numberTimesDown_ = numberDown; numberTimesDownInfeasible_ = numberDownInfeasible; sumDownCost_ = sumDown; numberTimesUp_ = numberUp; numberTimesUpInfeasible_ = numberUpInfeasible; sumUpCost_ = sumUp; if (numberTimesDown_ > 0) { setDownDynamicPseudoCost(sumDownCost_ / static_cast (numberTimesDown_)); assert (downDynamicPseudoCost_ > 0.0 && downDynamicPseudoCost_ < 1.0e50); } if (numberTimesUp_ > 0) { setUpDynamicPseudoCost(sumUpCost_ / static_cast (numberTimesUp_)); assert (upDynamicPseudoCost_ > 0.0 && upDynamicPseudoCost_ < 1.0e50); } assert (downDynamicPseudoCost_ > 1.0e-40 && upDynamicPseudoCost_ > 1.0e-40); } // Pass in probing information void CbcSimpleIntegerDynamicPseudoCost::setProbingInformation(int fixedDown, int fixedUp) { numberTimesProbingTotal_++; numberTimesDownLocalFixed_ = fixedDown; numberTimesDownTotalFixed_ += fixedDown; numberTimesUpLocalFixed_ = fixedUp; numberTimesUpTotalFixed_ += fixedUp; } // Print void CbcSimpleIntegerDynamicPseudoCost::print(int type, double value) const { if (!type) { double meanDown = 0.0; double devDown = 0.0; if (numberTimesDown_) { meanDown = sumDownCost_ / static_cast (numberTimesDown_); devDown = meanDown * meanDown - 2.0 * meanDown * sumDownCost_; if (devDown >= 0.0) devDown = sqrt(devDown); } double meanUp = 0.0; double devUp = 0.0; if (numberTimesUp_) { meanUp = sumUpCost_ / static_cast (numberTimesUp_); devUp = meanUp * meanUp - 2.0 * meanUp * sumUpCost_; if (devUp >= 0.0) devUp = sqrt(devUp); } printf("%d down %d times (%d inf) mean %g (dev %g) up %d times (%d inf) mean %g (dev %g)\n", columnNumber_, numberTimesDown_, numberTimesDownInfeasible_, meanDown, devDown, numberTimesUp_, numberTimesUpInfeasible_, meanUp, devUp); } else { const double * upper = model_->getCbcColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double below = floor(value + integerTolerance); double above = below + 1.0; if (above > upper[columnNumber_]) { above = below; below = above - 1; } double objectiveValue = model_->getCurrentMinimizationObjValue(); double distanceToCutoff = model_->getCutoff() - objectiveValue; if (distanceToCutoff < 1.0e20) distanceToCutoff *= 10.0; else distanceToCutoff = 1.0e2 + fabs(objectiveValue); distanceToCutoff = CoinMax(distanceToCutoff, 1.0e-12 * (1.0 + fabs(objectiveValue))); double sum; int number; double downCost = CoinMax(value - below, 0.0); double downCost0 = downCost * downDynamicPseudoCost_; sum = sumDownCost(); number = numberTimesDown(); sum += INFEAS_MULTIPLIER*numberTimesDownInfeasible() * (distanceToCutoff / (downCost + 1.0e-12)); if (number > 0) downCost *= sum / static_cast (number); else downCost *= downDynamicPseudoCost_; double upCost = CoinMax((above - value), 0.0); double upCost0 = upCost * upDynamicPseudoCost_; sum = sumUpCost(); number = numberTimesUp(); sum += INFEAS_MULTIPLIER*numberTimesUpInfeasible() * (distanceToCutoff / (upCost + 1.0e-12)); if (number > 0) upCost *= sum / static_cast (number); else upCost *= upDynamicPseudoCost_; printf("%d down %d times %g (est %g) up %d times %g (est %g)\n", columnNumber_, numberTimesDown_, downCost, downCost0, numberTimesUp_, upCost, upCost0); } } //############################################################################## // Default Constructor CbcIntegerPseudoCostBranchingObject::CbcIntegerPseudoCostBranchingObject() : CbcIntegerBranchingObject() { changeInGuessed_ = 1.0e-5; } // Useful constructor CbcIntegerPseudoCostBranchingObject::CbcIntegerPseudoCostBranchingObject (CbcModel * model, int variable, int way , double value) : CbcIntegerBranchingObject(model, variable, way, value) { } // Useful constructor for fixing CbcIntegerPseudoCostBranchingObject::CbcIntegerPseudoCostBranchingObject (CbcModel * model, int variable, int way, double lowerValue, double /*upperValue*/) : CbcIntegerBranchingObject(model, variable, way, lowerValue) { changeInGuessed_ = 1.0e100; } // Copy constructor CbcIntegerPseudoCostBranchingObject::CbcIntegerPseudoCostBranchingObject ( const CbcIntegerPseudoCostBranchingObject & rhs) : CbcIntegerBranchingObject(rhs) { changeInGuessed_ = rhs.changeInGuessed_; } // Assignment operator CbcIntegerPseudoCostBranchingObject & CbcIntegerPseudoCostBranchingObject::operator=( const CbcIntegerPseudoCostBranchingObject & rhs) { if (this != &rhs) { CbcIntegerBranchingObject::operator=(rhs); changeInGuessed_ = rhs.changeInGuessed_; } return *this; } CbcBranchingObject * CbcIntegerPseudoCostBranchingObject::clone() const { return (new CbcIntegerPseudoCostBranchingObject(*this)); } // Destructor CbcIntegerPseudoCostBranchingObject::~CbcIntegerPseudoCostBranchingObject () { } /* Perform a branch by adjusting the bounds of the specified variable. Note that each arm of the branch advances the object to the next arm by advancing the value of way_. Providing new values for the variable's lower and upper bounds for each branching direction gives a little bit of additional flexibility and will be easily extensible to multi-way branching. Returns change in guessed objective on next branch */ double CbcIntegerPseudoCostBranchingObject::branch() { CbcIntegerBranchingObject::branch(); return changeInGuessed_; } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcIntegerPseudoCostBranchingObject::compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap) { const CbcIntegerPseudoCostBranchingObject* br = dynamic_cast(brObj); assert(br); double* thisBd = way_ < 0 ? down_ : up_; const double* otherBd = br->way_ < 0 ? br->down_ : br->up_; return CbcCompareRanges(thisBd, otherBd, replaceIfOverlap); } Cbc-2.8.12/src/CbcNodeInfo.hpp0000644000076600007660000002364312131315050014361 0ustar coincoin// $Id: CbcNodeInfo.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/24/09 carved from CbcNode #ifndef CbcNodeInfo_H #define CbcNodeInfo_H #include #include #include "CoinWarmStartBasis.hpp" #include "CoinSearchTree.hpp" #include "CbcBranchBase.hpp" class OsiSolverInterface; class OsiSolverBranch; class OsiCuts; class OsiRowCut; class OsiRowCutDebugger; class CoinWarmStartBasis; class CbcCountRowCut; class CbcModel; class CbcNode; class CbcSubProblem; class CbcGeneralBranchingObject; //############################################################################# /** Information required to recreate the subproblem at this node When a subproblem is initially created, it is represented by a CbcNode object and an attached CbcNodeInfo object. The CbcNode contains information needed while the subproblem remains live. The CbcNode is deleted when the last branch arm has been evaluated. The CbcNodeInfo contains information required to maintain the branch-and-cut search tree structure (links and reference counts) and to recreate the subproblem for this node (basis, variable bounds, cutting planes). A CbcNodeInfo object remains in existence until all nodes have been pruned from the subtree rooted at this node. The principle used to maintain the reference count is that the reference count is always the sum of all potential and actual children of the node. Specifically,
  • Once it's determined how the node will branch, the reference count is set to the number of potential children (i.e., the number of arms of the branch).
  • As each child is created by CbcNode::branch() (converting a potential child to the active subproblem), the reference count is decremented.
  • If the child survives and will become a node in the search tree (converting the active subproblem into an actual child), increment the reference count.
Notice that the active subproblem lives in a sort of limbo, neither a potential or an actual node in the branch-and-cut tree. CbcNodeInfo objects come in two flavours. A CbcFullNodeInfo object contains a full record of the information required to recreate a subproblem. A CbcPartialNodeInfo object expresses this information in terms of differences from the parent. */ class CbcNodeInfo { public: /** \name Constructors & destructors */ //@{ /** Default Constructor Creates an empty NodeInfo object. */ CbcNodeInfo (); /// Copy constructor CbcNodeInfo ( const CbcNodeInfo &); #ifdef JJF_ZERO /** Construct with parent Creates a NodeInfo object which knows its parent and assumes it will in turn have two children. */ CbcNodeInfo (CbcNodeInfo * parent); #endif /** Construct with parent and owner As for `construct with parent', and attached to \p owner. */ CbcNodeInfo (CbcNodeInfo * parent, CbcNode * owner); /** Destructor Note that the destructor will recursively delete the parent if this nodeInfo is the last child. */ virtual ~CbcNodeInfo(); //@} /** \brief Modify model according to information at node The routine modifies the model according to bound and basis information at node and adds any cuts to the addCuts array. */ virtual void applyToModel (CbcModel *model, CoinWarmStartBasis *&basis, CbcCountRowCut **addCuts, int ¤tNumberCuts) const = 0 ; /// Just apply bounds to one variable - force means overwrite by lower,upper (1=>infeasible) virtual int applyBounds(int iColumn, double & lower, double & upper, int force) = 0; /** Builds up row basis backwards (until original model). Returns NULL or previous one to apply . Depends on Free being 0 and impossible for cuts */ virtual CbcNodeInfo * buildRowBasis(CoinWarmStartBasis & basis) const = 0; /// Clone virtual CbcNodeInfo * clone() const = 0; /// Called when number branches left down to zero virtual void allBranchesGone() {} #ifndef JJF_ONE /// Increment number of references inline void increment(int amount = 1) { numberPointingToThis_ += amount;/*printf("CbcNodeInfo %x incremented by %d to %d\n",this,amount,numberPointingToThis_);*/ } /// Decrement number of references and return number left inline int decrement(int amount = 1) { numberPointingToThis_ -= amount;/*printf("CbcNodeInfo %x decremented by %d to %d\n",this,amount,numberPointingToThis_);*/ return numberPointingToThis_; } #else /// Increment number of references void increment(int amount = 1); /// Decrement number of references and return number left int decrement(int amount = 1); #endif /** Initialize reference counts Initialize the reference counts used for tree maintenance. */ inline void initializeInfo(int number) { numberPointingToThis_ = number; numberBranchesLeft_ = number; } /// Return number of branches left in object inline int numberBranchesLeft() const { return numberBranchesLeft_; } /// Set number of branches left in object inline void setNumberBranchesLeft(int value) { numberBranchesLeft_ = value; } /// Return number of objects pointing to this inline int numberPointingToThis() const { return numberPointingToThis_; } /// Set number of objects pointing to this inline void setNumberPointingToThis(int number) { numberPointingToThis_ = number; } /// Increment number of objects pointing to this inline void incrementNumberPointingToThis() { numberPointingToThis_ ++; } /// Say one branch taken inline int branchedOn() { numberPointingToThis_--; numberBranchesLeft_--; return numberBranchesLeft_; } /// Say thrown away inline void throwAway() { numberPointingToThis_ -= numberBranchesLeft_; numberBranchesLeft_ = 0; } /// Parent of this CbcNodeInfo * parent() const { return parent_; } /// Set parent null inline void nullParent() { parent_ = NULL; } void addCuts(OsiCuts & cuts, int numberToBranch, //int * whichGenerator, int numberPointingToThis); void addCuts(int numberCuts, CbcCountRowCut ** cuts, int numberToBranch); /** Delete cuts (decrements counts) Slow unless cuts in same order as saved */ void deleteCuts(int numberToDelete, CbcCountRowCut ** cuts); void deleteCuts(int numberToDelete, int * which); /// Really delete a cut void deleteCut(int whichOne); /// Decrement active cut counts void decrementCuts(int change = 1); /// Increment active cut counts void incrementCuts(int change = 1); /// Decrement all active cut counts in chain starting at parent void decrementParentCuts(CbcModel * model, int change = 1); /// Increment all active cut counts in parent chain void incrementParentCuts(CbcModel * model, int change = 1); /// Array of pointers to cuts inline CbcCountRowCut ** cuts() const { return cuts_; } /// Number of row cuts (this node) inline int numberCuts() const { return numberCuts_; } inline void setNumberCuts(int value) { numberCuts_ = value; } /// Set owner null inline void nullOwner() { owner_ = NULL; } const inline CbcNode * owner() const { return owner_; } inline CbcNode * mutableOwner() const { return owner_; } /// The node number inline int nodeNumber() const { return nodeNumber_; } inline void setNodeNumber(int node) { nodeNumber_ = node; } /** Deactivate node information. 1 - bounds 2 - cuts 4 - basis! */ void deactivate(int mode = 3); /// Say if normal inline bool allActivated() const { return (active_ == 7); } /// Say if marked inline bool marked() const { return ((active_&8) != 0); } /// Mark inline void mark() { active_ |= 8; } /// Unmark inline void unmark() { active_ &= ~8; } /// Branching object for the parent inline const OsiBranchingObject * parentBranch() const { return parentBranch_; } /// If we need to take off parent based data void unsetParentBasedData(); protected: /** Number of other nodes pointing to this node. Number of existing and potential search tree nodes pointing to this node. `Existing' means referenced by #parent_ of some other CbcNodeInfo. `Potential' means children still to be created (#numberBranchesLeft_ of this CbcNodeInfo). */ int numberPointingToThis_; /// parent CbcNodeInfo * parent_; /// Copy of the branching object of the parent when the node is created OsiBranchingObject * parentBranch_; /// Owner CbcNode * owner_; /// Number of row cuts (this node) int numberCuts_; /// The node number int nodeNumber_; /// Array of pointers to cuts CbcCountRowCut ** cuts_; /** Number of rows in problem (before these cuts). This means that for top of chain it must be rows at continuous */ int numberRows_; /** Number of branch arms left to explore at this node \todo There seems to be redundancy between this field and CbcBranchingObject::numberBranchesLeft_. It'd be good to sort out if both are necessary. */ int numberBranchesLeft_; /** Active node information. 1 - bounds 2 - cuts 4 - basis! */ int active_; private: /// Illegal Assignment operator CbcNodeInfo & operator=(const CbcNodeInfo& rhs); /// routine common to constructors void setParentBasedData(); }; #endif // CbcNodeInfo_H Cbc-2.8.12/src/CbcGenSolution.cpp0000644000076600007660000004501112131315050015112 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenSolution.cpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #include #include #include #include "CoinHelperFunctions.hpp" #include "CoinSort.hpp" #include "CoinFileIO.hpp" #include "CbcGenCtlBlk.hpp" #include "CbcGenParam.hpp" namespace { char svnid[] = "$Id: CbcGenSolution.cpp 1902 2013-04-10 16:58:16Z stefan $" ; } namespace { /* Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise. This is John Forrest's code, shamelessly stolen from CoinSolve and tweaked just enough to allow it to be yanked out of the main body of CoinSolve. Returns the number of generated masks, -1 on error. */ int generateMasks (std::string proto, int longestName, int *&maskStarts, char **&finalMasks) { int nAst = 0 ; const char *pMask2 = proto.c_str() ; char pMask[100] ; int iChar ; int lengthMask = strlen(pMask2) ; assert (lengthMask < 100) ; int maxMasks = -1 ; maskStarts = 0 ; finalMasks = 0 ; /* Remove surrounding matched quotes if present. Abort if unmatched. */ if (*pMask2 == '"') { if (pMask2[lengthMask-1] != '"') { printf("generateMasks: Mismatched \" in mask %s\n", pMask2) ; return (-1) ; } else { strcpy(pMask, pMask2 + 1) ; *strchr(pMask, '"') = '\0' ; } } else if (*pMask2 == '\'') { if (pMask2[lengthMask-1] != '\'') { printf("mismatched ' in mask %s\n", pMask2) ; return (maxMasks) ; } else { strcpy(pMask, pMask2 + 1) ; *strchr(pMask, '\'') = '\0' ; } } else { strcpy(pMask, pMask2) ; } /* Mask should not be longer than longest name. */ if (lengthMask > longestName) { printf("mask %s too long - skipping\n", pMask) ; return (maxMasks) ; } /* Expand `*' to multiple masks with varying number of `?' characters. */ maxMasks = 1 ; for (iChar = 0; iChar < lengthMask; iChar++) { if (pMask[iChar] == '*') { nAst++ ; maxMasks *= (longestName + 1) ; } } int nEntries = 1 ; maskStarts = new int[longestName+2] ; char ** masks = new char * [maxMasks] ; char ** newMasks = new char * [maxMasks] ; int i ; for (i = 0; i < maxMasks; i++) { masks[i] = new char[longestName+1] ; newMasks[i] = new char[longestName+1] ; } strcpy(masks[0], pMask) ; for (int iAst = 0; iAst < nAst; iAst++) { int nOldEntries = nEntries ; nEntries = 0 ; for (int iEntry = 0; iEntry < nOldEntries; iEntry++) { char * oldMask = masks[iEntry] ; char * ast = strchr(oldMask, '*') ; assert (ast) ; int length = strlen(oldMask) - 1 ; int nBefore = ast - oldMask ; int nAfter = length - nBefore ; // and add null nAfter++ ; for (int i = 0; i <= longestName - length; i++) { char * maskOut = newMasks[nEntries] ; memcpy(maskOut, oldMask, nBefore) ; for (int k = 0; k < i; k++) maskOut[k+nBefore] = '?' ; memcpy(maskOut + nBefore + i, ast + 1, nAfter) ; nEntries++ ; assert (nEntries <= maxMasks) ; } } char ** temp = masks ; masks = newMasks ; newMasks = temp ; } /* Trim trailing blanks and record final length. */ int * sort = new int[nEntries] ; for (i = 0; i < nEntries; i++) { char * maskThis = masks[i] ; int length = strlen(maskThis) ; while (maskThis[length-1] == ' ') length-- ; maskThis[length] = '\0' ; sort[i] = length ; } /* Sort by length. */ CoinSort_2(sort, sort + nEntries, masks) ; int lastLength = -1 ; for (i = 0; i < nEntries; i++) { int length = sort[i] ; while (length > lastLength) maskStarts[++lastLength] = i ; } maskStarts[++lastLength] = nEntries ; delete [] sort ; for (i = 0; i < maxMasks; i++) delete [] newMasks[i] ; delete [] newMasks ; finalMasks = masks ; return (maxMasks) ; } /* Utility routine to check a string against the array of masks. Borrowed from CoinSolve. */ bool maskMatches (const int *starts, char **masks, const char *checkC) { int length = strlen(checkC); while (checkC[length-1] == ' ') length--; for (int i = starts[length]; i < starts[length+1]; i++) { char * thisMask = masks[i]; int k; for ( k = 0; k < length; k++) { if (thisMask[k] != '?' && thisMask[k] != checkC[k]) break; } if (k == length) return true; } return (false) ; } } // end unnamed namespace /* Routine to write out the solution. Minimally adapted from John's code in CoinSolve to break out a few subroutines and use generic OSI functions. The print mode is established by the printingOptions command, and the integer coding is established by the order of declaration of the keyword parameters. As of 060920, known modes are normal (0) print nonzero primal variables integer (1) print nonzero integer primal variables special (2) print in a format suitable for OsiRowCutDebugger rows (3) `normal', plus rows with nonzero row activity all (4) all primal variables and row activities */ int CbcGenParamUtils::doSolutionParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; CbcModel *model = ctlBlk->model_ ; assert (model != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* It's hard to print a solution we don't have. */ if (ctlBlk->bab_.haveAnswer_ == false) { std::cout << "There is no solution available to print." << std::endl ; return (retval) ; } OsiSolverInterface *osi = ctlBlk->bab_.answerSolver_ ; assert (osi != 0) ; /* Figure out where we're going to write the solution. As special cases, `$' says `use the previous output file' and `-' says `use stdout'. cbc will also accept `no string value' as stdout, but that'd be a real pain in this architecture. */ std::string field = genParam->strVal() ; std::string fileName ; if (field == "$") { fileName = ctlBlk->lastSolnOut_ ; field = fileName ; } if (field == "-") { fileName = "stdout" ; field = fileName ; } else { fileName = field ; } if (!(fileName == "stdout" || fileName == "stderr")) { if (fileName[0] == '~') { char dirSep = CoinFindDirSeparator() ; if (fileName[1] == dirSep) { char *environVar = getenv("HOME") ; if (environVar) { std::string home(environVar) ; fileName = home + fileName.substr(1) ; } } } if (!(fileAbsPath(fileName) || fileName.substr(0, 2) == "./")) { fileName = ctlBlk->dfltDirectory_ + fileName ; } } /* See if we can open the file. Bail out if the open fails. */ FILE *fp ; if (fileName == "stdout") { fp = stdout ; } else if (fileName == "stderr") { fp = stderr ; } else { fp = fopen(fileName.c_str(), "w") ; fp = fopen(fileName.c_str(), "w") ; } if (!fp) { std::cout << "Unable to open file `" << fileName << "', original name '" << genParam->strVal() << "'." << std::endl ; return (retval) ; } else { std::cout << "Writing solution to `" << fileName << "'." << std::endl ; } int m = osi->getNumRows() ; int n = osi->getNumCols() ; int iColumn ; const double *primalColSolution = osi->getColSolution() ; /* Separate printing a solution for humans from printing a solution for the row cut debugger. For the row cut debugger, we want to produce C++ code that can be pasted into the debugger's set of known problems. */ if (ctlBlk->printMode_ == 2) { int k = 0 ; bool newLine = true ; bool comma = false ; fprintf(fp, " int intIndicesV[] = {") ; for (iColumn = 0 ; iColumn < n ; iColumn++ ) { if (fabs(primalColSolution[iColumn]) > 0.5 && osi->isInteger(iColumn)) { if (newLine) { fprintf(fp, "\n\t") ; newLine = false ; } else { fprintf(fp, ", ") ; } fprintf(fp, "%d", iColumn) ; if (++k == 10) { k = 0 ; newLine = true ; } } } fprintf(fp, "\n } ;\n") ; k = 0 ; newLine = true ; fprintf(fp, " double intSolnV[] = {") ; for (iColumn = 0 ; iColumn < n ; iColumn++) { double value = primalColSolution[iColumn] ; if (fabs(value) > 0.5 && osi->isInteger(iColumn)) { if (newLine) { fprintf(fp, "\n\t") ; newLine = false ; } else { fprintf(fp, ", ") ; } if (value > 0) { value = floor(value + .5) ; } else { value = ceil(value - .5) ; } int ivalue = static_cast(value) ; fprintf(fp, "%d.0", ivalue) ; if (++k == 10) { k = 0 ; newLine = true ; } } } fprintf(fp, "\n } ;\n") ; return (0) ; } /* Begin the code to generate output meant for a human. What's our longest name? Scan the names we're going to print. printMode_ of 3 or 4 requires we scan the row names too. Force between 8 and 20 characters in any event. */ int longestName = 0 ; for (int j = 0 ; j < n ; j++) { int len = osi->getColName(j).length() ; longestName = CoinMax(longestName, len) ; } if (ctlBlk->printMode_ >= 3) { for (int i = 0 ; i < m ; i++) { int len = osi->getRowName(i).length() ; longestName = CoinMax(longestName, len) ; } } /* Generate masks if we need to do so. */ bool doMask = ctlBlk->printMask_ != "" ; int *maskStarts = NULL ; int maxMasks = 0 ; char **masks = NULL ; if (doMask) { maxMasks = generateMasks(ctlBlk->printMask_, longestName, maskStarts, masks) ; if (maxMasks < 0) { return (retval) ; } } /* Force the space allocated to names to be between 8 and 20 characters. */ if (longestName < 8) { longestName = 8 ; } else if (longestName > 20) { longestName = 20 ; } /* Print requested components of the row solution. Only modes 3 (rows) and 4 (all) will print row information. For the rows that we print, print both the row activity and the value of the associated dual. Which to print? Violated constraints will always be flagged to print. Otherwise, if m < 50 or all rows are requested, print all rows. Otherwise, print tight constraints (non-zero dual). All of this is filtered through printMask, if specified. */ double primalTolerance ; osi->getDblParam(OsiPrimalTolerance, primalTolerance) ; int iRow ; if (ctlBlk->printMode_ >= 3) { const double *dualRowSolution = osi->getRowPrice() ; const double *primalRowSolution = osi->getRowActivity() ; const double *rowLower = osi->getRowLower() ; const double *rowUpper = osi->getRowUpper() ; fprintf(fp, "\n %7s %-*s%15s%15s\n\n", "Index", longestName, "Row", "Activity", "Dual") ; for (iRow = 0 ; iRow < m ; iRow++) { bool violated = false ; bool print = false ; if (primalRowSolution[iRow] > rowUpper[iRow] + primalTolerance || primalRowSolution[iRow] < rowLower[iRow] - primalTolerance) { violated = true ; print = true ; } else { if (m < 50 || ctlBlk->printMode_ >= 4) { print = true ; } else if (fabs(dualRowSolution[iRow]) > 1.0e-8) { print = true ; } } const char *name = osi->getRowName(iRow).c_str() ; if (doMask && !maskMatches(maskStarts, masks, name)) { print = false ; } if (print) { if (violated) { fprintf(fp, "** ") ; } else { fprintf(fp, "%3s", " ") ; } fprintf(fp, "%7d %-*s%15.8g%15.8g\n", iRow, longestName, name, primalRowSolution[iRow], dualRowSolution[iRow]) ; } } fprintf(fp, "\n") ; } /* Now do the columns. This first block handles all modes except 2 (special). Out-of-bounds variables are flagged with `**'. If there are less than 50 variables, all are printed. All of this is filtered through `integer only' and can be further filtered using printMask. */ if (ctlBlk->printMode_ != 2) { const double *columnLower = osi->getColLower() ; const double *columnUpper = osi->getColUpper() ; const double *dualColSolution = osi->getReducedCost() ; fprintf(fp, "\n %7s %-*s%15s%15s\n\n", "Index", longestName, "Column", "Value", "Reduced Cost") ; for (iColumn = 0 ; iColumn < n ; iColumn++) { bool violated = false ; bool print = false ; if (primalColSolution[iColumn] > columnUpper[iColumn] + primalTolerance || primalColSolution[iColumn] < columnLower[iColumn] - primalTolerance) { violated = true ; print = true ; } else { if (n < 50 || ctlBlk->printMode_ == 4) { print = true ; } else if (fabs(primalColSolution[iColumn]) > 1.0e-8) { if (ctlBlk->printMode_ == 1) { print = osi->isInteger(iColumn) ; } else { print = true ; } } } const char *name = osi->getColName(iColumn).c_str() ; if (doMask && !maskMatches(maskStarts, masks, name)) { print = false ; } if (print) { if (violated) { fprintf(fp, "** ") ; } else { fprintf(fp, "%3s", " ") ; } fprintf(fp, "%7d %-*s%15.8g%15.8g\n", iColumn, longestName, name, primalColSolution[iColumn], dualColSolution[iColumn]) ; } } } /* Close out the file, but don't close stdout. Delete any masks. */ if (fp != stdout) { fclose(fp) ; } if (masks) { delete [] maskStarts ; for (int i = 0 ; i < maxMasks ; i++) delete [] masks[i] ; delete [] masks ; } return (0) ; } /* Routine to do initial verification of a print mask. We don't generate the full set of print masks here, but we do some verification checks to make sure it's valid. */ int CbcGenParamUtils::doPrintMaskParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* Now do a bit of verification of the mask. It should be non-null and, if quoted, the quotes should be matched. Aribtrarily put the absolute maximum length at 50 characters. If we have a model loaded, that'll be tightened to the length of the longest name. */ std::string maskProto = param->strVal() ; int maskLen = maskProto.length() ; if (maskLen <= 0 || maskLen > 50) { std::cerr << "Mask |" << maskProto << "| is " << maskLen << " characters; should be between " << 0 << " and " << 50 << "." << std::endl ; return (retval) ; } /* Remove surrounding matched quotes if present. Abort if unmatched. */ if (maskProto[0] == '"' || maskProto[0] == '\'') { char quoteChar = maskProto[0] ; if (maskProto[maskLen-1] != quoteChar) { std::cerr << "Mismatched quotes around mask |" << maskProto << "|." << std::endl ; return (retval) ; } else { maskProto = maskProto.substr(1, maskLen - 2) ; } } /* Mask should not be longer than longest name. Of course, if we don't have a model, we can't do this check. */ if (ctlBlk->goodModel_) { CbcModel *model = ctlBlk->model_ ; assert (model != 0) ; OsiSolverInterface *osi = model->solver() ; assert (osi != 0) ; int longestName = 0 ; int n = osi->getNumCols() ; for (int j = 0 ; j < n ; j++) { int len = osi->getColName(j).length() ; longestName = CoinMax(longestName, len) ; } int m = osi->getNumRows() ; for (int i = 0 ; i < m ; i++) { int len = osi->getRowName(i).length() ; longestName = CoinMax(longestName, len) ; } if (maskLen > longestName) { std::cerr << "Mask |" << maskProto << "| has " << maskLen << " chars; this" << " is longer than the longest name (" << longestName << " chars)." << std::endl ; return (retval) ; } } ctlBlk->printMask_ = maskProto ; return (0) ; } Cbc-2.8.12/src/CbcHeuristicVND.hpp0000644000076600007660000000456412131315050015170 0ustar coincoin// $Id: CbcHeuristicVND.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2006, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // edwin 12/5/09 carved out of CbcHeuristicRINS #ifndef CbcHeuristicVND_H #define CbcHeuristicVND_H #include "CbcHeuristic.hpp" /** LocalSearch class */ class CbcHeuristicVND : public CbcHeuristic { public: // Default Constructor CbcHeuristicVND (); /* Constructor with model - assumed before cuts Initial version does not do Lps */ CbcHeuristicVND (CbcModel & model); // Copy constructor CbcHeuristicVND ( const CbcHeuristicVND &); // Destructor ~CbcHeuristicVND (); /// Clone virtual CbcHeuristic * clone() const; /// Assignment operator CbcHeuristicVND & operator=(const CbcHeuristicVND& rhs); /// Create C++ lines to get to current state virtual void generateCpp( FILE * fp) ; /// Resets stuff if model changes virtual void resetModel(CbcModel * model); /// update model (This is needed if cliques update matrix etc) virtual void setModel(CbcModel * model); using CbcHeuristic::solution ; /** returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) This does Relaxation Induced Neighborhood Search */ virtual int solution(double & objectiveValue, double * newSolution); /// This version fixes stuff and does IP int solutionFix(double & objectiveValue, double * newSolution, const int * keep); /// Sets how often to do it inline void setHowOften(int value) { howOften_ = value; } /// base solution array so we can set inline double * baseSolution() const { return baseSolution_; } protected: // Data /// Number of solutions so we can do something at solution int numberSolutions_; /// How often to do (code can change) int howOften_; /// Number of successes int numberSuccesses_; /// Number of tries int numberTries_; /// Node when last done int lastNode_; /// Step size for decomposition int stepSize_; int k_; int kmax_; int nDifferent_; /// Base solution double * baseSolution_; }; #endif Cbc-2.8.12/src/config.h.in0000644000076600007660000001036112131315050013553 0ustar coincoin/* src/config.h.in. Generated from configure.ac by autoheader. */ /* Define to the name of the default solver to be used in cbc-generic in small letters */ #undef CBC_DEFAULT_SOLVER /* SVN revision number of project */ #undef CBC_SVN_REV /* Define to 1 if the SMP version of Cbc should be compiled */ #undef CBC_THREAD /* Version number of project */ #undef CBC_VERSION /* Major Version number of project */ #undef CBC_VERSION_MAJOR /* Minor Version number of project */ #undef CBC_VERSION_MINOR /* Release Version number of project */ #undef CBC_VERSION_RELEASE /* Define to the debug sanity check level (0 is no test) */ #undef COIN_CBC_CHECKLEVEL /* Define to the debug verbosity level (0 is no output) */ #undef COIN_CBC_VERBOSITY /* Define to 1 if the ASL package is available */ #undef COIN_HAS_ASL /* Define to 1 if the Clp package is available */ #undef COIN_HAS_CLP /* Define to 1 if the CoinDepend package is available */ #undef COIN_HAS_COINDEPEND /* Define to 1 if the Cpx package is available */ #undef COIN_HAS_CPX /* Define to 1 if the DyLP package is available */ #undef COIN_HAS_DYLP /* Define to 1 if the Glpk package is available */ #undef COIN_HAS_GLPK /* Define to 1 if the Grb package is available */ #undef COIN_HAS_GRB /* Define to 1 if the Miplib3 package is available */ #undef COIN_HAS_MIPLIB3 /* Define to 1 if the Msk package is available */ #undef COIN_HAS_MSK /* Define to 1 if the Netlib package is available */ #undef COIN_HAS_NETLIB /* Define to 1 if the OsiTests package is available */ #undef COIN_HAS_OSITESTS /* Define to 1 if readline is available */ #undef COIN_HAS_READLINE /* Define to 1 if the Sample package is available */ #undef COIN_HAS_SAMPLE /* Define to 1 if the Spx package is available */ #undef COIN_HAS_SPX /* Define to 1 if the Vol package is available */ #undef COIN_HAS_VOL /* Define to 1 if the Xpr package is available */ #undef COIN_HAS_XPR /* Define to 1 if you have the header file. */ #undef HAVE_CFLOAT /* Define to 1 if you have the header file. */ #undef HAVE_CIEEEFP /* Define if clock_gettime and rt library is available */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have the header file. */ #undef HAVE_CMATH /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_FLOAT_H /* Define to 1 if you have the header file. */ #undef HAVE_IEEEFP_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_MATH_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_READLINE_READLINE_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* define to the name of the default solver interface class, e.g., OsiClpSolverInterface */ #undef OSICBC_DFLT_SOLVER /* define this symbol if clp is the default solver */ #undef OSICBC_DFLT_SOLVER_CLP /* define to the name of the .hpp file for the default solver interface class, e.g., "OsiClpSolverInterface.hpp" (include quotes) */ #undef OSICBC_DFLT_SOLVER_HPP /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION Cbc-2.8.12/src/CbcClique.cpp0000644000076600007660000006711412131315050014076 0ustar coincoin// $Id: CbcClique.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/9/2009-- carved out of CbcBranchActual #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include #include #include //#define CBC_DEBUG #include "CoinTypes.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcClique.hpp" #include "CbcBranchActual.hpp" #include "CoinSort.hpp" #include "CoinError.hpp" //############################################################################## // Default Constructor CbcClique::CbcClique () : CbcObject(), numberMembers_(0), numberNonSOSMembers_(0), members_(NULL), type_(NULL), cliqueType_(-1), slack_(-1) { } // Useful constructor (which are integer indices) CbcClique::CbcClique (CbcModel * model, int cliqueType, int numberMembers, const int * which, const char * type, int identifier, int slack) : CbcObject(model) { id_ = identifier; numberMembers_ = numberMembers; if (numberMembers_) { members_ = new int[numberMembers_]; memcpy(members_, which, numberMembers_*sizeof(int)); type_ = new char[numberMembers_]; if (type) { memcpy(type_, type, numberMembers_*sizeof(char)); } else { for (int i = 0; i < numberMembers_; i++) type_[i] = 1; } } else { members_ = NULL; type_ = NULL; } // Find out how many non sos int i; numberNonSOSMembers_ = 0; for (i = 0; i < numberMembers_; i++) if (!type_[i]) numberNonSOSMembers_++; cliqueType_ = cliqueType; slack_ = slack; } // Copy constructor CbcClique::CbcClique ( const CbcClique & rhs) : CbcObject(rhs) { numberMembers_ = rhs.numberMembers_; numberNonSOSMembers_ = rhs.numberNonSOSMembers_; if (numberMembers_) { members_ = new int[numberMembers_]; memcpy(members_, rhs.members_, numberMembers_*sizeof(int)); type_ = new char[numberMembers_]; memcpy(type_, rhs.type_, numberMembers_*sizeof(char)); } else { members_ = NULL; type_ = NULL; } cliqueType_ = rhs.cliqueType_; slack_ = rhs.slack_; } // Clone CbcObject * CbcClique::clone() const { return new CbcClique(*this); } // Assignment operator CbcClique & CbcClique::operator=( const CbcClique & rhs) { if (this != &rhs) { CbcObject::operator=(rhs); delete [] members_; delete [] type_; numberMembers_ = rhs.numberMembers_; numberNonSOSMembers_ = rhs.numberNonSOSMembers_; if (numberMembers_) { members_ = new int[numberMembers_]; memcpy(members_, rhs.members_, numberMembers_*sizeof(int)); type_ = new char[numberMembers_]; memcpy(type_, rhs.type_, numberMembers_*sizeof(char)); } else { members_ = NULL; type_ = NULL; } cliqueType_ = rhs.cliqueType_; slack_ = rhs.slack_; } return *this; } // Destructor CbcClique::~CbcClique () { delete [] members_; delete [] type_; } /* Unfortunately, that comment is untrue. And there are other issues. This routine is clearly an unfinished work. */ double CbcClique::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { int numberUnsatis = 0, numberFree = 0; int j; const int * integer = model_->integerVariable(); OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double largestValue = 0.0; double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double * sort = new double[numberMembers_]; /* Calculate integer infeasibility and fill an array. Pick off the infeasibility of the slack and the max infeasibility while we're at it. You can see here the conversion of `non-SOS' (strong value of 0, negative coefficient) to `SOS' (strong value of 1, positive coefficient). Also count the number of variables that have integral values but are not fixed. */ double slackValue = 0.0; for (j = 0; j < numberMembers_; j++) { int sequence = members_[j]; int iColumn = integer[sequence]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); double nearest = floor(value + 0.5); double distance = fabs(value - nearest); if (distance > integerTolerance) { if (!type_[j]) value = 1.0 - value; // non SOS // if slack then choose that if (j == slack_ && value > 0.05) slackValue = value; largestValue = CoinMax(value, largestValue); sort[numberUnsatis++] = -value; } else if (upper[iColumn] > lower[iColumn]) { numberFree++; } } /* preferredWay will not change. The calculation of otherWay is an expensive noop --- value is ultimately unused. Same for the sort of sort. It looks like there was some notion of branching by splitting the set using even and odd indices (as opposed to first and second half). */ preferredWay = 1; double otherWay = 0.0; if (numberUnsatis) { // sort std::sort(sort, sort + numberUnsatis); for (j = 0; j < numberUnsatis; j++) { if ((j&1) != 0) otherWay += -sort[j]; } // Need to think more /* Here we have the actual infeasibility calculation. Most previous work is discarded, and we calculate a value using various counts, adjusted by the max value and slack value. This is not scaled to [0, .5]. */ double value = 0.2 * numberUnsatis + 0.01 * (numberMembers_ - numberFree); if (fabs(largestValue - 0.5) < 0.1) { // close to half value += 0.1; } if (slackValue) { // branching on slack value += slackValue; } // scale other way otherWay *= value / (1.0 - otherWay); delete [] sort; return value; } else { delete [] sort; return 0.0; // satisfied } } // This looks at solution and sets bounds to contain solution void CbcClique::feasibleRegion() { int j; const int * integer = model_->integerVariable(); OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); #ifndef NDEBUG double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); #endif for (j = 0; j < numberMembers_; j++) { int sequence = members_[j]; int iColumn = integer[sequence]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); double nearest = floor(value + 0.5); #ifndef NDEBUG double distance = fabs(value - nearest); assert(distance <= integerTolerance); #endif solver->setColLower(iColumn, nearest); solver->setColUpper(iColumn, nearest); } } // Redoes data when sequence numbers change void CbcClique::redoSequenceEtc(CbcModel * model, int numberColumns, const int * originalColumns) { model_ = model; int n2 = 0; for (int j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; int i; for (i = 0; i < numberColumns; i++) { if (originalColumns[i] == iColumn) break; } if (i < numberColumns) { members_[n2] = i; type_[n2++] = type_[j]; } } if (n2 < numberMembers_) { //printf("** SOS number of members reduced from %d to %d!\n",numberMembers_,n2); numberMembers_ = n2; } // Find out how many non sos int i; numberNonSOSMembers_ = 0; for (i = 0; i < numberMembers_; i++) if (!type_[i]) numberNonSOSMembers_++; } CbcBranchingObject * CbcClique::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int way) { int numberUnsatis = 0; int j; int nUp = 0; int nDown = 0; int numberFree = numberMembers_; const int * integer = model_->integerVariable(); //OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); int * upList = new int[numberMembers_]; int * downList = new int[numberMembers_]; double * sort = new double[numberMembers_]; double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double slackValue = 0.0; for (j = 0; j < numberMembers_; j++) { int sequence = members_[j]; int iColumn = integer[sequence]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); double nearest = floor(value + 0.5); double distance = fabs(value - nearest); if (distance > integerTolerance) { if (!type_[j]) value = 1.0 - value; // non SOS // if slack then choose that if (j == slack_ && value > 0.05) slackValue = value; value = -value; // for sort upList[numberUnsatis] = j; sort[numberUnsatis++] = value; } else if (upper[iColumn] > lower[iColumn]) { upList[--numberFree] = j; } } assert (numberUnsatis); if (!slackValue) { // sort CoinSort_2(sort, sort + numberUnsatis, upList); // put first in up etc int kWay = 1; for (j = 0; j < numberUnsatis; j++) { if (kWay > 0) upList[nUp++] = upList[j]; else downList[nDown++] = upList[j]; kWay = -kWay; } for (j = numberFree; j < numberMembers_; j++) { if (kWay > 0) upList[nUp++] = upList[j]; else downList[nDown++] = upList[j]; kWay = -kWay; } } else { // put slack to 0 in first way nUp = 1; upList[0] = slack_; for (j = 0; j < numberUnsatis; j++) { downList[nDown++] = upList[j]; } for (j = numberFree; j < numberMembers_; j++) { downList[nDown++] = upList[j]; } } // create object CbcBranchingObject * branch; if (numberMembers_ <= 64) branch = new CbcCliqueBranchingObject(model_, this, way, nDown, downList, nUp, upList); else branch = new CbcLongCliqueBranchingObject(model_, this, way, nDown, downList, nUp, upList); delete [] upList; delete [] downList; delete [] sort; return branch; } // Default Constructor CbcCliqueBranchingObject::CbcCliqueBranchingObject() : CbcBranchingObject() { clique_ = NULL; downMask_[0] = 0; downMask_[1] = 0; upMask_[0] = 0; upMask_[1] = 0; } // Useful constructor CbcCliqueBranchingObject::CbcCliqueBranchingObject (CbcModel * model, const CbcClique * clique, int way , int numberOnDownSide, const int * down, int numberOnUpSide, const int * up) : CbcBranchingObject(model, clique->id(), way, 0.5) { clique_ = clique; downMask_[0] = 0; downMask_[1] = 0; upMask_[0] = 0; upMask_[1] = 0; int i; for (i = 0; i < numberOnDownSide; i++) { int sequence = down[i]; int iWord = sequence >> 5; int iBit = sequence - 32 * iWord; unsigned int k = 1 << iBit; downMask_[iWord] |= k; } for (i = 0; i < numberOnUpSide; i++) { int sequence = up[i]; int iWord = sequence >> 5; int iBit = sequence - 32 * iWord; unsigned int k = 1 << iBit; upMask_[iWord] |= k; } } // Copy constructor CbcCliqueBranchingObject::CbcCliqueBranchingObject ( const CbcCliqueBranchingObject & rhs) : CbcBranchingObject(rhs) { clique_ = rhs.clique_; downMask_[0] = rhs.downMask_[0]; downMask_[1] = rhs.downMask_[1]; upMask_[0] = rhs.upMask_[0]; upMask_[1] = rhs.upMask_[1]; } // Assignment operator CbcCliqueBranchingObject & CbcCliqueBranchingObject::operator=( const CbcCliqueBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); clique_ = rhs.clique_; downMask_[0] = rhs.downMask_[0]; downMask_[1] = rhs.downMask_[1]; upMask_[0] = rhs.upMask_[0]; upMask_[1] = rhs.upMask_[1]; } return *this; } CbcBranchingObject * CbcCliqueBranchingObject::clone() const { return (new CbcCliqueBranchingObject(*this)); } // Destructor CbcCliqueBranchingObject::~CbcCliqueBranchingObject () { } double CbcCliqueBranchingObject::branch() { decrementNumberBranchesLeft(); int iWord; int numberMembers = clique_->numberMembers(); const int * which = clique_->members(); const int * integerVariables = model_->integerVariable(); int numberWords = (numberMembers + 31) >> 5; // *** for way - up means fix all those in down section if (way_ < 0) { #ifdef FULL_PRINT printf("Down Fix "); #endif for (iWord = 0; iWord < numberWords; iWord++) { int i; for (i = 0; i < 32; i++) { unsigned int k = 1 << i; if ((upMask_[iWord]&k) != 0) { int iColumn = which[i+32*iWord]; #ifdef FULL_PRINT printf("%d ", i + 32*iWord); #endif // fix weak way if (clique_->type(i + 32*iWord)) model_->solver()->setColUpper(integerVariables[iColumn], 0.0); else model_->solver()->setColLower(integerVariables[iColumn], 1.0); } } } way_ = 1; // Swap direction } else { #ifdef FULL_PRINT printf("Up Fix "); #endif for (iWord = 0; iWord < numberWords; iWord++) { int i; for (i = 0; i < 32; i++) { unsigned int k = 1 << i; if ((downMask_[iWord]&k) != 0) { int iColumn = which[i+32*iWord]; #ifdef FULL_PRINT printf("%d ", i + 32*iWord); #endif // fix weak way if (clique_->type(i + 32*iWord)) model_->solver()->setColUpper(integerVariables[iColumn], 0.0); else model_->solver()->setColLower(integerVariables[iColumn], 1.0); } } } way_ = -1; // Swap direction } #ifdef FULL_PRINT printf("\n"); #endif return 0.0; } // Print what would happen void CbcCliqueBranchingObject::print() { int iWord; int numberMembers = clique_->numberMembers(); const int * which = clique_->members(); const int * integerVariables = model_->integerVariable(); int numberWords = (numberMembers + 31) >> 5; // *** for way - up means fix all those in down section if (way_ < 0) { printf("Clique - Down Fix "); for (iWord = 0; iWord < numberWords; iWord++) { int i; for (i = 0; i < 32; i++) { unsigned int k = 1 << i; if ((upMask_[iWord]&k) != 0) { int iColumn = which[i+32*iWord]; printf("%d ", integerVariables[iColumn]); } } } } else { printf("Clique - Up Fix "); for (iWord = 0; iWord < numberWords; iWord++) { int i; for (i = 0; i < 32; i++) { unsigned int k = 1 << i; if ((downMask_[iWord]&k) != 0) { int iColumn = which[i+32*iWord]; printf("%d ", integerVariables[iColumn]); } } } } printf("\n"); } static inline int CbcCompareCliques(const CbcClique* cl0, const CbcClique* cl1) { if (cl0->cliqueType() < cl1->cliqueType()) { return -1; } if (cl0->cliqueType() > cl1->cliqueType()) { return 1; } if (cl0->numberMembers() != cl1->numberMembers()) { return cl0->numberMembers() - cl1->numberMembers(); } if (cl0->numberNonSOSMembers() != cl1->numberNonSOSMembers()) { return cl0->numberNonSOSMembers() - cl1->numberNonSOSMembers(); } return memcmp(cl0->members(), cl1->members(), cl0->numberMembers() * sizeof(int)); } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcCliqueBranchingObject::compareOriginalObject (const CbcBranchingObject* brObj) const { const CbcCliqueBranchingObject* br = dynamic_cast(brObj); assert(br); return CbcCompareCliques(clique_, br->clique_); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcCliqueBranchingObject::compareBranchingObject (const CbcBranchingObject* brObj, const bool /*replaceIfOverlap*/) { const CbcCliqueBranchingObject* br = dynamic_cast(brObj); assert(br); unsigned int* thisMask = way_ < 0 ? upMask_ : downMask_; const unsigned int* otherMask = br->way_ < 0 ? br->upMask_ : br->downMask_; const CoinUInt64 cl0 = (static_cast(thisMask[0]) << 32) | thisMask[1]; const CoinUInt64 cl1 = (static_cast(otherMask[0]) << 32) | otherMask[1]; if (cl0 == cl1) { return CbcRangeSame; } const CoinUInt64 cl_intersection = (cl0 & cl1); if (cl_intersection == cl0) { return CbcRangeSuperset; } if (cl_intersection == cl1) { return CbcRangeSubset; } const CoinUInt64 cl_xor = (cl0 ^ cl1); if (cl_intersection == 0 && cl_xor == 0) { return CbcRangeDisjoint; } const CoinUInt64 cl_union = (cl0 | cl1); thisMask[0] = static_cast(cl_union >> 32); thisMask[1] = static_cast(cl_union & 0xffffffff); return CbcRangeOverlap; } //############################################################################## // Default Constructor CbcLongCliqueBranchingObject::CbcLongCliqueBranchingObject() : CbcBranchingObject() { clique_ = NULL; downMask_ = NULL; upMask_ = NULL; } // Useful constructor CbcLongCliqueBranchingObject::CbcLongCliqueBranchingObject (CbcModel * model, const CbcClique * clique, int way , int numberOnDownSide, const int * down, int numberOnUpSide, const int * up) : CbcBranchingObject(model, clique->id(), way, 0.5) { clique_ = clique; int numberMembers = clique_->numberMembers(); int numberWords = (numberMembers + 31) >> 5; downMask_ = new unsigned int [numberWords]; upMask_ = new unsigned int [numberWords]; memset(downMask_, 0, numberWords*sizeof(unsigned int)); memset(upMask_, 0, numberWords*sizeof(unsigned int)); int i; for (i = 0; i < numberOnDownSide; i++) { int sequence = down[i]; int iWord = sequence >> 5; int iBit = sequence - 32 * iWord; unsigned int k = 1 << iBit; downMask_[iWord] |= k; } for (i = 0; i < numberOnUpSide; i++) { int sequence = up[i]; int iWord = sequence >> 5; int iBit = sequence - 32 * iWord; unsigned int k = 1 << iBit; upMask_[iWord] |= k; } } // Copy constructor CbcLongCliqueBranchingObject::CbcLongCliqueBranchingObject ( const CbcLongCliqueBranchingObject & rhs) : CbcBranchingObject(rhs) { clique_ = rhs.clique_; if (rhs.downMask_) { int numberMembers = clique_->numberMembers(); int numberWords = (numberMembers + 31) >> 5; downMask_ = new unsigned int [numberWords]; memcpy(downMask_, rhs.downMask_, numberWords*sizeof(unsigned int)); upMask_ = new unsigned int [numberWords]; memcpy(upMask_, rhs.upMask_, numberWords*sizeof(unsigned int)); } else { downMask_ = NULL; upMask_ = NULL; } } // Assignment operator CbcLongCliqueBranchingObject & CbcLongCliqueBranchingObject::operator=( const CbcLongCliqueBranchingObject & rhs) { if (this != &rhs) { CbcBranchingObject::operator=(rhs); clique_ = rhs.clique_; delete [] downMask_; delete [] upMask_; if (rhs.downMask_) { int numberMembers = clique_->numberMembers(); int numberWords = (numberMembers + 31) >> 5; downMask_ = new unsigned int [numberWords]; memcpy(downMask_, rhs.downMask_, numberWords*sizeof(unsigned int)); upMask_ = new unsigned int [numberWords]; memcpy(upMask_, rhs.upMask_, numberWords*sizeof(unsigned int)); } else { downMask_ = NULL; upMask_ = NULL; } } return *this; } CbcBranchingObject * CbcLongCliqueBranchingObject::clone() const { return (new CbcLongCliqueBranchingObject(*this)); } // Destructor CbcLongCliqueBranchingObject::~CbcLongCliqueBranchingObject () { delete [] downMask_; delete [] upMask_; } double CbcLongCliqueBranchingObject::branch() { decrementNumberBranchesLeft(); int iWord; int numberMembers = clique_->numberMembers(); const int * which = clique_->members(); const int * integerVariables = model_->integerVariable(); int numberWords = (numberMembers + 31) >> 5; // *** for way - up means fix all those in down section if (way_ < 0) { #ifdef FULL_PRINT printf("Down Fix "); #endif for (iWord = 0; iWord < numberWords; iWord++) { int i; for (i = 0; i < 32; i++) { unsigned int k = 1 << i; if ((upMask_[iWord]&k) != 0) { int iColumn = which[i+32*iWord]; #ifdef FULL_PRINT printf("%d ", i + 32*iWord); #endif // fix weak way if (clique_->type(i + 32*iWord)) model_->solver()->setColUpper(integerVariables[iColumn], 0.0); else model_->solver()->setColLower(integerVariables[iColumn], 1.0); } } } way_ = 1; // Swap direction } else { #ifdef FULL_PRINT printf("Up Fix "); #endif for (iWord = 0; iWord < numberWords; iWord++) { int i; for (i = 0; i < 32; i++) { unsigned int k = 1 << i; if ((downMask_[iWord]&k) != 0) { int iColumn = which[i+32*iWord]; #ifdef FULL_PRINT printf("%d ", i + 32*iWord); #endif // fix weak way if (clique_->type(i + 32*iWord)) model_->solver()->setColUpper(integerVariables[iColumn], 0.0); else model_->solver()->setColLower(integerVariables[iColumn], 1.0); } } } way_ = -1; // Swap direction } #ifdef FULL_PRINT printf("\n"); #endif return 0.0; } void CbcLongCliqueBranchingObject::print() { int iWord; int numberMembers = clique_->numberMembers(); const int * which = clique_->members(); const int * integerVariables = model_->integerVariable(); int numberWords = (numberMembers + 31) >> 5; // *** for way - up means fix all those in down section if (way_ < 0) { printf("Clique - Down Fix "); for (iWord = 0; iWord < numberWords; iWord++) { int i; for (i = 0; i < 32; i++) { unsigned int k = 1 << i; if ((upMask_[iWord]&k) != 0) { int iColumn = which[i+32*iWord]; printf("%d ", integerVariables[iColumn]); } } } } else { printf("Clique - Up Fix "); for (iWord = 0; iWord < numberWords; iWord++) { int i; for (i = 0; i < 32; i++) { unsigned int k = 1 << i; if ((downMask_[iWord]&k) != 0) { int iColumn = which[i+32*iWord]; printf("%d ", integerVariables[iColumn]); } } } } printf("\n"); } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ int CbcLongCliqueBranchingObject::compareOriginalObject (const CbcBranchingObject* brObj) const { const CbcLongCliqueBranchingObject* br = dynamic_cast(brObj); assert(br); return CbcCompareCliques(clique_, br->clique_); } /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ CbcRangeCompare CbcLongCliqueBranchingObject::compareBranchingObject (const CbcBranchingObject* brObj, const bool /*replaceIfOverlap*/) { const CbcLongCliqueBranchingObject* br = dynamic_cast(brObj); assert(br); const int numberMembers = clique_->numberMembers(); const int numberWords = (numberMembers + 31) >> 5; unsigned int* thisMask = way_ < 0 ? upMask_ : downMask_; const unsigned int* otherMask = br->way_ < 0 ? br->upMask_ : br->downMask_; if (memcmp(thisMask, otherMask, numberWords * sizeof(unsigned int)) == 0) { return CbcRangeSame; } bool canBeSuperset = true; bool canBeSubset = true; int i; for (i = numberWords - 1; i >= 0 && (canBeSuperset || canBeSubset); --i) { const unsigned int both = (thisMask[i] & otherMask[i]); canBeSuperset &= (both == thisMask[i]); canBeSubset &= (both == otherMask[i]); } if (canBeSuperset) { return CbcRangeSuperset; } if (canBeSubset) { return CbcRangeSubset; } for (i = numberWords - 1; i >= 0; --i) { if ((thisMask[i] ^ otherMask[i]) != 0) { break; } } if (i == -1) { // complement return CbcRangeDisjoint; } // must be overlap for (i = numberWords - 1; i >= 0; --i) { thisMask[i] |= otherMask[i]; } return CbcRangeOverlap; } Cbc-2.8.12/src/CbcFollowOn.hpp0000644000076600007660000001471212131315050014414 0ustar coincoin// $Id: CbcFollowOn.hpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // Edwin 11/10/2009-- carved out of CbcBranchActual #ifndef CbcFollowOn_H #define CbcFollowOn_H #include "CbcBranchBase.hpp" #include "OsiRowCut.hpp" #include "CoinHelperFunctions.hpp" #include "CoinPackedMatrix.hpp" /** Define a follow on class. The idea of this is that in air-crew scheduling problems crew may fly in on flight A and out on flight B or on some other flight. A useful branch is one which on one side fixes all which go out on flight B to 0, while the other branch fixes all those that do NOT go out on flight B to 0. This branching rule should be in addition to normal rules and have a high priority. */ class CbcFollowOn : public CbcObject { public: // Default Constructor CbcFollowOn (); /** Useful constructor */ CbcFollowOn (CbcModel * model); // Copy constructor CbcFollowOn ( const CbcFollowOn &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcFollowOn & operator=( const CbcFollowOn& rhs); // Destructor ~CbcFollowOn (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /// This looks at solution and sets bounds to contain solution virtual void feasibleRegion(); /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// As some computation is needed in more than one place - returns row virtual int gutsOfFollowOn(int & otherRow, int & preferredWay) const; protected: /// data /// Matrix CoinPackedMatrix matrix_; /// Matrix by row CoinPackedMatrix matrixByRow_; /// Possible rhs (if 0 then not possible) int * rhs_; }; /** General Branching Object class. Each way fixes some variables to lower bound */ class CbcFixingBranchingObject : public CbcBranchingObject { public: // Default Constructor CbcFixingBranchingObject (); // Useful constructor CbcFixingBranchingObject (CbcModel * model, int way, int numberOnDownSide, const int * down, int numberOnUpSide, const int * up); // Copy constructor CbcFixingBranchingObject ( const CbcFixingBranchingObject &); // Assignment operator CbcFixingBranchingObject & operator=( const CbcFixingBranchingObject& rhs); /// Clone virtual CbcBranchingObject * clone() const; // Destructor virtual ~CbcFixingBranchingObject (); using CbcBranchingObject::branch ; /// Does next branch and updates state virtual double branch(); #ifdef JJF_ZERO // No need to override. Default works fine. /** Reset every information so that the branching object appears to point to the previous child. This method does not need to modify anything in any solver. */ virtual void previousBranch(); #endif using CbcBranchingObject::print ; /** \brief Print something about branch - only if log level high */ virtual void print(); /** Return the type (an integer identifier) of \c this */ virtual CbcBranchObjType type() const { return FollowOnBranchObj; } /** Compare the original object of \c this with the original object of \c brObj. Assumes that there is an ordering of the original objects. This method should be invoked only if \c this and brObj are of the same type. Return negative/0/positive depending on whether \c this is smaller/same/larger than the argument. */ virtual int compareOriginalObject(const CbcBranchingObject* brObj) const; /** Compare the \c this with \c brObj. \c this and \c brObj must be os the same type and must have the same original object, but they may have different feasible regions. Return the appropriate CbcRangeCompare value (first argument being the sub/superset if that's the case). In case of overlap (and if \c replaceIfOverlap is true) replace the current branching object with one whose feasible region is the overlap. */ virtual CbcRangeCompare compareBranchingObject (const CbcBranchingObject* brObj, const bool replaceIfOverlap = false); private: /// data /// Number on down list int numberDown_; /// Number on up list int numberUp_; /// downList - variables to fix to lb on down branch int * downList_; /// upList - variables to fix to lb on up branch int * upList_; }; /** Define an idiotic idea class. The idea of this is that we take some integer variables away from integer and sum them with some randomness to get signed sum close to 0.5. We then can branch to exclude that gap. This branching rule should be in addition to normal rules and have a high priority. */ class CbcIdiotBranch : public CbcObject { public: // Default Constructor CbcIdiotBranch (); /** Useful constructor */ CbcIdiotBranch (CbcModel * model); // Copy constructor CbcIdiotBranch ( const CbcIdiotBranch &); /// Clone virtual CbcObject * clone() const; // Assignment operator CbcIdiotBranch & operator=( const CbcIdiotBranch& rhs); // Destructor ~CbcIdiotBranch (); /// Infeasibility - large is 0.5 virtual double infeasibility(const OsiBranchingInformation * info, int &preferredWay) const; using CbcObject::feasibleRegion ; /// This looks at solution and sets bounds to contain solution virtual void feasibleRegion(); /// Creates a branching object virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) ; /// Initialize for branching virtual void initializeForBranching(CbcModel * ); protected: /// Build "cut" OsiRowCut buildCut(const OsiBranchingInformation * info,int type,int & preferredWay) const; /// data /// Thread specific random number generator mutable CoinThreadRandom randomNumberGenerator_; /// Saved version of thread specific random number generator mutable CoinThreadRandom savedRandomNumberGenerator_; }; #endif Cbc-2.8.12/src/CbcHeuristicDiveGuided.cpp0000644000076600007660000000713312131315050016540 0ustar coincoin/* $Id: CbcHeuristicDiveGuided.cpp 1902 2013-04-10 16:58:16Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcHeuristicDiveGuided.hpp" #include "CbcStrategy.hpp" // Default Constructor CbcHeuristicDiveGuided::CbcHeuristicDiveGuided() : CbcHeuristicDive() { } // Constructor from model CbcHeuristicDiveGuided::CbcHeuristicDiveGuided(CbcModel & model) : CbcHeuristicDive(model) { } // Destructor CbcHeuristicDiveGuided::~CbcHeuristicDiveGuided () { } // Clone CbcHeuristicDiveGuided * CbcHeuristicDiveGuided::clone() const { return new CbcHeuristicDiveGuided(*this); } // Create C++ lines to get to current state void CbcHeuristicDiveGuided::generateCpp( FILE * fp) { CbcHeuristicDiveGuided other; fprintf(fp, "0#include \"CbcHeuristicDiveGuided.hpp\"\n"); fprintf(fp, "3 CbcHeuristicDiveGuided heuristicDiveGuided(*cbcModel);\n"); CbcHeuristic::generateCpp(fp, "heuristicDiveGuided"); fprintf(fp, "3 cbcModel->addHeuristic(&heuristicDiveGuided);\n"); } // Copy constructor CbcHeuristicDiveGuided::CbcHeuristicDiveGuided(const CbcHeuristicDiveGuided & rhs) : CbcHeuristicDive(rhs) { } // Assignment operator CbcHeuristicDiveGuided & CbcHeuristicDiveGuided::operator=( const CbcHeuristicDiveGuided & rhs) { if (this != &rhs) { CbcHeuristicDive::operator=(rhs); } return *this; } bool CbcHeuristicDiveGuided::canHeuristicRun() { double* bestIntegerSolution = model_->bestSolution(); if (bestIntegerSolution == NULL) return false; // no integer solution available. Switch off heuristic return CbcHeuristicDive::canHeuristicRun(); } bool CbcHeuristicDiveGuided::selectVariableToBranch(OsiSolverInterface* solver, const double* newSolution, int& bestColumn, int& bestRound) { double* bestIntegerSolution = model_->bestSolution(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); bestColumn = -1; bestRound = -1; // -1 rounds down, +1 rounds up double bestFraction = COIN_DBL_MAX; bool allTriviallyRoundableSoFar = true; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; double fraction = value - floor(value); int round = 0; if (fabs(floor(value + 0.5) - value) > integerTolerance) { if (allTriviallyRoundableSoFar || (downLocks_[i] > 0 && upLocks_[i] > 0)) { if (allTriviallyRoundableSoFar && downLocks_[i] > 0 && upLocks_[i] > 0) { allTriviallyRoundableSoFar = false; bestFraction = COIN_DBL_MAX; } if (value >= bestIntegerSolution[iColumn]) round = -1; else { round = 1; fraction = 1.0 - fraction; } // if variable is not binary, penalize it if (!solver->isBinary(iColumn)) fraction *= 1000.0; if (fraction < bestFraction) { bestColumn = iColumn; bestFraction = fraction; bestRound = round; } } } } return allTriviallyRoundableSoFar; } Cbc-2.8.12/src/CbcEventHandler.hpp0000644000076600007660000001434712246146734015262 0ustar coincoin/* Copyright (C) 2006, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcEventHandler.hpp 1986 2013-11-29 17:24:44Z forrest $ */ #ifndef CbcEventHandler_H #define CbcEventHandler_H /*! \file CbcEventHandler.hpp \brief Event handling for cbc This file contains the declaration of CbcEventHandler, used for event handling in cbc. The central method is CbcEventHandler::event(). The default semantics of this call are `ask for the action to take in reponse to this event'. The call is made at the point in the code where the event occurs (e.g., when a solution is found, or when a node is added to or removed from the search tree). The return value specifies the action to perform in response to the event (e.g., continue, or stop). This is a lazy class. Initially, it knows nothing about specific events, and returns dfltAction_ for any event. This makes for a trivial constructor and fast startup. The only place where the list of known events or actions is hardwired is in the enum definitions for CbcEvent and CbcAction, respectively. At the first call to setAction, a map is created to hold (Event,Action) pairs, and this map will be consulted ever after. Events not in the map will still return the default value. For serious extensions, derive a subclass and replace event() with a function that suits you better. The function has access to the CbcModel via a pointer held in the CbcEventHandler object, and can do as much thinking as it likes before returning an answer. You can also print as much information as you want. The model is held as a const, however, so you can't alter reality. The design of the class deliberately matches ClpEventHandler, so that other solvers can participate in cbc without breaking the patterns set by clp-specific code. */ #include #include /* May well already be declared, but can't hurt. */ class CbcModel ; /* cvs/svn: $Id: CbcEventHandler.hpp 1986 2013-11-29 17:24:44Z forrest $ */ /*! \class CbcEventHandler \brief Base class for Cbc event handling. Up front: We're not talking about unanticipated events here. We're talking about anticipated events, in the sense that the code is going to make a call to event() and is prepared to obey the return value that it receives. The general pattern for usage is as follows:
  1. Create a CbcEventHandler object. This will be initialised with a set of default actions for every recognised event.
  2. Attach the event handler to the CbcModel object.
  3. When execution reaches the point where an event occurs, call the event handler as CbcEventHandler::event(the event). The return value will specify what the code should do in response to the event.
The return value associated with an event can be changed at any time. */ class CbcEventHandler { public: /*! \brief Events known to cbc */ enum CbcEvent { /*! Processing of the current node is complete. */ node = 200, /*! A tree status interval has arrived. */ treeStatus, /*! A solution has been found. */ solution, /*! A heuristic solution has been found. */ heuristicSolution, /*! A solution will be found unless user takes action (first check). */ beforeSolution1, /*! A solution will be found unless user takes action (thorough check). */ beforeSolution2, /*! After failed heuristic. */ afterHeuristic, /*! End of search. */ endSearch } ; /*! \brief Action codes returned by the event handler. Specific values are chosen to match ClpEventHandler return codes. */ enum CbcAction { /*! Continue --- no action required. */ noAction = -1, /*! Stop --- abort the current run at the next opportunity. */ stop = 0, /*! Restart --- restart branch-and-cut search; do not undo root node processing. */ restart, /*! RestartRoot --- undo root node and start branch-and-cut afresh. */ restartRoot, /*! Add special cuts. */ addCuts, /*! Pretend solution never happened. */ killSolution } ; /*! \brief Data type for event/action pairs */ typedef std::map eaMapPair ; /*! \name Event Processing */ //@{ /*! \brief Return the action to be taken for an event. Return the action that should be taken in response to the event passed as the parameter. The default implementation simply reads a return code from a map. */ virtual CbcAction event(CbcEvent whichEvent) ; //@} /*! \name Constructors and destructors */ //@{ /*! \brief Default constructor. */ CbcEventHandler(CbcModel *model = 0 /* was NULL but 4.6 complains */) ; /*! \brief Copy constructor. */ CbcEventHandler(const CbcEventHandler &orig) ; /*! \brief Assignment. */ CbcEventHandler& operator=(const CbcEventHandler &rhs) ; /*! \brief Clone (virtual) constructor. */ virtual CbcEventHandler* clone() const ; /*! \brief Destructor. */ virtual ~CbcEventHandler() ; //@} /*! \name Set/Get methods */ //@{ /*! \brief Set model. */ inline void setModel(CbcModel *model) { model_ = model ; } /*! \brief Get model. */ inline const CbcModel* getModel() const { return model_ ; } /*! \brief Set the default action */ inline void setDfltAction(CbcAction action) { dfltAction_ = action ; } /*! \brief Set the action code associated with an event */ inline void setAction(CbcEvent event, CbcAction action) { if (eaMap_ == 0) { eaMap_ = new eaMapPair ; } (*eaMap_)[event] = action ; } //@} protected: /*! \name Data members Protected (as opposed to private) to allow access by derived classes. */ //@{ /*! \brief Pointer to associated CbcModel */ CbcModel *model_ ; /*! \brief Default action */ CbcAction dfltAction_ ; /*! \brief Pointer to a map that holds non-default event/action pairs */ eaMapPair *eaMap_ ; //@} } ; #endif Cbc-2.8.12/src/CbcTreeLocal.cpp0000644000076600007660000020251212075572125014536 0ustar coincoin/* $Id: CbcTreeLocal.cpp 1839 2013-01-16 18:41:25Z forrest $ */ // Copyright (C) 2004, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CbcModel.hpp" #include "CbcNode.hpp" #include "CbcTreeLocal.hpp" #include "CoinPackedMatrix.hpp" #include "CoinTime.hpp" #include "OsiRowCutDebugger.hpp" #include #ifdef JJF_ZERO // gdb doesn't always put breakpoints in this virtual function // just stick xxxxxx() where you want to start static void xxxxxx() { printf("break\n"); } #endif CbcTreeLocal::CbcTreeLocal() : localNode_(NULL), bestSolution_(NULL), savedSolution_(NULL), saveNumberSolutions_(0), model_(NULL), originalLower_(NULL), originalUpper_(NULL), range_(0), typeCuts_(-1), maxDiversification_(0), diversification_(0), nextStrong_(false), rhs_(0.0), savedGap_(0.0), bestCutoff_(0.0), timeLimit_(0), startTime_(0), nodeLimit_(0), startNode_(-1), searchType_(-1), refine_(false) { } /* Constructor with solution. range is upper bound on difference from given solution. maxDiversification is maximum number of diversifications to try timeLimit is seconds in subTree nodeLimit is nodes in subTree */ CbcTreeLocal::CbcTreeLocal(CbcModel * model, const double * solution , int range, int typeCuts, int maxDiversification, int timeLimit, int nodeLimit, bool refine) : localNode_(NULL), bestSolution_(NULL), savedSolution_(NULL), saveNumberSolutions_(0), model_(model), originalLower_(NULL), originalUpper_(NULL), range_(range), typeCuts_(typeCuts), maxDiversification_(maxDiversification), diversification_(0), nextStrong_(false), rhs_(0.0), savedGap_(0.0), bestCutoff_(0.0), timeLimit_(timeLimit), startTime_(0), nodeLimit_(nodeLimit), startNode_(-1), searchType_(-1), refine_(refine) { OsiSolverInterface * solver = model_->solver(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); //const double * solution = solver->getColSolution(); //const double * objective = solver->getObjCoefficients(); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // Get increment model_->analyzeObjective(); { // needed to sync cutoffs double value ; solver->getDblParam(OsiDualObjectiveLimit, value) ; model_->setCutoff(value * solver->getObjSense()); } bestCutoff_ = model_->getCutoff(); // save current gap savedGap_ = model_->getDblParam(CbcModel::CbcAllowableGap); // make sure integers found model_->findIntegers(false); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; double direction = solver->getObjSense(); double newSolutionValue = 1.0e50; if (solution) { // copy solution solver->setColSolution(solution); newSolutionValue = direction * solver->getObjValue(); } originalLower_ = new double [numberIntegers]; originalUpper_ = new double [numberIntegers]; bool all01 = true; int number01 = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; originalLower_[i] = lower[iColumn]; originalUpper_[i] = upper[iColumn]; if (upper[iColumn] - lower[iColumn] > 1.5) all01 = false; else if (upper[iColumn] - lower[iColumn] == 1.0) number01++; } if (all01 && !typeCuts_) typeCuts_ = 1; // may as well so we don't have to deal with refine if (!number01 && !typeCuts_) { if (model_->messageHandler()->logLevel() > 1) printf("** No 0-1 variables and local search only on 0-1 - switching off\n"); typeCuts_ = -1; } else { if (model_->messageHandler()->logLevel() > 1) { std::string type; if (all01) { printf("%d 0-1 variables normal local cuts\n", number01); } else if (typeCuts_) { printf("%d 0-1 variables, %d other - general integer local cuts\n", number01, numberIntegers - number01); } else { printf("%d 0-1 variables, %d other - local cuts but just on 0-1 variables\n", number01, numberIntegers - number01); } printf("maximum diversifications %d, initial cutspace %d, max time %d seconds, max nodes %d\n", maxDiversification_, range_, timeLimit_, nodeLimit_); } } int numberColumns = model_->getNumCols(); savedSolution_ = new double [numberColumns]; memset(savedSolution_, 0, numberColumns*sizeof(double)); if (solution) { rhs_ = range_; // Check feasible int goodSolution = createCut(solution, cut_); if (goodSolution >= 0) { for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = floor(solution[iColumn] + 0.5); // fix so setBestSolution will work solver->setColLower(iColumn, value); solver->setColUpper(iColumn, value); } model_->reserveCurrentSolution(); // Create cut and get total gap if (newSolutionValue < bestCutoff_) { model_->setBestSolution(CBC_ROUNDING, newSolutionValue, solution); bestCutoff_ = model_->getCutoff(); // save as best solution memcpy(savedSolution_, model_->bestSolution(), numberColumns*sizeof(double)); } for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; // restore bounds solver->setColLower(iColumn, originalLower_[i]); solver->setColUpper(iColumn, originalUpper_[i]); } // make sure can't stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, -1.0e50); } else { model_ = NULL; } } else { // no solution rhs_ = 1.0e50; // make sure can't stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, -1.0e50); } } CbcTreeLocal::~CbcTreeLocal() { delete [] originalLower_; delete [] originalUpper_; delete [] bestSolution_; delete [] savedSolution_; delete localNode_; } // Copy constructor CbcTreeLocal::CbcTreeLocal ( const CbcTreeLocal & rhs) : CbcTree(rhs), saveNumberSolutions_(rhs.saveNumberSolutions_), model_(rhs.model_), range_(rhs.range_), typeCuts_(rhs.typeCuts_), maxDiversification_(rhs.maxDiversification_), diversification_(rhs.diversification_), nextStrong_(rhs.nextStrong_), rhs_(rhs.rhs_), savedGap_(rhs.savedGap_), bestCutoff_(rhs.bestCutoff_), timeLimit_(rhs.timeLimit_), startTime_(rhs.startTime_), nodeLimit_(rhs.nodeLimit_), startNode_(rhs.startNode_), searchType_(rhs.searchType_), refine_(rhs.refine_) { cut_ = rhs.cut_; fixedCut_ = rhs.fixedCut_; if (rhs.localNode_) localNode_ = new CbcNode(*rhs.localNode_); else localNode_ = NULL; if (rhs.originalLower_) { int numberIntegers = model_->numberIntegers(); originalLower_ = new double [numberIntegers]; memcpy(originalLower_, rhs.originalLower_, numberIntegers*sizeof(double)); originalUpper_ = new double [numberIntegers]; memcpy(originalUpper_, rhs.originalUpper_, numberIntegers*sizeof(double)); } else { originalLower_ = NULL; originalUpper_ = NULL; } if (rhs.bestSolution_) { int numberColumns = model_->getNumCols(); bestSolution_ = new double [numberColumns]; memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double)); } else { bestSolution_ = NULL; } if (rhs.savedSolution_) { int numberColumns = model_->getNumCols(); savedSolution_ = new double [numberColumns]; memcpy(savedSolution_, rhs.savedSolution_, numberColumns*sizeof(double)); } else { savedSolution_ = NULL; } } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcTreeLocal & CbcTreeLocal::operator=(const CbcTreeLocal & rhs) { if (this != &rhs) { CbcTree::operator=(rhs); saveNumberSolutions_ = rhs.saveNumberSolutions_; cut_ = rhs.cut_; fixedCut_ = rhs.fixedCut_; delete localNode_; if (rhs.localNode_) localNode_ = new CbcNode(*rhs.localNode_); else localNode_ = NULL; model_ = rhs.model_; range_ = rhs.range_; typeCuts_ = rhs.typeCuts_; maxDiversification_ = rhs.maxDiversification_; diversification_ = rhs.diversification_; nextStrong_ = rhs.nextStrong_; rhs_ = rhs.rhs_; savedGap_ = rhs.savedGap_; bestCutoff_ = rhs.bestCutoff_; timeLimit_ = rhs.timeLimit_; startTime_ = rhs.startTime_; nodeLimit_ = rhs.nodeLimit_; startNode_ = rhs.startNode_; searchType_ = rhs.searchType_; refine_ = rhs.refine_; delete [] originalLower_; delete [] originalUpper_; if (rhs.originalLower_) { int numberIntegers = model_->numberIntegers(); originalLower_ = new double [numberIntegers]; memcpy(originalLower_, rhs.originalLower_, numberIntegers*sizeof(double)); originalUpper_ = new double [numberIntegers]; memcpy(originalUpper_, rhs.originalUpper_, numberIntegers*sizeof(double)); } else { originalLower_ = NULL; originalUpper_ = NULL; } delete [] bestSolution_; if (rhs.bestSolution_) { int numberColumns = model_->getNumCols(); bestSolution_ = new double [numberColumns]; memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double)); } else { bestSolution_ = NULL; } delete [] savedSolution_; if (rhs.savedSolution_) { int numberColumns = model_->getNumCols(); savedSolution_ = new double [numberColumns]; memcpy(savedSolution_, rhs.savedSolution_, numberColumns*sizeof(double)); } else { savedSolution_ = NULL; } } return *this; } // Clone CbcTree * CbcTreeLocal::clone() const { return new CbcTreeLocal(*this); } // Pass in solution (so can be used after heuristic) void CbcTreeLocal::passInSolution(const double * solution, double solutionValue) { int numberColumns = model_->getNumCols(); delete [] savedSolution_; savedSolution_ = new double [numberColumns]; memcpy(savedSolution_, solution, numberColumns*sizeof(double)); rhs_ = range_; // Check feasible int goodSolution = createCut(solution, cut_); if (goodSolution >= 0) { bestCutoff_ = CoinMin(solutionValue, model_->getCutoff()); } else { model_ = NULL; } } // Return the top node of the heap CbcNode * CbcTreeLocal::top() const { #ifdef CBC_DEBUG int smallest = 9999999; int largest = -1; double smallestD = 1.0e30; double largestD = -1.0e30; int n = nodes_.size(); for (int i = 0; i < n; i++) { int nn = nodes_[i]->nodeInfo()->nodeNumber(); double dd = nodes_[i]->objectiveValue(); largest = CoinMax(largest, nn); smallest = CoinMin(smallest, nn); largestD = CoinMax(largestD, dd); smallestD = CoinMin(smallestD, dd); } if (model_->messageHandler()->logLevel() > 1) { printf("smallest %d, largest %d, top %d\n", smallest, largest, nodes_.front()->nodeInfo()->nodeNumber()); printf("smallestD %g, largestD %g, top %g\n", smallestD, largestD, nodes_.front()->objectiveValue()); } #endif return nodes_.front(); } // Add a node to the heap void CbcTreeLocal::push(CbcNode * x) { if (typeCuts_ >= 0 && !nodes_.size() && searchType_ < 0) { startNode_ = model_->getNodeCount(); // save copy of node localNode_ = new CbcNode(*x); if (cut_.row().getNumElements()) { // Add to global cuts // we came in with solution model_->makeGlobalCut(cut_); if (model_->messageHandler()->logLevel() > 1) printf("initial cut - rhs %g %g\n", cut_.lb(), cut_.ub()); searchType_ = 1; } else { // stop on first solution searchType_ = 0; } startTime_ = static_cast (CoinCpuTime()); saveNumberSolutions_ = model_->getSolutionCount(); } nodes_.push_back(x); #ifdef CBC_DEBUG if (model_->messageHandler()->logLevel() > 0) printf("pushing node onto heap %d %x %x\n", x->nodeInfo()->nodeNumber(), x, x->nodeInfo()); #endif std::push_heap(nodes_.begin(), nodes_.end(), comparison_); } // Remove the top node from the heap void CbcTreeLocal::pop() { std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); } // Test if empty - does work if so bool CbcTreeLocal::empty() { if (typeCuts_ < 0) return !nodes_.size(); /* state - 0 iterating 1 subtree finished optimal solution for subtree found 2 subtree finished and no solution found 3 subtree exiting and solution found 4 subtree exiting and no solution found */ int state = 0; assert (searchType_ != 2); if (searchType_) { if (CoinCpuTime() - startTime_ > timeLimit_ || model_->getNodeCount() - startNode_ >= nodeLimit_) { state = 4; } } else { if (model_->getSolutionCount() > saveNumberSolutions_) { state = 4; } } if (!nodes_.size()) state = 2; if (!state) { return false; } // Finished this phase int numberColumns = model_->getNumCols(); if (model_->getSolutionCount() > saveNumberSolutions_) { if (model_->getCutoff() < bestCutoff_) { // Save solution if (!bestSolution_) bestSolution_ = new double [numberColumns]; memcpy(bestSolution_, model_->bestSolution(), numberColumns*sizeof(double)); bestCutoff_ = model_->getCutoff(); } state--; } // get rid of all nodes (safe even if already done) double bestPossibleObjective; cleanTree(model_, -COIN_DBL_MAX, bestPossibleObjective); double increment = model_->getDblParam(CbcModel::CbcCutoffIncrement) ; if (model_->messageHandler()->logLevel() > 1) printf("local state %d after %d nodes and %d seconds, new solution %g, best solution %g, k was %g\n", state, model_->getNodeCount() - startNode_, static_cast (CoinCpuTime()) - startTime_, model_->getCutoff() + increment, bestCutoff_ + increment, rhs_); saveNumberSolutions_ = model_->getSolutionCount(); bool finished = false; bool lastTry = false; switch (state) { case 1: // solution found and subtree exhausted if (rhs_ > 1.0e30) { finished = true; } else { // find global cut and reverse reverseCut(1); searchType_ = 1; // first false rhs_ = range_; // reset range nextStrong_ = false; // save best solution in this subtree memcpy(savedSolution_, model_->bestSolution(), numberColumns*sizeof(double)); } break; case 2: // solution not found and subtree exhausted if (rhs_ > 1.0e30) { finished = true; } else { // find global cut and reverse reverseCut(2); searchType_ = 1; // first false if (diversification_ < maxDiversification_) { if (nextStrong_) { diversification_++; // cut is valid so don't model_->setCutoff(1.0e50); searchType_ = 0; } nextStrong_ = true; rhs_ += range_ / 2; } else { // This will be last try (may hit max time) lastTry = true; if (!maxDiversification_) typeCuts_ = -1; // make sure can't start again model_->setCutoff(bestCutoff_); if (model_->messageHandler()->logLevel() > 1) printf("Exiting local search with current set of cuts\n"); rhs_ = 1.0e100; // Can now stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, savedGap_); } } break; case 3: // solution found and subtree not exhausted if (rhs_ < 1.0e30) { if (searchType_) { if (!typeCuts_ && refine_ && searchType_ == 1) { // We need to check we have best solution given these 0-1 values OsiSolverInterface * subSolver = model_->continuousSolver()->clone(); CbcModel * subModel = model_->subTreeModel(subSolver); CbcTree normalTree; subModel->passInTreeHandler(normalTree); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double * solution = model_->bestSolution(); int i; int numberColumns = model_->getNumCols(); for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = floor(solution[iColumn] + 0.5); if (!typeCuts_ && originalUpper_[i] - originalLower_[i] > 1.0) continue; // skip as not 0-1 if (originalLower_[i] == originalUpper_[i]) continue; subSolver->setColLower(iColumn, value); subSolver->setColUpper(iColumn, value); } subSolver->initialSolve(); // We can copy cutoff // But adjust subModel->setCutoff(model_->getCutoff() + model_->getDblParam(CbcModel::CbcCutoffIncrement) + 1.0e-6); subModel->setSolutionCount(0); assert (subModel->isProvenOptimal()); if (!subModel->typePresolve()) { subModel->branchAndBound(); if (subModel->status()) { model_->incrementSubTreeStopped(); } //printf("%g %g %g %g\n",subModel->getCutoff(),model_->getCutoff(), // subModel->getMinimizationObjValue(),model_->getMinimizationObjValue()); double newCutoff = subModel->getMinimizationObjValue() - subModel->getDblParam(CbcModel::CbcCutoffIncrement) ; if (subModel->getSolutionCount()) { if (!subModel->status()) assert (subModel->isProvenOptimal()); memcpy(model_->bestSolution(), subModel->bestSolution(), numberColumns*sizeof(double)); model_->setCutoff(newCutoff); } } else if (subModel->typePresolve() == 1) { CbcModel * model2 = subModel->integerPresolve(true); if (model2) { // Do complete search model2->branchAndBound(); // get back solution subModel->originalModel(model2, false); if (model2->status()) { model_->incrementSubTreeStopped(); } double newCutoff = model2->getMinimizationObjValue() - model2->getDblParam(CbcModel::CbcCutoffIncrement) ; if (model2->getSolutionCount()) { if (!model2->status()) assert (model2->isProvenOptimal()); memcpy(model_->bestSolution(), subModel->bestSolution(), numberColumns*sizeof(double)); model_->setCutoff(newCutoff); } delete model2; } else { // infeasible - could just be - due to cutoff } } else { // too dangerous at present assert (subModel->typePresolve() != 2); } if (model_->getCutoff() < bestCutoff_) { // Save solution if (!bestSolution_) bestSolution_ = new double [numberColumns]; memcpy(bestSolution_, model_->bestSolution(), numberColumns*sizeof(double)); bestCutoff_ = model_->getCutoff(); } delete subModel; } // we have done search to make sure best general solution searchType_ = 1; // Reverse cut weakly reverseCut(3, rhs_); } else { searchType_ = 1; // delete last cut deleteCut(cut_); } } else { searchType_ = 1; } // save best solution in this subtree memcpy(savedSolution_, model_->bestSolution(), numberColumns*sizeof(double)); nextStrong_ = false; rhs_ = range_; break; case 4: // solution not found and subtree not exhausted if (maxDiversification_) { if (nextStrong_) { // Reverse cut weakly reverseCut(4, rhs_); model_->setCutoff(1.0e50); diversification_++; searchType_ = 0; } else { // delete last cut deleteCut(cut_); searchType_ = 1; } nextStrong_ = true; rhs_ += range_ / 2; } else { // special case when using as heuristic // Reverse cut weakly if lb -infinity reverseCut(4, rhs_); // This will be last try (may hit max time0 lastTry = true; model_->setCutoff(bestCutoff_); if (model_->messageHandler()->logLevel() > 1) printf("Exiting local search with current set of cuts\n"); rhs_ = 1.0e100; // Can now stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, savedGap_); typeCuts_ = -1; } break; } if (rhs_ < 1.0e30 || lastTry) { int goodSolution = createCut(savedSolution_, cut_); if (goodSolution >= 0) { // Add to global cuts model_->makeGlobalCut(cut_); CbcRowCuts * global = model_->globalCuts(); int n = global->sizeRowCuts(); OsiRowCut * rowCut = global->rowCutPtr(n - 1); if (model_->messageHandler()->logLevel() > 1) printf("inserting cut - now %d cuts, rhs %g %g, cutspace %g, diversification %d\n", n, rowCut->lb(), rowCut->ub(), rhs_, diversification_); const OsiRowCutDebugger *debugger = model_->solver()->getRowCutDebuggerAlways() ; if (debugger) { if (debugger->invalidCut(*rowCut)) printf("ZZZZTree Global cut - cuts off optimal solution!\n"); } for (int i = 0; i < n; i++) { rowCut = global->rowCutPtr(i); if (model_->messageHandler()->logLevel() > 0) printf("%d - rhs %g %g\n", i, rowCut->lb(), rowCut->ub()); } } // put back node startTime_ = static_cast (CoinCpuTime()); startNode_ = model_->getNodeCount(); if (localNode_) { // save copy of node CbcNode * localNode2 = new CbcNode(*localNode_); // But localNode2 now owns cuts so swap //printf("pushing local node2 onto heap %d %x %x\n",localNode_->nodeNumber(), // localNode_,localNode_->nodeInfo()); nodes_.push_back(localNode_); localNode_ = localNode2; std::make_heap(nodes_.begin(), nodes_.end(), comparison_); } } return finished; } // We may have got an intelligent tree so give it one more chance void CbcTreeLocal::endSearch() { if (typeCuts_ >= 0) { // copy best solution to model int numberColumns = model_->getNumCols(); if (bestSolution_ && bestCutoff_ < model_->getCutoff()) { memcpy(model_->bestSolution(), bestSolution_, numberColumns*sizeof(double)); model_->setCutoff(bestCutoff_); // recompute objective value const double * objCoef = model_->getObjCoefficients(); double objOffset = 0.0; model_->continuousSolver()->getDblParam(OsiObjOffset, objOffset); // Compute dot product of objCoef and colSol and then adjust by offset double objValue = -objOffset; for ( int i = 0 ; i < numberColumns ; i++ ) objValue += objCoef[i] * bestSolution_[i]; model_->setMinimizationObjValue(objValue); } // Can now stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, savedGap_); } } // Create cut int CbcTreeLocal::createCut(const double * solution, OsiRowCut & rowCut) { if (rhs_ > 1.0e20) return -1; OsiSolverInterface * solver = model_->solver(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); //const double * solution = solver->getColSolution(); //const double * objective = solver->getObjCoefficients(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // relax primalTolerance *= 1000.0; int numberRows = model_->getNumRows(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; // Check feasible double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); solver->getMatrixByCol()->times(solution, rowActivity) ; int goodSolution = 0; // check was feasible for (i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i] - primalTolerance) { goodSolution = -1; } else if (rowActivity[i] > rowUpper[i] + primalTolerance) { goodSolution = -1; } } delete [] rowActivity; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = solution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { goodSolution = -1; } } // zap cut if (goodSolution == 0) { // Create cut and get total gap CoinPackedVector cut; double rhs = rhs_; double maxValue = 0.0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = floor(solution[iColumn] + 0.5); /* typeCuts_ == 0 restricts to binary, 1 allows general integer. But we're still restricted to being up against a bound. Consider: the notion is that the cut restricts us to a k-neighbourhood. For binary variables, this amounts to k variables which change value. For general integer, we could end up with a single variable sucking up all of k (hence mu --- the variable must swing to its other bound to look like a movement of 1). For variables in the middle of a range, we're talking about fabs(sol - x). */ if (!typeCuts_ && originalUpper_[i] - originalLower_[i] > 1.0) continue; // skip as not 0-1 if (originalLower_[i] == originalUpper_[i]) continue; double mu = 1.0 / (originalUpper_[i] - originalLower_[i]); if (value == originalLower_[i]) { rhs += mu * originalLower_[i]; cut.insert(iColumn, 1.0); maxValue += originalUpper_[i]; } else if (value == originalUpper_[i]) { rhs -= mu * originalUpper_[i]; cut.insert(iColumn, -1.0); maxValue += originalLower_[i]; } } if (maxValue < rhs - primalTolerance) { if (model_->messageHandler()->logLevel() > 1) printf("slack cut\n"); goodSolution = 1; } rowCut.setRow(cut); rowCut.setLb(-COIN_DBL_MAX); rowCut.setUb(rhs); rowCut.setGloballyValid(); if (model_->messageHandler()->logLevel() > 1) printf("Cut size: %i Cut rhs: %g\n", cut.getNumElements(), rhs); #ifdef CBC_DEBUG if (model_->messageHandler()->logLevel() > 0) { int k; for (k = 0; k < cut.getNumElements(); k++) { printf("%i %g ", cut.getIndices()[k], cut.getElements()[k]); if ((k + 1) % 5 == 0) printf("\n"); } if (k % 5 != 0) printf("\n"); } #endif return goodSolution; } else { if (model_->messageHandler()->logLevel() > 1) printf("Not a good solution\n"); return -1; } } // Other side of last cut branch void CbcTreeLocal::reverseCut(int state, double bias) { // find global cut CbcRowCuts * global = model_->globalCuts(); int n = global->sizeRowCuts(); int i; OsiRowCut * rowCut = NULL; for ( i = 0; i < n; i++) { rowCut = global->rowCutPtr(i); if (cut_ == *rowCut) { break; } } if (!rowCut) { // must have got here in odd way e.g. strong branching return; } if (rowCut->lb() > -1.0e10) return; // get smallest element double smallest = COIN_DBL_MAX; CoinPackedVector row = cut_.row(); for (int k = 0; k < row.getNumElements(); k++) smallest = CoinMin(smallest, fabs(row.getElements()[k])); if (!typeCuts_ && !refine_) { // Reverse cut very very weakly if (state > 2) smallest = 0.0; } // replace by other way if (model_->messageHandler()->logLevel() > 1) printf("reverseCut - changing cut %d out of %d, old rhs %g %g ", i, n, rowCut->lb(), rowCut->ub()); rowCut->setLb(rowCut->ub() + smallest - bias); rowCut->setUb(COIN_DBL_MAX); if (model_->messageHandler()->logLevel() > 1) printf("new rhs %g %g, bias %g smallest %g ", rowCut->lb(), rowCut->ub(), bias, smallest); const OsiRowCutDebugger *debugger = model_->solver()->getRowCutDebuggerAlways() ; if (debugger) { if (debugger->invalidCut(*rowCut)) printf("ZZZZTree Global cut - cuts off optimal solution!\n"); } } // Delete last cut branch void CbcTreeLocal::deleteCut(OsiRowCut & cut) { // find global cut CbcRowCuts * global = model_->globalCuts(); int n = global->sizeRowCuts(); int i; OsiRowCut * rowCut = NULL; for ( i = 0; i < n; i++) { rowCut = global->rowCutPtr(i); if (cut == *rowCut) { break; } } assert (i < n); // delete last cut if (model_->messageHandler()->logLevel() > 1) printf("deleteCut - deleting cut %d out of %d, rhs %g %g\n", i, n, rowCut->lb(), rowCut->ub()); global->eraseRowCut(i); } // Create C++ lines to get to current state void CbcTreeLocal::generateCpp( FILE * fp) { CbcTreeLocal other; fprintf(fp, "0#include \"CbcTreeLocal.hpp\"\n"); fprintf(fp, "5 CbcTreeLocal localTree(cbcModel,NULL);\n"); if (range_ != other.range_) fprintf(fp, "5 localTree.setRange(%d);\n", range_); if (typeCuts_ != other.typeCuts_) fprintf(fp, "5 localTree.setTypeCuts(%d);\n", typeCuts_); if (maxDiversification_ != other.maxDiversification_) fprintf(fp, "5 localTree.setMaxDiversification(%d);\n", maxDiversification_); if (timeLimit_ != other.timeLimit_) fprintf(fp, "5 localTree.setTimeLimit(%d);\n", timeLimit_); if (nodeLimit_ != other.nodeLimit_) fprintf(fp, "5 localTree.setNodeLimit(%d);\n", nodeLimit_); if (refine_ != other.refine_) fprintf(fp, "5 localTree.setRefine(%s);\n", refine_ ? "true" : "false"); fprintf(fp, "5 cbcModel->passInTreeHandler(localTree);\n"); } CbcTreeVariable::CbcTreeVariable() : localNode_(NULL), bestSolution_(NULL), savedSolution_(NULL), saveNumberSolutions_(0), model_(NULL), originalLower_(NULL), originalUpper_(NULL), range_(0), typeCuts_(-1), maxDiversification_(0), diversification_(0), nextStrong_(false), rhs_(0.0), savedGap_(0.0), bestCutoff_(0.0), timeLimit_(0), startTime_(0), nodeLimit_(0), startNode_(-1), searchType_(-1), refine_(false) { } /* Constructor with solution. range is upper bound on difference from given solution. maxDiversification is maximum number of diversifications to try timeLimit is seconds in subTree nodeLimit is nodes in subTree */ CbcTreeVariable::CbcTreeVariable(CbcModel * model, const double * solution , int range, int typeCuts, int maxDiversification, int timeLimit, int nodeLimit, bool refine) : localNode_(NULL), bestSolution_(NULL), savedSolution_(NULL), saveNumberSolutions_(0), model_(model), originalLower_(NULL), originalUpper_(NULL), range_(range), typeCuts_(typeCuts), maxDiversification_(maxDiversification), diversification_(0), nextStrong_(false), rhs_(0.0), savedGap_(0.0), bestCutoff_(0.0), timeLimit_(timeLimit), startTime_(0), nodeLimit_(nodeLimit), startNode_(-1), searchType_(-1), refine_(refine) { OsiSolverInterface * solver = model_->solver(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); //const double * solution = solver->getColSolution(); //const double * objective = solver->getObjCoefficients(); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // Get increment model_->analyzeObjective(); { // needed to sync cutoffs double value ; solver->getDblParam(OsiDualObjectiveLimit, value) ; model_->setCutoff(value * solver->getObjSense()); } bestCutoff_ = model_->getCutoff(); // save current gap savedGap_ = model_->getDblParam(CbcModel::CbcAllowableGap); // make sure integers found model_->findIntegers(false); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; double direction = solver->getObjSense(); double newSolutionValue = 1.0e50; if (solution) { // copy solution solver->setColSolution(solution); newSolutionValue = direction * solver->getObjValue(); } originalLower_ = new double [numberIntegers]; originalUpper_ = new double [numberIntegers]; bool all01 = true; int number01 = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; originalLower_[i] = lower[iColumn]; originalUpper_[i] = upper[iColumn]; if (upper[iColumn] - lower[iColumn] > 1.5) all01 = false; else if (upper[iColumn] - lower[iColumn] == 1.0) number01++; } if (all01 && !typeCuts_) typeCuts_ = 1; // may as well so we don't have to deal with refine if (!number01 && !typeCuts_) { if (model_->messageHandler()->logLevel() > 1) printf("** No 0-1 variables and local search only on 0-1 - switching off\n"); typeCuts_ = -1; } else { if (model_->messageHandler()->logLevel() > 1) { std::string type; if (all01) { printf("%d 0-1 variables normal local cuts\n", number01); } else if (typeCuts_) { printf("%d 0-1 variables, %d other - general integer local cuts\n", number01, numberIntegers - number01); } else { printf("%d 0-1 variables, %d other - local cuts but just on 0-1 variables\n", number01, numberIntegers - number01); } printf("maximum diversifications %d, initial cutspace %d, max time %d seconds, max nodes %d\n", maxDiversification_, range_, timeLimit_, nodeLimit_); } } int numberColumns = model_->getNumCols(); savedSolution_ = new double [numberColumns]; memset(savedSolution_, 0, numberColumns*sizeof(double)); if (solution) { rhs_ = range_; // Check feasible int goodSolution = createCut(solution, cut_); if (goodSolution >= 0) { for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = floor(solution[iColumn] + 0.5); // fix so setBestSolution will work solver->setColLower(iColumn, value); solver->setColUpper(iColumn, value); } model_->reserveCurrentSolution(); // Create cut and get total gap if (newSolutionValue < bestCutoff_) { model_->setBestSolution(CBC_ROUNDING, newSolutionValue, solution); bestCutoff_ = model_->getCutoff(); // save as best solution memcpy(savedSolution_, model_->bestSolution(), numberColumns*sizeof(double)); } for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; // restore bounds solver->setColLower(iColumn, originalLower_[i]); solver->setColUpper(iColumn, originalUpper_[i]); } // make sure can't stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, -1.0e50); } else { model_ = NULL; } } else { // no solution rhs_ = 1.0e50; // make sure can't stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, -1.0e50); } } CbcTreeVariable::~CbcTreeVariable() { delete [] originalLower_; delete [] originalUpper_; delete [] bestSolution_; delete [] savedSolution_; delete localNode_; } // Copy constructor CbcTreeVariable::CbcTreeVariable ( const CbcTreeVariable & rhs) : CbcTree(rhs), saveNumberSolutions_(rhs.saveNumberSolutions_), model_(rhs.model_), range_(rhs.range_), typeCuts_(rhs.typeCuts_), maxDiversification_(rhs.maxDiversification_), diversification_(rhs.diversification_), nextStrong_(rhs.nextStrong_), rhs_(rhs.rhs_), savedGap_(rhs.savedGap_), bestCutoff_(rhs.bestCutoff_), timeLimit_(rhs.timeLimit_), startTime_(rhs.startTime_), nodeLimit_(rhs.nodeLimit_), startNode_(rhs.startNode_), searchType_(rhs.searchType_), refine_(rhs.refine_) { cut_ = rhs.cut_; fixedCut_ = rhs.fixedCut_; if (rhs.localNode_) localNode_ = new CbcNode(*rhs.localNode_); else localNode_ = NULL; if (rhs.originalLower_) { int numberIntegers = model_->numberIntegers(); originalLower_ = new double [numberIntegers]; memcpy(originalLower_, rhs.originalLower_, numberIntegers*sizeof(double)); originalUpper_ = new double [numberIntegers]; memcpy(originalUpper_, rhs.originalUpper_, numberIntegers*sizeof(double)); } else { originalLower_ = NULL; originalUpper_ = NULL; } if (rhs.bestSolution_) { int numberColumns = model_->getNumCols(); bestSolution_ = new double [numberColumns]; memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double)); } else { bestSolution_ = NULL; } if (rhs.savedSolution_) { int numberColumns = model_->getNumCols(); savedSolution_ = new double [numberColumns]; memcpy(savedSolution_, rhs.savedSolution_, numberColumns*sizeof(double)); } else { savedSolution_ = NULL; } } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcTreeVariable & CbcTreeVariable::operator=(const CbcTreeVariable & rhs) { if (this != &rhs) { CbcTree::operator=(rhs); saveNumberSolutions_ = rhs.saveNumberSolutions_; cut_ = rhs.cut_; fixedCut_ = rhs.fixedCut_; delete localNode_; if (rhs.localNode_) localNode_ = new CbcNode(*rhs.localNode_); else localNode_ = NULL; model_ = rhs.model_; range_ = rhs.range_; typeCuts_ = rhs.typeCuts_; maxDiversification_ = rhs.maxDiversification_; diversification_ = rhs.diversification_; nextStrong_ = rhs.nextStrong_; rhs_ = rhs.rhs_; savedGap_ = rhs.savedGap_; bestCutoff_ = rhs.bestCutoff_; timeLimit_ = rhs.timeLimit_; startTime_ = rhs.startTime_; nodeLimit_ = rhs.nodeLimit_; startNode_ = rhs.startNode_; searchType_ = rhs.searchType_; refine_ = rhs.refine_; delete [] originalLower_; delete [] originalUpper_; if (rhs.originalLower_) { int numberIntegers = model_->numberIntegers(); originalLower_ = new double [numberIntegers]; memcpy(originalLower_, rhs.originalLower_, numberIntegers*sizeof(double)); originalUpper_ = new double [numberIntegers]; memcpy(originalUpper_, rhs.originalUpper_, numberIntegers*sizeof(double)); } else { originalLower_ = NULL; originalUpper_ = NULL; } delete [] bestSolution_; if (rhs.bestSolution_) { int numberColumns = model_->getNumCols(); bestSolution_ = new double [numberColumns]; memcpy(bestSolution_, rhs.bestSolution_, numberColumns*sizeof(double)); } else { bestSolution_ = NULL; } delete [] savedSolution_; if (rhs.savedSolution_) { int numberColumns = model_->getNumCols(); savedSolution_ = new double [numberColumns]; memcpy(savedSolution_, rhs.savedSolution_, numberColumns*sizeof(double)); } else { savedSolution_ = NULL; } } return *this; } // Clone CbcTree * CbcTreeVariable::clone() const { return new CbcTreeVariable(*this); } // Pass in solution (so can be used after heuristic) void CbcTreeVariable::passInSolution(const double * solution, double solutionValue) { int numberColumns = model_->getNumCols(); delete [] savedSolution_; savedSolution_ = new double [numberColumns]; memcpy(savedSolution_, solution, numberColumns*sizeof(double)); rhs_ = range_; // Check feasible int goodSolution = createCut(solution, cut_); if (goodSolution >= 0) { bestCutoff_ = CoinMin(solutionValue, model_->getCutoff()); } else { model_ = NULL; } } // Return the top node of the heap CbcNode * CbcTreeVariable::top() const { #ifdef CBC_DEBUG int smallest = 9999999; int largest = -1; double smallestD = 1.0e30; double largestD = -1.0e30; int n = nodes_.size(); for (int i = 0; i < n; i++) { int nn = nodes_[i]->nodeInfo()->nodeNumber(); double dd = nodes_[i]->objectiveValue(); largest = CoinMax(largest, nn); smallest = CoinMin(smallest, nn); largestD = CoinMax(largestD, dd); smallestD = CoinMin(smallestD, dd); } if (model_->messageHandler()->logLevel() > 1) { printf("smallest %d, largest %d, top %d\n", smallest, largest, nodes_.front()->nodeInfo()->nodeNumber()); printf("smallestD %g, largestD %g, top %g\n", smallestD, largestD, nodes_.front()->objectiveValue()); } #endif return nodes_.front(); } // Add a node to the heap void CbcTreeVariable::push(CbcNode * x) { if (typeCuts_ >= 0 && !nodes_.size() && searchType_ < 0) { startNode_ = model_->getNodeCount(); // save copy of node localNode_ = new CbcNode(*x); if (cut_.row().getNumElements()) { // Add to global cuts // we came in with solution model_->makeGlobalCut(cut_); if (model_->messageHandler()->logLevel() > 1) printf("initial cut - rhs %g %g\n", cut_.lb(), cut_.ub()); searchType_ = 1; } else { // stop on first solution searchType_ = 0; } startTime_ = static_cast (CoinCpuTime()); saveNumberSolutions_ = model_->getSolutionCount(); } nodes_.push_back(x); #ifdef CBC_DEBUG if (model_->messageHandler()->logLevel() > 0) printf("pushing node onto heap %d %x %x\n", x->nodeInfo()->nodeNumber(), x, x->nodeInfo()); #endif std::push_heap(nodes_.begin(), nodes_.end(), comparison_); } // Remove the top node from the heap void CbcTreeVariable::pop() { std::pop_heap(nodes_.begin(), nodes_.end(), comparison_); nodes_.pop_back(); } // Test if empty - does work if so bool CbcTreeVariable::empty() { if (typeCuts_ < 0) return !nodes_.size(); /* state - 0 iterating 1 subtree finished optimal solution for subtree found 2 subtree finished and no solution found 3 subtree exiting and solution found 4 subtree exiting and no solution found */ int state = 0; assert (searchType_ != 2); if (searchType_) { if (CoinCpuTime() - startTime_ > timeLimit_ || model_->getNodeCount() - startNode_ >= nodeLimit_) { state = 4; } } else { if (model_->getSolutionCount() > saveNumberSolutions_) { state = 4; } } if (!nodes_.size()) state = 2; if (!state) { return false; } // Finished this phase int numberColumns = model_->getNumCols(); if (model_->getSolutionCount() > saveNumberSolutions_) { if (model_->getCutoff() < bestCutoff_) { // Save solution if (!bestSolution_) bestSolution_ = new double [numberColumns]; memcpy(bestSolution_, model_->bestSolution(), numberColumns*sizeof(double)); bestCutoff_ = model_->getCutoff(); } state--; } // get rid of all nodes (safe even if already done) double bestPossibleObjective; cleanTree(model_, -COIN_DBL_MAX, bestPossibleObjective); double increment = model_->getDblParam(CbcModel::CbcCutoffIncrement) ; if (model_->messageHandler()->logLevel() > 1) printf("local state %d after %d nodes and %d seconds, new solution %g, best solution %g, k was %g\n", state, model_->getNodeCount() - startNode_, static_cast (CoinCpuTime()) - startTime_, model_->getCutoff() + increment, bestCutoff_ + increment, rhs_); saveNumberSolutions_ = model_->getSolutionCount(); bool finished = false; bool lastTry = false; switch (state) { case 1: // solution found and subtree exhausted if (rhs_ > 1.0e30) { finished = true; } else { // find global cut and reverse reverseCut(1); searchType_ = 1; // first false rhs_ = range_; // reset range nextStrong_ = false; // save best solution in this subtree memcpy(savedSolution_, model_->bestSolution(), numberColumns*sizeof(double)); } break; case 2: // solution not found and subtree exhausted if (rhs_ > 1.0e30) { finished = true; } else { // find global cut and reverse reverseCut(2); searchType_ = 1; // first false if (diversification_ < maxDiversification_) { if (nextStrong_) { diversification_++; // cut is valid so don't model_->setCutoff(1.0e50); searchType_ = 0; } nextStrong_ = true; rhs_ += range_ / 2; } else { // This will be last try (may hit max time) lastTry = true; if (!maxDiversification_) typeCuts_ = -1; // make sure can't start again model_->setCutoff(bestCutoff_); if (model_->messageHandler()->logLevel() > 1) printf("Exiting local search with current set of cuts\n"); rhs_ = 1.0e100; // Can now stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, savedGap_); } } break; case 3: // solution found and subtree not exhausted if (rhs_ < 1.0e30) { if (searchType_) { if (!typeCuts_ && refine_ && searchType_ == 1) { // We need to check we have best solution given these 0-1 values OsiSolverInterface * subSolver = model_->continuousSolver()->clone(); CbcModel * subModel = model_->subTreeModel(subSolver); CbcTree normalTree; subModel->passInTreeHandler(normalTree); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double * solution = model_->bestSolution(); int i; int numberColumns = model_->getNumCols(); for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = floor(solution[iColumn] + 0.5); if (!typeCuts_ && originalUpper_[i] - originalLower_[i] > 1.0) continue; // skip as not 0-1 if (originalLower_[i] == originalUpper_[i]) continue; subSolver->setColLower(iColumn, value); subSolver->setColUpper(iColumn, value); } subSolver->initialSolve(); // We can copy cutoff // But adjust subModel->setCutoff(model_->getCutoff() + model_->getDblParam(CbcModel::CbcCutoffIncrement) + 1.0e-6); subModel->setSolutionCount(0); assert (subModel->isProvenOptimal()); if (!subModel->typePresolve()) { subModel->branchAndBound(); if (subModel->status()) { model_->incrementSubTreeStopped(); } //printf("%g %g %g %g\n",subModel->getCutoff(),model_->getCutoff(), // subModel->getMinimizationObjValue(),model_->getMinimizationObjValue()); double newCutoff = subModel->getMinimizationObjValue() - subModel->getDblParam(CbcModel::CbcCutoffIncrement) ; if (subModel->getSolutionCount()) { if (!subModel->status()) assert (subModel->isProvenOptimal()); memcpy(model_->bestSolution(), subModel->bestSolution(), numberColumns*sizeof(double)); model_->setCutoff(newCutoff); } } else if (subModel->typePresolve() == 1) { CbcModel * model2 = subModel->integerPresolve(true); if (model2) { // Do complete search model2->branchAndBound(); // get back solution subModel->originalModel(model2, false); if (model2->status()) { model_->incrementSubTreeStopped(); } double newCutoff = model2->getMinimizationObjValue() - model2->getDblParam(CbcModel::CbcCutoffIncrement) ; if (model2->getSolutionCount()) { if (!model2->status()) assert (model2->isProvenOptimal()); memcpy(model_->bestSolution(), subModel->bestSolution(), numberColumns*sizeof(double)); model_->setCutoff(newCutoff); } delete model2; } else { // infeasible - could just be - due to cutoff } } else { // too dangerous at present assert (subModel->typePresolve() != 2); } if (model_->getCutoff() < bestCutoff_) { // Save solution if (!bestSolution_) bestSolution_ = new double [numberColumns]; memcpy(bestSolution_, model_->bestSolution(), numberColumns*sizeof(double)); bestCutoff_ = model_->getCutoff(); } delete subModel; } // we have done search to make sure best general solution searchType_ = 1; // Reverse cut weakly reverseCut(3, rhs_); } else { searchType_ = 1; // delete last cut deleteCut(cut_); } } else { searchType_ = 1; } // save best solution in this subtree memcpy(savedSolution_, model_->bestSolution(), numberColumns*sizeof(double)); nextStrong_ = false; rhs_ = range_; break; case 4: // solution not found and subtree not exhausted if (maxDiversification_) { if (nextStrong_) { // Reverse cut weakly reverseCut(4, rhs_); model_->setCutoff(1.0e50); diversification_++; searchType_ = 0; } else { // delete last cut deleteCut(cut_); searchType_ = 1; } nextStrong_ = true; rhs_ += range_ / 2; } else { // special case when using as heuristic // Reverse cut weakly if lb -infinity reverseCut(4, rhs_); // This will be last try (may hit max time0 lastTry = true; model_->setCutoff(bestCutoff_); if (model_->messageHandler()->logLevel() > 1) printf("Exiting local search with current set of cuts\n"); rhs_ = 1.0e100; // Can now stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, savedGap_); typeCuts_ = -1; } break; } if (rhs_ < 1.0e30 || lastTry) { int goodSolution = createCut(savedSolution_, cut_); if (goodSolution >= 0) { // Add to global cuts model_->makeGlobalCut(cut_); CbcRowCuts * global = model_->globalCuts(); int n = global->sizeRowCuts(); OsiRowCut * rowCut = global->rowCutPtr(n - 1); if (model_->messageHandler()->logLevel() > 1) printf("inserting cut - now %d cuts, rhs %g %g, cutspace %g, diversification %d\n", n, rowCut->lb(), rowCut->ub(), rhs_, diversification_); const OsiRowCutDebugger *debugger = model_->solver()->getRowCutDebuggerAlways() ; if (debugger) { if (debugger->invalidCut(*rowCut)) printf("ZZZZTree Global cut - cuts off optimal solution!\n"); } for (int i = 0; i < n; i++) { rowCut = global->rowCutPtr(i); if (model_->messageHandler()->logLevel() > 1) printf("%d - rhs %g %g\n", i, rowCut->lb(), rowCut->ub()); } } // put back node startTime_ = static_cast (CoinCpuTime()); startNode_ = model_->getNodeCount(); if (localNode_) { // save copy of node CbcNode * localNode2 = new CbcNode(*localNode_); // But localNode2 now owns cuts so swap //printf("pushing local node2 onto heap %d %x %x\n",localNode_->nodeNumber(), // localNode_,localNode_->nodeInfo()); nodes_.push_back(localNode_); localNode_ = localNode2; std::make_heap(nodes_.begin(), nodes_.end(), comparison_); } } return finished; } // We may have got an intelligent tree so give it one more chance void CbcTreeVariable::endSearch() { if (typeCuts_ >= 0) { // copy best solution to model int numberColumns = model_->getNumCols(); if (bestSolution_ && bestCutoff_ < model_->getCutoff()) { memcpy(model_->bestSolution(), bestSolution_, numberColumns*sizeof(double)); model_->setCutoff(bestCutoff_); // recompute objective value const double * objCoef = model_->getObjCoefficients(); double objOffset = 0.0; model_->continuousSolver()->getDblParam(OsiObjOffset, objOffset); // Compute dot product of objCoef and colSol and then adjust by offset double objValue = -objOffset; for ( int i = 0 ; i < numberColumns ; i++ ) objValue += objCoef[i] * bestSolution_[i]; model_->setMinimizationObjValue(objValue); } // Can now stop on gap model_->setDblParam(CbcModel::CbcAllowableGap, savedGap_); } } // Create cut int CbcTreeVariable::createCut(const double * solution, OsiRowCut & rowCut) { if (rhs_ > 1.0e20) return -1; OsiSolverInterface * solver = model_->solver(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); //const double * solution = solver->getColSolution(); //const double * objective = solver->getObjCoefficients(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // relax primalTolerance *= 1000.0; int numberRows = model_->getNumRows(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; // Check feasible double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); solver->getMatrixByCol()->times(solution, rowActivity) ; int goodSolution = 0; // check was feasible for (i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i] - primalTolerance) { goodSolution = -1; } else if (rowActivity[i] > rowUpper[i] + primalTolerance) { goodSolution = -1; } } delete [] rowActivity; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = solution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { goodSolution = -1; } } // zap cut if (goodSolution == 0) { // Create cut and get total gap CoinPackedVector cut; double rhs = rhs_; double maxValue = 0.0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = floor(solution[iColumn] + 0.5); if (!typeCuts_ && originalUpper_[i] - originalLower_[i] > 1.0) continue; // skip as not 0-1 if (originalLower_[i] == originalUpper_[i]) continue; double mu = 1.0 / (originalUpper_[i] - originalLower_[i]); if (value == originalLower_[i]) { rhs += mu * originalLower_[i]; cut.insert(iColumn, 1.0); maxValue += originalUpper_[i]; } else if (value == originalUpper_[i]) { rhs -= mu * originalUpper_[i]; cut.insert(iColumn, -1.0); maxValue += originalLower_[i]; } } if (maxValue < rhs - primalTolerance) { if (model_->messageHandler()->logLevel() > 1) printf("slack cut\n"); goodSolution = 1; } rowCut.setRow(cut); rowCut.setLb(-COIN_DBL_MAX); rowCut.setUb(rhs); rowCut.setGloballyValid(); if (model_->messageHandler()->logLevel() > 1) printf("Cut size: %i Cut rhs: %g\n", cut.getNumElements(), rhs); #ifdef CBC_DEBUG if (model_->messageHandler()->logLevel() > 0) { int k; for (k = 0; k < cut.getNumElements(); k++) { printf("%i %g ", cut.getIndices()[k], cut.getElements()[k]); if ((k + 1) % 5 == 0) printf("\n"); } if (k % 5 != 0) printf("\n"); } #endif return goodSolution; } else { if (model_->messageHandler()->logLevel() > 1) printf("Not a good solution\n"); return -1; } } // Other side of last cut branch void CbcTreeVariable::reverseCut(int state, double bias) { // find global cut CbcRowCuts * global = model_->globalCuts(); int n = global->sizeRowCuts(); int i; OsiRowCut * rowCut = NULL; for ( i = 0; i < n; i++) { rowCut = global->rowCutPtr(i); if (cut_ == *rowCut) { break; } } if (!rowCut) { // must have got here in odd way e.g. strong branching return; } if (rowCut->lb() > -1.0e10) return; // get smallest element double smallest = COIN_DBL_MAX; CoinPackedVector row = cut_.row(); for (int k = 0; k < row.getNumElements(); k++) smallest = CoinMin(smallest, fabs(row.getElements()[k])); if (!typeCuts_ && !refine_) { // Reverse cut very very weakly if (state > 2) smallest = 0.0; } // replace by other way if (model_->messageHandler()->logLevel() > 1) printf("reverseCut - changing cut %d out of %d, old rhs %g %g ", i, n, rowCut->lb(), rowCut->ub()); rowCut->setLb(rowCut->ub() + smallest - bias); rowCut->setUb(COIN_DBL_MAX); if (model_->messageHandler()->logLevel() > 1) printf("new rhs %g %g, bias %g smallest %g ", rowCut->lb(), rowCut->ub(), bias, smallest); const OsiRowCutDebugger *debugger = model_->solver()->getRowCutDebuggerAlways() ; if (debugger) { if (debugger->invalidCut(*rowCut)) printf("ZZZZTree Global cut - cuts off optimal solution!\n"); } } // Delete last cut branch void CbcTreeVariable::deleteCut(OsiRowCut & cut) { // find global cut CbcRowCuts * global = model_->globalCuts(); int n = global->sizeRowCuts(); int i; OsiRowCut * rowCut = NULL; for ( i = 0; i < n; i++) { rowCut = global->rowCutPtr(i); if (cut == *rowCut) { break; } } assert (i < n); // delete last cut if (model_->messageHandler()->logLevel() > 1) printf("deleteCut - deleting cut %d out of %d, rhs %g %g\n", i, n, rowCut->lb(), rowCut->ub()); global->eraseRowCut(i); } // Create C++ lines to get to current state void CbcTreeVariable::generateCpp( FILE * fp) { CbcTreeVariable other; fprintf(fp, "0#include \"CbcTreeVariable.hpp\"\n"); fprintf(fp, "5 CbcTreeVariable variableTree(cbcModel,NULL);\n"); if (range_ != other.range_) fprintf(fp, "5 variableTree.setRange(%d);\n", range_); if (typeCuts_ != other.typeCuts_) fprintf(fp, "5 variableTree.setTypeCuts(%d);\n", typeCuts_); if (maxDiversification_ != other.maxDiversification_) fprintf(fp, "5 variableTree.setMaxDiversification(%d);\n", maxDiversification_); if (timeLimit_ != other.timeLimit_) fprintf(fp, "5 variableTree.setTimeLimit(%d);\n", timeLimit_); if (nodeLimit_ != other.nodeLimit_) fprintf(fp, "5 variableTree.setNodeLimit(%d);\n", nodeLimit_); if (refine_ != other.refine_) fprintf(fp, "5 variableTree.setRefine(%s);\n", refine_ ? "true" : "false"); fprintf(fp, "5 cbcModel->passInTreeHandler(variableTree);\n"); } Cbc-2.8.12/src/CbcCutModifier.cpp0000644000076600007660000000217512131315050015062 0ustar coincoin// $Id: CbcCutModifier.cpp 1902 2013-04-10 16:58:16Z stefan $ // Copyright (C) 2003, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). //Edwin 11/25/09 carved out of CbcCutGenerator #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CbcConfig.h" #include #include #include #include #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #else #include "OsiSolverInterface.hpp" #endif #include "CbcModel.hpp" #include "CbcMessage.hpp" #include "CbcCutGenerator.hpp" #include "CbcBranchDynamic.hpp" #include "CglProbing.hpp" #include "CoinTime.hpp" #include "CbcCutModifier.hpp" // Default Constructor CbcCutModifier::CbcCutModifier() { } // Destructor CbcCutModifier::~CbcCutModifier () { } // Copy constructor CbcCutModifier::CbcCutModifier ( const CbcCutModifier & /*rhs*/) { } // Assignment operator CbcCutModifier & CbcCutModifier::operator=( const CbcCutModifier & rhs) { if (this != &rhs) { } return *this; } Cbc-2.8.12/src/CbcGenOsiParam.hpp0000644000076600007660000001306012131315050015015 0ustar coincoin/* Copyright (C) 2007, Lou Hafer, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). $Id: CbcGenOsiParam.hpp 1902 2013-04-10 16:58:16Z stefan $ */ /* This file is part of cbc-generic. */ #ifndef CbcOsiParam_H #define CbcOsiParam_H /* \file CbcGenOsiParam.hpp \brief Declarations for parameters that act on a OsiSolverInterface object. */ /* $Id: CbcGenOsiParam.hpp 1902 2013-04-10 16:58:16Z stefan $ */ /*! \class CbcOsiParam \brief Class for control parameters that act on a OsiSolverInterface object. Adds parameter type codes and push/pull functions to the generic parameter object. */ class CbcOsiParam : public CoinParam { public: /*! \name Subtypes */ //@{ /*! \enum CbcOsiParamCode \brief Enumeration for parameters that control an OsiSolverInterface object These are parameters that control the operation of an OsiSolverInterface object. CBCOSI_FIRSTPARAM and CBCOSI_LASTPARAM are markers to allow convenient separation of parameter groups. */ typedef enum { CBCOSI_FIRSTPARAM = CbcCbcParam::CBCCBC_LASTPARAM + 1, ALGORITHM, ALLSLACK, AUTOSCALE, BARRIER, BARRIERSCALE, BASISIN, BASISOUT, BIASLU, CHOLESKY, CRASH, CROSSOVER, DUALBOUND, DUALPIVOT, DUALSIMPLEX, DUALTOLERANCE, FAKEBOUND, GAMMA, IDIOT, KEEPNAMES, KKT, MAXITERATION, MAXHOTITS, NETLIB_BARRIER, NETLIB_DUAL, NETLIB_PRIMAL, NETWORK, OBJSCALE, PERTURBATION, PERTVALUE, PFI, PLUSMINUS, PRESOLVE, PRESOLVEOPTIONS, PRESOLVEPASS, PRIMALPIVOT, PRIMALSIMPLEX, PRIMALTOLERANCE, REALLY_SCALE, RESTORE, REVERSE, RHSSCALE, SAVE, SCALING, SLPVALUE, SOLVERLOGLEVEL, SPARSEFACTOR, SPECIALOPTIONS, SPRINT, TIGHTEN, CBCOSI_LASTPARAM } CbcOsiParamCode ; //@} /*! \name Constructors and Destructors Be careful how you specify parameters for the constructors! There's great potential for confusion. */ //@{ /*! \brief Default constructor */ CbcOsiParam() ; /*! \brief Constructor for a parameter with a double value The default value is 0.0. Be careful to clearly indicate that \p lower and \p upper are real (double) values to distinguish this constructor from the constructor for an integer parameter. */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, double lower, double upper, double dflt = 0.0, bool display = true) ; /*! \brief Constructor for a parameter with an integer value The default value is 0. */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, int lower, int upper, int dflt = 0, bool display = true) ; /*! \brief Constructor for a parameter with keyword values The string supplied as \p firstValue becomes the first keyword. Additional keywords can be added using appendKwd(). Keywords are numbered from zero. It's necessary to specify both the first keyword (\p firstValue) and the default keyword index (\p dflt) in order to distinguish this constructor from the string and action parameter constructors. */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, std::string firstValue, int dflt, bool display = true) ; /*! \brief Constructor for a string parameter The default string value must be specified explicitly to distinguish a string constructor from an action parameter constructor. */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, std::string dflt, bool display = true) ; /*! \brief Constructor for an action parameter */ CbcOsiParam(CbcOsiParamCode code, std::string name, std::string help, bool display = true) ; /*! \brief Copy constructor */ CbcOsiParam(const CbcOsiParam &orig) ; /*! \brief Clone */ CbcOsiParam *clone() ; /*! \brief Assignment */ CbcOsiParam &operator=(const CbcOsiParam &rhs) ; /*! \brief Destructor */ ~CbcOsiParam() ; //@} /*! \name Methods to query and manipulate a parameter object */ //@{ /*! \brief Get the parameter code */ inline CbcOsiParamCode paramCode() const { return (paramCode_) ; } /*! \brief Set the parameter code */ inline void setParamCode(CbcOsiParamCode code) { paramCode_ = code ; } /*! \brief Get the underlying OsiSolverInterface object */ inline OsiSolverInterface *obj() const { return (obj_) ; } /*! \brief Set the underlying OsiSolverInterace object */ inline void setObj(OsiSolverInterface *obj) { obj_ = obj ; } //@} private: /*! \name Data */ //@{ /// Parameter code CbcOsiParamCode paramCode_ ; /// OsiSolverInterface object OsiSolverInterface *obj_ ; //@} } ; /* Declare the utility functions. */ namespace CbcOsiParamUtils { void addCbcOsiParams(int &numParams, CoinParamVec ¶mVec, OsiSolverInterface *osi) ; void loadOsiParamObj(const CoinParamVec paramVec, CbcGenCtlBlk *ctlBlk) ; void setOsiSolverInterfaceDefaults(OsiSolverInterface *osi) ; int pushCbcOsiLogLevel(CoinParam *param) ; int pushCbcOsiInt(CoinParam *param) ; int pushCbcOsiDbl(CoinParam *param) ; int pushCbcOsiKwd(CoinParam *param) ; int pushCbcOsiHint(CoinParam *param) ; } #endif Cbc-2.8.12/depcomp0000755000076600007660000003710011405215312012321 0ustar coincoin#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2005-07-09.11 # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test -f "$tmpdepfile"; then : else stripped=`echo "$stripped" | sed 's,^.*/,,'` tmpdepfile="$stripped.u" fi if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mecanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: Cbc-2.8.12/scripts/0000755000076600007660000000000012377555231012452 5ustar coincoinCbc-2.8.12/scripts/parse.awk0000644000076600007660000001041212101340057014245 0ustar coincoin#!/usr/bin/awk -f #* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * #* * #* This file is part of the test engine for MIPLIB2010 * #* * #* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * # $Id: parse.awk 1854 2013-01-28 00:02:55Z stefan $ function abs(x) { return x < 0 ? -x : x; } function min(x,y) { return (x) < (y) ? (x) : (y); } function max(x,y) { return (x) > (y) ? (x) : (y); } BEGIN { printf("----------------------------+----------------+----------------+------+-------+-------+--------+---------\n"); printf("Name | Dual Bound | Primal Bound | Gap%% | Nodes | Time | Status | Solution \n"); printf("----------------------------+----------------+----------------+------+-------+-------+--------+---------\n"); infty = +1e+20; eps = 1e-04; largegap = 1e+04; # initialize summary data nsolved = 0; nstopped = 0; nfailed = 0; # initialize data to be set in parse_.awk solver = "?"; solverversion = "?"; solverremark = ""; } # instance name /^@01/ { n = split ($2, a, "/"); m = split(a[n], b, "."); prob = b[1]; if( b[m] == "gz" || b[m] == "z" || b[m] == "GZ" || b[m] == "Z" ) m--; for( i = 2; i < m; ++i ) prob = prob "." b[i]; # initialize data to be set in parse.awk timelimit = 0; starttime = 0.0; endtime = 0.0; time = 0.0; # initialize data to be set parse_.awk bbnodes = 0; pb = +infty; db = -infty; aborted = 1; timeout = 0; solstatus = "none"; read_error = 0; } # time /@03/ { starttime = $2; } /@04/ { endtime = $2; } /@05/ { timelimit = $2; } # solution status /Read SOL:/ { solstatus = "--"; } /Check SOL:/ { intcheck = $4; conscheck = $6; objcheck = $8; if( intcheck && conscheck && objcheck ) solstatus = "ok"; else solstatus = "fail"; } /^=ready=/ { # measure wallclock time externaly rounded up to the next second time = max(1, endtime - starttime); if( timelimit > 0 ) { # report time limit as time for instances stopped by time limit if( timeout ) time = timelimit; # report time limit as time for aborted instances if( aborted ) time = timelimit; # report time limit as time for instances that exceeded the time limit but did not stop time = min(time, timelimit); } # determine solving status status = ""; if( aborted && !read_error) status = "abort"; else if (aborted && read_error) status = "noread"; else if( timeout ) status = "stopped"; else status = "ok"; # determine overall status from solving status and solution status: # instance solved correctly (including case that no solution was found) if( status == "ok" && (solstatus == "ok" || solstatus == "--") ) nsolved++; # incorrect solving process or infeasible solution (including errors with solution checker) else if( status == "abort" || (solstatus == "fail" || solstatus == "error") ) nfailed++; # stopped due to imposed limits else if ( status == "stopped" ) nstopped++; else nnoread++; # compute gap temp = pb; pb = 1.0*temp; temp = db; db = 1.0*temp; if( abs(pb - db) < eps && pb < +infty ) gap = 0.0; else if( abs(db) < eps ) gap = -1.0; else if( pb*db < 0.0 ) gap = -1.0; else if( abs(db) >= +infty ) gap = -1.0; else if( abs(pb) >= +infty ) gap = -1.0; else gap = 100.0*abs((pb-db)/db); if( gap < 0.0 ) gapstr = " --"; else if( gap < largegap ) gapstr = sprintf("%6.1f", gap); else gapstr = " Large"; printf("%-28s %16.9g %16.9g %6s %7d %7d %8s %9s\n", prob, db, pb, gapstr, bbnodes, time, status, solstatus); } END { printf("----------------------------+----------------+----------------+------+-------+-------+--------+---------\n"); printf("\n"); printf("solved/stopped/noread/failed: %d/%d/%d/%d\n", nsolved, nstopped, nnoread, nfailed); printf("\n"); printf("@02 timelimit: %g\n", timelimit); printf("@01 %s(%s)%s\n", solver, solverversion, solverremark); }Cbc-2.8.12/scripts/run.sh0000755000076600007660000000664012101340057013602 0ustar coincoin#* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * #* * #* This file is part of the test engine for MIPLIB2010 * #* * #* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * # $Id: run.sh 1854 2013-01-28 00:02:55Z stefan $ SHELL=$1 BINNAME=$2 TSTNAME=$3 TIMELIMIT=$4 HARDMEMLIMIT=$5 THREADS=$6 # construct paths MIPLIBPATH=`pwd` BINPATH=$MIPLIBPATH/bin CHECKERPATH=$MIPLIBPATH/checker RESULTSPATH=$MIPLIBPATH/results SCRIPTPATH=$MIPLIBPATH/scripts TSTPATH=$MIPLIBPATH/testset # check if the solver link (binary) exists if test ! -e $BINPATH/$BINNAME then echo "ERROR: solver link <$BINNAME> does not exist in folder; see bin/README" exit; fi # check if the test set file/link exists if test ! -e $TSTPATH/$TSTNAME.test then echo "ERROR: test set file/link <$TSTNAME.test> does not exist in folder" exit; fi # grep solver name SOLVER=`echo $BINNAME | sed 's/\([a-zA-Z0-9_-]*\).*/\1/g'` # check if the result folder exist. if not create the result folder if test ! -e $RESULTSPATH then mkdir $RESULTSPATH fi # construct name of output, results, and temporary solution file BASENAME=$RESULTSPATH/$TSTNAME.$BINNAME OUTFILE=$BASENAME.out RESFILE=$BASENAME.res SOLFILE=$BASENAME.sol # absolut tolerance for checking linear constraints and objective value LINTOL=1e-4 # absolut tolerance for checking integrality constraints INTTOL=1e-4 # Note that the MIP gap (gap between primal and dual solution) is not # uniqly defined through all solvers. For example, there is a difference # between SCIP and CPLEX. All solver, however, have the some behaviour in # case of a MIP gap of 0.0. MIPGAP=0.0 # post system information and current time into the output file uname -a > $OUTFILE date >> $OUTFILE # convert hard memory limit to kilo bytes and post it into the output file HARDMEMLIMIT=`expr $HARDMEMLIMIT \* 1024` echo "hard mem limit: $HARDMEMLIMIT k" >> $OUTFILE # loop over all instance names which are listed in the test set file name for i in `cat $TSTPATH/$TSTNAME.test` do # check if the current instance exists if test -f $i then echo @01 $i =========== echo ----------------------------- date echo ----------------------------- TIMESTART=`date +"%s"` echo @03 $TIMESTART $SHELL -c " ulimit -v $HARDMEMLIMIT k; ulimit -f 2000000; $SCRIPTPATH/run_$SOLVER.sh $SOLVER $BINPATH/$BINNAME $i $TIMELIMIT $SOLFILE $THREADS $MIPGAP" echo TIMEEND=`date +"%s"` echo @04 $TIMEEND echo @05 $TIMELIMIT # check if a solution file was written if test -e $SOLFILE then # check if the link to the solution checker exists if test -f "$CHECKERPATH/bin/solchecker" then echo $SHELL -c " $CHECKERPATH/bin/solchecker $i $SOLFILE $LINTOL $INTTOL" echo else echo WARNING: solution cannot be checked because solution checker is missing fi fi echo ----------------------------- date echo ----------------------------- echo echo =ready= else echo @02 FILE NOT FOUND: $i =========== fi done 2>&1 | tee -a $OUTFILE date >> $OUTFILE if test -e $SOLFILE then rm $SOLFILE fi awk -f $SCRIPTPATH/parse.awk -f $SCRIPTPATH/parse_$SOLVER.awk $OUTFILE | tee $RESFILE Cbc-2.8.12/scripts/parse_cbc_sol.awk0000755000076600007660000000132612101340057015740 0ustar coincoin#!/usr/bin/awk -f #* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * #* * #* This file is part of the test engine for MIPLIB2010 * #* * #* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /^Stopped/ { if( NF > 7 ) exit; printf ("=obj= %s \n", $7); next; } /^Optimal/ { printf ("=obj= %s \n", $5); next; } /^Infeasible/ { printf ("=infeas= \n"); exit; } /^Integer/ { if( $2 == "infeasible") printf ("=infeas= \n"); exit; } //{ printf ("%s %s \n", $2, $3); } Cbc-2.8.12/scripts/get.miplib20100000755000076600007660000000033312101340057014713 0ustar coincoin#!/bin/bash for file in `cat miplib2010-candidates.test` do if test -f $file then echo $file exists else cd miplib2010-candidates/ wget http://miplib.zib.de/miplib2010/$file cd .. fi doneCbc-2.8.12/scripts/run_cbc.sh0000755000076600007660000000360112101340057014403 0ustar coincoin#* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * #* * #* This file is part of the test engine for MIPLIB2010 * #* * #* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * # $Id: run_cbc.sh 1854 2013-01-28 00:02:55Z stefan $ SOLVER=$1 BINNAME=$2 NAME=$3 TIMELIMIT=$4 SOLFILE=$5 THREADS=$6 MIPGAP=$7 TMPFILE=results/check.$SOLVER.tmp if test $THREADS != 0 then $BINNAME -import $NAME -sec $TIMELIMIT -threads $THREADS -ratio $MIPGAP -solve -solution $SOLFILE else $BINNAME -import $NAME -sec $TIMELIMIT -ratio $MIPGAP -solve -solution $SOLFILE fi if test -f $SOLFILE then # translate CBC solution format into format for solution checker. # The SOLFILE format is a very simple format where in each line # we have a pair, separated by spaces. # A variable name of =obj= is used to store the objective value # of the solution, as computed by the solver. A variable name of # =infeas= can be used to indicate that an instance is infeasible. awk ' BEGIN{ infeasible = 0; nointsol = 0; } ($3 != "objective" && $3 != "gap" && $3 != "time" && $2 != "infeasible"){ if (!infeasible){ printf ("%s %s \n", $2, $3); } } ($3 == "objective" && $1 != "Infeasible" && $2 != "infeasible"){ printf ("=obj= %s \n", $5); } ($3 == "gap"){ printf ("=obj= %s \n", $8); } ($3 == "time"){ if ($5 == "integer"){ printf ("=nointsol= \n"); nointsol = 1; }else{ printf ("=obj= %s \n", $7); } } ($1 == "Infeasible" || $2 == "infeasible"){ printf ("=infeas= \n"); infeasible = 1; }' $SOLFILE | tee $TMPFILE mv $TMPFILE $SOLFILE fi Cbc-2.8.12/scripts/parse_cbc.awk0000644000076600007660000000304012101340057015053 0ustar coincoin#!/usr/bin/awk -f #* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * #* * #* This file is part of the test engine for MIPLIB2010 * #* * #* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * # $Id: parse_cbc.awk 1854 2013-01-28 00:02:55Z stefan $ # set all solver specific data: # solver ["?"] # solverversion ["?"] # lps ["none"] # lpsversion ["-"] # bbnodes [0] # db [-infty] # pb [+infty] # aborted [1] # timeout [0] # The solver name BEGIN { solver = "CBC"; gap = 0; } # The solver version /^Version:/ { version = $2; } /^Revision Number:/ { revision = $3; solverversion = version "-" revision } # The results /^Result/ { if ($3 == "Optimal"){ if ($7 == "gap"){ gap = 1; }else{ gap = 0 } aborted = 0; timeout = 0; } if ($5 == "infeasible"){ pb = +infty; db = +infty; aborted = 0; timeout = 0; }else if ($5 == "unbounded"){ pb = -infty; db = -infty; aborted = 0; timeout = 0; }else if ($3 == "Stopped"){ if ($5 == "time"){ timeout = 1; aborted = 0; } }else if ($3 == "Difficulties"){ aborted = 1 } } /^Objective value:/ { pb = $3; if (!gap){ db = pb; } } /^Lower bound:/ { db = $3; } /^Enumerated nodes:/ { bbnodes = $3 } /errors on input/ { read_error = 1; }Cbc-2.8.12/MSVisualStudio/0000755000076600007660000000000012377555231013656 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/0000755000076600007660000000000012377555231014264 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/Cbc.sln0000644000076600007660000002515411645033041015463 0ustar coincoinMicrosoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cbcExamplesSample2", "cbcExamplesSample2\cbcExamplesSample2.vcxproj", "{4C0B8243-2876-4C92-B6CB-2472B0571CC3}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cbc", "cbc\cbc.vcxproj", "{E2294708-C5BA-460A-B0A7-060A4023684A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCbc", "libCbc\libCbc.vcxproj", "{363BA154-FEC9-4E1E-BC23-93CEC58AB785}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCgl", "..\..\..\Cgl\MSVisualStudio\v10\libCgl\libCgl.vcxproj", "{DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libClp", "..\..\..\Clp\MSVisualStudio\v10\libClp\libClp.vcxproj", "{4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCoinUtils", "..\..\..\CoinUtils\MSVisualStudio\v10\libCoinUtils\libCoinUtils.vcxproj", "{C4867F15-438D-4FF8-8388-62FBAAA9786C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libOsi", "..\..\..\Osi\MSVisualStudio\v10\libOsi\libOsi.vcxproj", "{7D98E2CB-876E-4F75-9F71-77D3FE87E149}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cbcCInterfaceDll", "cbcCInterfaceDll\cbcCInterfaceDll.vcxproj", "{F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cbcCSosDllSample", "cbcCSosDllSample\cbcCSosDllSample.vcxproj", "{8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCbcSolver", "libCbcSolver\libCbcSolver.vcxproj", "{71DA4595-E8A7-4B21-A00A-D96D29D11E3E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libOsiClp", "..\..\..\Clp\MSVisualStudio\v10\libOsiClp\libOsiClp.vcxproj", "{02D45875-A8CF-41B9-990B-3699C0ECFE10}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libOsiCbc", "libOsiCbc\libOsiCbc.vcxproj", "{431ED9C6-FDF6-4836-8B33-BE4EC5378640}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OsiCbcUnitTest", "OsiCbcUnitTest\OsiCbcUnitTest.vcxproj", "{BB058D80-D376-4F0F-87F7-E4760BC2C84D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libOsiCommonTest", "..\..\..\Osi\MSVisualStudio\v10\libOsiCommonTest\libOsiCommonTest.vcxproj", "{109D6E6F-6D91-460F-86AE-DF27400E09A9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Debug|Win32.ActiveCfg = Debug|Win32 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Debug|Win32.Build.0 = Debug|Win32 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Debug|x64.ActiveCfg = Debug|x64 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Debug|x64.Build.0 = Debug|x64 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Release|Win32.ActiveCfg = Release|Win32 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Release|Win32.Build.0 = Release|Win32 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Release|x64.ActiveCfg = Release|x64 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Release|x64.Build.0 = Release|x64 {E2294708-C5BA-460A-B0A7-060A4023684A}.Debug|Win32.ActiveCfg = Debug|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Debug|Win32.Build.0 = Debug|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Debug|x64.ActiveCfg = Debug|x64 {E2294708-C5BA-460A-B0A7-060A4023684A}.Debug|x64.Build.0 = Debug|x64 {E2294708-C5BA-460A-B0A7-060A4023684A}.Release|Win32.ActiveCfg = Release|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Release|Win32.Build.0 = Release|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Release|x64.ActiveCfg = Release|x64 {E2294708-C5BA-460A-B0A7-060A4023684A}.Release|x64.Build.0 = Release|x64 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Debug|Win32.ActiveCfg = Debug|Win32 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Debug|Win32.Build.0 = Debug|Win32 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Debug|x64.ActiveCfg = Debug|x64 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Debug|x64.Build.0 = Debug|x64 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Release|Win32.ActiveCfg = Release|Win32 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Release|Win32.Build.0 = Release|Win32 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Release|x64.ActiveCfg = Release|x64 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Release|x64.Build.0 = Release|x64 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Debug|Win32.ActiveCfg = Debug|Win32 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Debug|Win32.Build.0 = Debug|Win32 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Debug|x64.ActiveCfg = Debug|x64 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Debug|x64.Build.0 = Debug|x64 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Release|Win32.ActiveCfg = Release|Win32 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Release|Win32.Build.0 = Release|Win32 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Release|x64.ActiveCfg = Release|x64 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Release|x64.Build.0 = Release|x64 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Debug|Win32.ActiveCfg = Debug|Win32 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Debug|Win32.Build.0 = Debug|Win32 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Debug|x64.ActiveCfg = Debug|x64 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Debug|x64.Build.0 = Debug|x64 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Release|Win32.ActiveCfg = Release|Win32 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Release|Win32.Build.0 = Release|Win32 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Release|x64.ActiveCfg = Release|x64 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Release|x64.Build.0 = Release|x64 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Debug|Win32.ActiveCfg = Debug|Win32 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Debug|Win32.Build.0 = Debug|Win32 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Debug|x64.ActiveCfg = Debug|x64 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Debug|x64.Build.0 = Debug|x64 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Release|Win32.ActiveCfg = Release|Win32 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Release|Win32.Build.0 = Release|Win32 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Release|x64.ActiveCfg = Release|x64 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Release|x64.Build.0 = Release|x64 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Debug|Win32.ActiveCfg = Debug|Win32 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Debug|Win32.Build.0 = Debug|Win32 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Debug|x64.ActiveCfg = Debug|x64 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Debug|x64.Build.0 = Debug|x64 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Release|Win32.ActiveCfg = Release|Win32 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Release|Win32.Build.0 = Release|Win32 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Release|x64.ActiveCfg = Release|x64 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Release|x64.Build.0 = Release|x64 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}.Debug|Win32.ActiveCfg = Debug|Win32 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}.Debug|x64.ActiveCfg = Debug|x64 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}.Release|Win32.ActiveCfg = Release|Win32 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}.Release|x64.ActiveCfg = Release|x64 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}.Debug|Win32.ActiveCfg = Debug|Win32 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}.Debug|x64.ActiveCfg = Debug|x64 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}.Release|Win32.ActiveCfg = Release|Win32 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}.Release|x64.ActiveCfg = Release|x64 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Debug|Win32.ActiveCfg = Debug|Win32 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Debug|Win32.Build.0 = Debug|Win32 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Debug|x64.ActiveCfg = Debug|x64 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Debug|x64.Build.0 = Debug|x64 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Release|Win32.ActiveCfg = Release|Win32 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Release|Win32.Build.0 = Release|Win32 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Release|x64.ActiveCfg = Release|x64 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Release|x64.Build.0 = Release|x64 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Debug|Win32.ActiveCfg = Debug|Win32 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Debug|Win32.Build.0 = Debug|Win32 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Debug|x64.ActiveCfg = Debug|x64 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Debug|x64.Build.0 = Debug|x64 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Release|Win32.ActiveCfg = Release|Win32 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Release|Win32.Build.0 = Release|Win32 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Release|x64.ActiveCfg = Release|x64 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Release|x64.Build.0 = Release|x64 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Debug|Win32.ActiveCfg = Debug|Win32 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Debug|Win32.Build.0 = Debug|Win32 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Debug|x64.ActiveCfg = Debug|x64 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Debug|x64.Build.0 = Debug|x64 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Release|Win32.ActiveCfg = Release|Win32 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Release|Win32.Build.0 = Release|Win32 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Release|x64.ActiveCfg = Release|x64 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Release|x64.Build.0 = Release|x64 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Debug|Win32.ActiveCfg = Debug|Win32 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Debug|Win32.Build.0 = Debug|Win32 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Debug|x64.ActiveCfg = Debug|x64 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Debug|x64.Build.0 = Debug|x64 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Release|Win32.ActiveCfg = Release|Win32 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Release|Win32.Build.0 = Release|Win32 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Release|x64.ActiveCfg = Release|x64 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Release|x64.Build.0 = Release|x64 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Debug|Win32.ActiveCfg = Debug|Win32 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Debug|Win32.Build.0 = Debug|Win32 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Debug|x64.ActiveCfg = Debug|x64 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Debug|x64.Build.0 = Debug|x64 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Release|Win32.ActiveCfg = Release|Win32 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Release|Win32.Build.0 = Release|Win32 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Release|x64.ActiveCfg = Release|x64 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal Cbc-2.8.12/MSVisualStudio/v10/cbcCInterfaceDll/0000755000076600007660000000000012377555231017373 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/cbcCInterfaceDll/cbcCInterfaceDll.vcxproj0000644000076600007660000003421312131315050024077 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB} cbcCInterfaceDll Win32Proj DynamicLibrary DynamicLibrary DynamicLibrary DynamicLibrary <_ProjectFileVersion>10.0.30319.1 true false true false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..\..\Cbc\src\;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_WINDOWS;_USRDLL;CBCCINTERFACEDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 EditAndContinue libOsiClp.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).dll $(OutDir);%(AdditionalLibraryDirectories) true $(OutDir)cbcCInterfaceDll.pdb Windows false $(OutDir)cbcCInterfaceDll.lib MachineX86 ..\..\..\..\Cbc\src\;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_WINDOWS;_USRDLL;CBCCINTERFACEDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase libOsiClp.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).dll $(OutDir);%(AdditionalLibraryDirectories) true Windows true true false $(OutDir)cbcCInterfaceDll.lib MachineX86 X64 Disabled ..\..\..\..\Cbc\src\;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_WINDOWS;_USRDLL;CBCCINTERFACEDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 ProgramDatabase libOsiClp.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).dll $(OutDir);%(AdditionalLibraryDirectories) true $(OutDir)cbcCInterfaceDll.pdb Windows false $(OutDir)cbcCInterfaceDll.lib MachineX64 X64 ..\..\..\..\Cbc\src\;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_WINDOWS;_USRDLL;CBCCINTERFACEDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase libOsiClp.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).dll $(OutDir);%(AdditionalLibraryDirectories) true Windows true true false $(OutDir)cbcCInterfaceDll.lib MachineX64 {dbea3904-f0b8-408a-9e1a-6497febe8c42} false {4f8f7d1c-3a9e-444d-8ee9-77f33fa05994} false {02d45875-a8cf-41b9-990b-3699c0ecfe10} false {c4867f15-438d-4ff8-8388-62fbaaa9786c} false {7d98e2cb-876e-4f75-9f71-77d3fe87e149} false {363ba154-fec9-4e1e-bc23-93cec58ab785} false Cbc-2.8.12/MSVisualStudio/v10/cbcExamplesSample2/0000755000076600007660000000000012377555231017736 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/cbcExamplesSample2/cbcExamplesSample2.vcxproj0000644000076600007660000006321612131315050025012 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {4C0B8243-2876-4C92-B6CB-2472B0571CC3} cbcExamplesSample2 Application Application Application Application <_ProjectFileVersion>10.0.30319.1 false false false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/cbcExamplesSample2.tlb ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample";%(PreprocessorDefinitions) _DEBUG;%(PreprocessorDefinitions) 0x0409 libCbcSolver.lib;libCbc.lib;libCgl.lib;libOsiClp.lib;libOsi.lib;libClp.lib;libCoinUtils.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).exe true $(OutDir);%(AdditionalLibraryDirectories) true .\Debug/cbcExamplesSample2.pdb Console false MachineX86 false X64 .\Debug/cbcExamplesSample2.tlb ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample";%(PreprocessorDefinitions) _DEBUG;%(PreprocessorDefinitions) 0x0409 libCbcSolver.lib;libCbc.lib;libCgl.lib;libOsiClp.lib;libOsi.lib;libClp.lib;libCoinUtils.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).exe true $(OutDir);%(AdditionalLibraryDirectories) true .\Debug/cbcExamplesSample2.pdb Console false MachineX64 false .\Release/cbcExamplesSample2.tlb ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample";%(PreprocessorDefinitions) NDEBUG;_NDEBUG;%(PreprocessorDefinitions) 0x0409 libCbcSolver.lib;libCbc.lib;libCgl.lib;libOsiClp.lib;libOsi.lib;libClp.lib;libCoinUtils.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).exe true $(OutDir);%(AdditionalLibraryDirectories) .\Release/cbcExamplesSample2.pdb Console false MachineX86 false X64 .\Release/cbcExamplesSample2.tlb ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample";%(PreprocessorDefinitions) NDEBUG;_NDEBUG;%(PreprocessorDefinitions) 0x0409 libCbcSolver.lib;libCbc.lib;libCgl.lib;libOsiClp.lib;libOsi.lib;libClp.lib;libCoinUtils.lib;%(AdditionalDependencies) $(OutDir)$(ProjectName).exe true $(OutDir);%(AdditionalLibraryDirectories) .\Release/cbcExamplesSample2.pdb Console false MachineX64 false Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks $(IntDir) $(IntDir)vc90.pdb Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks $(IntDir) $(IntDir)vc90.pdb MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) $(IntDir) $(IntDir)vc90.pdb MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) $(IntDir) $(IntDir)vc90.pdb Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks $(IntDir) $(IntDir)vc90.pdb Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks $(IntDir) $(IntDir)vc90.pdb MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) $(IntDir) $(IntDir)vc90.pdb MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) $(IntDir) $(IntDir)vc90.pdb Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks $(IntDir) $(IntDir)vc90.pdb Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks $(IntDir) $(IntDir)vc90.pdb MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) $(IntDir) $(IntDir)vc90.pdb MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) $(IntDir) $(IntDir)vc90.pdb {dbea3904-f0b8-408a-9e1a-6497febe8c42} false {4f8f7d1c-3a9e-444d-8ee9-77f33fa05994} false {02d45875-a8cf-41b9-990b-3699c0ecfe10} false {c4867f15-438d-4ff8-8388-62fbaaa9786c} false {7d98e2cb-876e-4f75-9f71-77d3fe87e149} false {363ba154-fec9-4e1e-bc23-93cec58ab785} false Cbc-2.8.12/MSVisualStudio/v10/libOsiCbc/0000755000076600007660000000000012377555231016115 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/libOsiCbc/libOsiCbc.vcxproj0000644000076600007660000002132712131315050021345 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {431ED9C6-FDF6-4836-8B33-BE4EC5378640} libOsiCbc ManagedCProj StaticLibrary StaticLibrary StaticLibrary StaticLibrary <_ProjectFileVersion>10.0.30319.1 AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset ..\..\..\..\Osi\src\Osi;..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\src;%(AdditionalIncludeDirectories) WIN32;_DEBUG;%(PreprocessorDefinitions) ..\..\..\..\Osi\src\Osi;..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\src;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;%(PreprocessorDefinitions) Level3 ProgramDatabase X64 ..\..\..\..\Osi\src\Osi;..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\src;%(AdditionalIncludeDirectories) WIN32;_DEBUG;%(PreprocessorDefinitions) Level3 ProgramDatabase X64 ..\..\..\..\Osi\src\Osi;..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\src;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;%(PreprocessorDefinitions) Level3 ProgramDatabase Default true true true true true true Cbc-2.8.12/MSVisualStudio/v10/libCbc/0000755000076600007660000000000012377555231015442 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/libCbc/libCbc.vcxproj0000644000076600007660000020771512136524567020252 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {363BA154-FEC9-4E1E-BC23-93CEC58AB785} libCbc StaticLibrary StaticLibrary StaticLibrary StaticLibrary <_ProjectFileVersion>10.0.30319.1 AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglGMI;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;..\..\..\..\Cgl\src\CglRedSplit2;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_LIB;USE_CBCCONFIG;COIN_NO_CLP_MESSAGE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) _DEBUG;%(PreprocessorDefinitions) 0x0409 true ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglGMI;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;..\..\..\..\Cgl\src\CglRedSplit2;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;WIN32;_LIB;USE_CBCCONFIG;COIN_NO_CLP_MESSAGE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true true NDEBUG;_NDEBUG;%(PreprocessorDefinitions) 0x0409 true X64 ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglGMI;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;..\..\..\..\Cgl\src\CglRedSplit2;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_LIB;USE_CBCCONFIG;COIN_NO_CLP_MESSAGE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true EnableFastChecks ProgramDatabase false _DEBUG;%(PreprocessorDefinitions) 0x0409 true X64 Default ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglGMI;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;..\..\..\..\Cgl\src\CglRedSplit2;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;WIN32;_LIB;USE_CBCCONFIG;COIN_NO_CLP_MESSAGE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) NDEBUG;_NDEBUG;%(PreprocessorDefinitions) 0x0409 true Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) Cbc-2.8.12/MSVisualStudio/v10/cbc/0000755000076600007660000000000012377555231015013 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/cbc/cbc.vcxproj0000644000076600007660000004033512131315050017141 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {E2294708-C5BA-460A-B0A7-060A4023684A} cbc Application Application Application Application <_ProjectFileVersion>10.0.30319.1 false false false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/cbcSolve.tlb ..\..\..\src;..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Osi\src\Osi;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) _DEBUG;%(PreprocessorDefinitions) 0x0409 libCbcSolver.lib;libCbc.lib;libCgl.lib;libOsiClp.lib;libOsi.lib;libClp.lib;libCoinUtils.lib;%(AdditionalDependencies) true $(OutDir);%(AdditionalLibraryDirectories) true Console false MachineX86 false .\Release/cbcSolve.tlb ..\..\..\src;..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Osi\src\Osi;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true Default NDEBUG;_NDEBUG;%(PreprocessorDefinitions) 0x0409 libCbcSolver.lib;libCbc.lib;libCgl.lib;libOsiClp.lib;libOsi.lib;libClp.lib;libCoinUtils.lib;%(AdditionalDependencies) true $(OutDir);%(AdditionalLibraryDirectories) Console false MachineX86 false X64 .\Debug/cbcSolve.tlb ..\..\..\src;..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Osi\src\Osi;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0409 libCbcSolver.lib;libCbc.lib;libCgl.lib;libOsiClp.lib;libOsi.lib;libClp.lib;libCoinUtils.lib;%(AdditionalDependencies) true $(OutDir);%(AdditionalLibraryDirectories) true Console false MachineX64 false X64 .\Release/cbcSolve.tlb ..\..\..\src;..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Osi\src\Osi;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) NDEBUG;_NDEBUG;%(PreprocessorDefinitions) 0x0409 libCbcSolver.lib;libCbc.lib;libCgl.lib;libOsiClp.lib;libOsi.lib;libClp.lib;libCoinUtils.lib;%(AdditionalDependencies) true $(OutDir);%(AdditionalLibraryDirectories) Console false MachineX64 false Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) {dbea3904-f0b8-408a-9e1a-6497febe8c42} false {4f8f7d1c-3a9e-444d-8ee9-77f33fa05994} false {02d45875-a8cf-41b9-990b-3699c0ecfe10} false {c4867f15-438d-4ff8-8388-62fbaaa9786c} false {7d98e2cb-876e-4f75-9f71-77d3fe87e149} false {71da4595-e8a7-4b21-a00a-d96d29d11e3e} false {363ba154-fec9-4e1e-bc23-93cec58ab785} false Cbc-2.8.12/MSVisualStudio/v10/OsiCbcUnitTest/0000755000076600007660000000000012377555231017126 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/OsiCbcUnitTest/OsiCbcUnitTest.vcxproj0000644000076600007660000003347112131315050023372 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {BB058D80-D376-4F0F-87F7-E4760BC2C84D} OsiCbcUnitTest Win32Proj Application Application Application Application <_ProjectFileVersion>10.0.30319.1 true false true false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset ..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Osi\src\Osi;..\..\..\src\OsiCbc;..\..\..\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\OsiCommonTest;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_CONSOLE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample";NETLIBDIR="..\\..\\..\\..\\Data\\Netlib";MIPLIBDIR="..\\..\\..\\..\\Data\\miplib3";%(PreprocessorDefinitions) libCoinUtils.lib;libOsi.lib;libOsiCommonTest.lib;libClp.lib;libOsiClp.lib;libCgl.lib;libCbc.lib;libOsiCbc.lib;libOsiClp.lib;libClp.lib;libOsi.lib;libOsiCommonTest.lib;libCoinUtils.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) true Console MachineX86 false ..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Osi\src\Osi;..\..\..\src\OsiCbc;..\..\..\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\OsiCommonTest;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample";NETLIBDIR="..\\..\\..\\..\\Data\\Netlib";MIPLIBDIR="..\\..\\..\\..\\Data\\miplib3";%(PreprocessorDefinitions) libCoinUtils.lib;libOsi.lib;libOsiCommonTest.lib;libClp.lib;libOsiClp.lib;libCgl.lib;libCbc.lib;libOsiCbc.lib;libOsiClp.lib;libClp.lib;libOsi.lib;libOsiCommonTest.lib;libCoinUtils.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) true Console true true MachineX86 false X64 ..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Osi\src\Osi;..\..\..\src\OsiCbc;..\..\..\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\OsiCommonTest;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_CONSOLE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample";NETLIBDIR="..\\..\\..\\..\\Data\\Netlib";MIPLIBDIR="..\\..\\..\\..\\Data\\miplib3";%(PreprocessorDefinitions) libCoinUtils.lib;libOsi.lib;libOsiCommonTest.lib;libClp.lib;libOsiClp.lib;libCgl.lib;libCbc.lib;libOsiCbc.lib;libCgl.lib;libOsiClp.lib;libClp.lib;libOsi.lib;libOsiCommonTest.lib;libCoinUtils.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) true Console MachineX64 false X64 ..\..\..\..\BuildTools\headers;..\..\..\..\CoinUtils\src;..\..\..\..\Osi\src\Osi;..\..\..\src\OsiCbc;..\..\..\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\OsiCommonTest;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample";NETLIBDIR="..\\..\\..\\..\\Data\\Netlib";MIPLIBDIR="..\\..\\..\\..\\Data\\miplib3";%(PreprocessorDefinitions) libCoinUtils.lib;libOsi.lib;libOsiCommonTest.lib;libClp.lib;libOsiClp.lib;libCgl.lib;libCbc.lib;libOsiCbc.lib;libCgl.lib;libOsiClp.lib;libClp.lib;libOsi.lib;libOsiCommonTest.lib;libCoinUtils.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) true Console true true MachineX64 false {dbea3904-f0b8-408a-9e1a-6497febe8c42} false {4f8f7d1c-3a9e-444d-8ee9-77f33fa05994} false {02d45875-a8cf-41b9-990b-3699c0ecfe10} false {c4867f15-438d-4ff8-8388-62fbaaa9786c} false {109d6e6f-6d91-460f-86ae-df27400e09a9} false {7d98e2cb-876e-4f75-9f71-77d3fe87e149} false {e2294708-c5ba-460a-b0a7-060a4023684a} false {363ba154-fec9-4e1e-bc23-93cec58ab785} false {431ed9c6-fdf6-4836-8b33-be4ec5378640} false Cbc-2.8.12/MSVisualStudio/v10/CbcCSosDllSample/0000755000076600007660000000000012377555231017341 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/CbcCSosDllSample/cbcCSosDllSample.vcxproj0000644000076600007660000003532112131315050024054 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E} cbcCSosDllSample Win32Proj Application Application Application Application <_ProjectFileVersion>10.0.30319.1 true false true false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset ..\..\..\..\Osi\src\OsiCbc;..\..\..\..\Osi\src;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Osi\src\OsiClp;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cbc\src;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;CBCCINTERFACEDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\";%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Cdecl Default false cbcCInterfaceDll.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) %(DelayLoadDLLs) true true true Console false MachineX86 ..\..\..\..\Osi\src\OsiCbc;..\..\..\..\Osi\src;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Osi\src\OsiClp;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cbc\src;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;CBCCINTERFACEDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\\";%(PreprocessorDefinitions) MultiThreadedDLL Cdecl Default false cbcCInterfaceDll.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) %(DelayLoadDLLs) true true true Console true true false MachineX86 X64 ..\..\..\..\Osi\src\OsiCbc;..\..\..\..\Osi\src;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Osi\src\OsiClp;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cbc\src;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;CBCCINTERFACEDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\\";%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL ProgramDatabase Cdecl Default false cbcCInterfaceDll.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) %(DelayLoadDLLs) true true true Console false MachineX64 X64 ..\..\..\..\Osi\src\OsiCbc;..\..\..\..\Osi\src;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Osi\src\OsiClp;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cbc\src;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CONSOLE;CBCCINTERFACEDLL_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\\";%(PreprocessorDefinitions) MultiThreadedDLL Cdecl Default false cbcCInterfaceDll.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) %(DelayLoadDLLs) true true true Console true true false MachineX64 {f1e9e3f0-6639-4a84-8e0f-a2d5f11978fb} false Cbc-2.8.12/MSVisualStudio/v10/CbcWithInstalledLibraries/0000755000076600007660000000000012377555231021304 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/CbcWithInstalledLibraries/main.cpp0000644000076600007660000000211012252737704022725 0ustar coincoin#include "OsiClpSolverInterface.hpp" #include "CbcModel.hpp" #include "CoinModel.hpp" #include int main() { const int numcols = 2; const int numrows = 1; double obj[] = { 1.0, 1.0}; // obj: Max x0 + x1 // Column-major sparse "A" matrix: x0 + 2 x1 <= 3.9 int start[] = {0, 1, 2}; // where in index columns start (?) int index[] = {0, 0}; // row indexs for the columns double values[] = {1.0, 2.0}; // the values in the sparse matrix double rowlb[] = {0.0}; double rowub[] = {3.9}; // 0 <= x0 <= 10 and integer // 0 <= x1 <= 10 double collb[] = {0.0, 0.0}; double colub[] = {10.0, 10.0}; OsiClpSolverInterface model; model.loadProblem(numcols, numrows, start, index, values, collb, colub, obj, rowlb, rowub); model.setInteger(0); // Sets x0 to integer model.setObjSense(-1.0); // Maximise CbcModel solver(model); solver.branchAndBound(); bool optimal = solver.isProvenOptimal(); const double *val = solver.getColSolution(); printf("Solution %g %g\n", val[0], val[1]); return 0; }Cbc-2.8.12/MSVisualStudio/v10/CbcWithInstalledLibraries/BaseCBCProject.sln0000644000076600007660000000155712252737704024542 0ustar coincoin Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C++ Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseCBCProject", "BaseCBCProject.vcxproj", "{58EC5CA5-F696-4DC1-8E73-722E90FCFBCA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {58EC5CA5-F696-4DC1-8E73-722E90FCFBCA}.Debug|Win32.ActiveCfg = Debug|Win32 {58EC5CA5-F696-4DC1-8E73-722E90FCFBCA}.Debug|Win32.Build.0 = Debug|Win32 {58EC5CA5-F696-4DC1-8E73-722E90FCFBCA}.Release|Win32.ActiveCfg = Release|Win32 {58EC5CA5-F696-4DC1-8E73-722E90FCFBCA}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal Cbc-2.8.12/MSVisualStudio/v10/CbcWithInstalledLibraries/README.txt0000644000076600007660000000057112252737704023004 0ustar coincoinBaseCBCProject Originated by Iain Dunning: http://www.iaindunning.com Shamelessly modified by Ted Ralphs from original versions on https://github.com/IainNZ/BaseCBCProject This is a nearly-empty Visual C++ 2010 project with settings ready for use with the Cbc libraries that come bundled with the COIN-OR installer. See more: https://projects.coin-or.org/Cbc/wiki/VSSetup Cbc-2.8.12/MSVisualStudio/v10/CbcWithInstalledLibraries/BaseCBCProject.vcxproj0000644000076600007660000001170612252737704025436 0ustar coincoin Debug Win32 Release Win32 {58EC5CA5-F696-4DC1-8E73-722E90FCFBCA} Win32Proj BaseCBCProject Application true Unicode Application false true Unicode true false Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) C:\Program Files (x86)\COIN-OR\1.7.3\win32-msvc10\include\coin Console true libcoinmetis.lib;libcoinmumps.lib;libcoinglpk.lib;libcoinasl.lib;libcoinlapack.lib;libcoinblas.lib;libCbc.lib;libCgl.lib;libClp.lib;libCoinUtils.lib;libOsi.lib;libOsiClp.lib;%(AdditionalDependencies) C:\Program Files (x86)\COIN-OR\1.7.3\win32-msvc10\lib;C:\Program Files (x86)\COIN-OR\1.7.3\win32-msvc10\lib\intel Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) C:\Program Files (x86)\COIN-OR\1.7.3\win32-msvc10\include\coin Console true true true libcoinmetis.lib;libcoinmumps.lib;libcoinglpk.lib;libcoinasl.lib;libcoinlapack.lib;libcoinblas.lib;libCbc.lib;libCgl.lib;libClp.lib;libCoinUtils.lib;libOsi.lib;libOsiClp.lib;%(AdditionalDependencies) C:\Program Files (x86)\COIN-OR\1.7.3\win32-msvc10\lib;C:\Program Files (x86)\COIN-OR\1.7.3\win32-msvc10\lib\intel Cbc-2.8.12/MSVisualStudio/v10/libCbcSolver/0000755000076600007660000000000012377555231016635 5ustar coincoinCbc-2.8.12/MSVisualStudio/v10/libCbcSolver/libCbcSolver.vcxproj0000644000076600007660000002746712136524567022644 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E} libCbcSolver ManagedCProj StaticLibrary StaticLibrary StaticLibrary StaticLibrary <_ProjectFileVersion>10.0.30319.1 AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglGMI;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;..\..\..\..\Cgl\src\CglRedSplit2;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglGMI;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;..\..\..\..\Cgl\src\CglRedSplit2;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) Level3 ProgramDatabase X64 ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglGMI;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;..\..\..\..\Cgl\src\CglRedSplit2;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) Level3 ProgramDatabase X64 ..\..\..\src\;..\..\..\..\Cgl\src\CglZeroHalf;..\..\..\..\Cgl\src\CglGMI;..\..\..\..\Cgl\src\CglLandP;..\..\..\..\Cgl\src\CglTwomir;..\..\..\..\Cgl\src\CglMixedIntegerRounding;..\..\..\..\Cgl\src\CglMixedIntegerRounding2;..\..\..\..\Cgl\src\CglFlowCover;..\..\..\..\Cgl\src\CglClique;..\..\..\..\Cgl\src\CglOddHole;..\..\..\..\Cgl\src\CglKnapsackCover;..\..\..\..\Cgl\src\CglGomory;..\..\..\..\Cgl\src\CglPreProcess;..\..\..\..\Cgl\src\CglDuplicateRow;..\..\..\..\Cgl\src\CglRedSplit;..\..\..\..\Cgl\src\CglProbing;..\..\..\..\Cgl\src;..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;..\..\..\..\Cgl\src\CglResidualCapacity;..\..\..\..\Cgl\src\CglRedSplit2;%(AdditionalIncludeDirectories) CBC_BUILD;WIN32;NDEBUG;_NDEBUG;COIN_FAST_CODE;CLP_FAST_CODE;COIN_NO_TEST_DUPLICATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) Level3 ProgramDatabase Default true true true true true true Cbc-2.8.12/MSVisualStudio/v9/0000755000076600007660000000000012377555231014214 5ustar coincoinCbc-2.8.12/MSVisualStudio/v9/Cbc.sln0000644000076600007660000003201412131315050015376 0ustar coincoinMicrosoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cbcExamplesSample2", "cbcExamplesSample2\cbcExamplesSample2.vcproj", "{4C0B8243-2876-4C92-B6CB-2472B0571CC3}" ProjectSection(ProjectDependencies) = postProject {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42} = {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42} {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} {363BA154-FEC9-4E1E-BC23-93CEC58AB785} = {363BA154-FEC9-4E1E-BC23-93CEC58AB785} {02D45875-A8CF-41B9-990B-3699C0ECFE10} = {02D45875-A8CF-41B9-990B-3699C0ECFE10} {7D98E2CB-876E-4F75-9F71-77D3FE87E149} = {7D98E2CB-876E-4F75-9F71-77D3FE87E149} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cbc", "cbc\cbc.vcproj", "{E2294708-C5BA-460A-B0A7-060A4023684A}" ProjectSection(ProjectDependencies) = postProject {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42} = {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42} {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} {363BA154-FEC9-4E1E-BC23-93CEC58AB785} = {363BA154-FEC9-4E1E-BC23-93CEC58AB785} {02D45875-A8CF-41B9-990B-3699C0ECFE10} = {02D45875-A8CF-41B9-990B-3699C0ECFE10} {71DA4595-E8A7-4B21-A00A-D96D29D11E3E} = {71DA4595-E8A7-4B21-A00A-D96D29D11E3E} {7D98E2CB-876E-4F75-9F71-77D3FE87E149} = {7D98E2CB-876E-4F75-9F71-77D3FE87E149} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCbc", "libCbc\libCbc.vcproj", "{363BA154-FEC9-4E1E-BC23-93CEC58AB785}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCgl", "..\..\..\Cgl\MSVisualStudio\v9\libCgl\libCgl.vcproj", "{DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libClp", "..\..\..\Clp\MSVisualStudio\v9\libClp\libClp.vcproj", "{4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCoinUtils", "..\..\..\CoinUtils\MSVisualStudio\v9\libCoinUtils\libCoinUtils.vcproj", "{C4867F15-438D-4FF8-8388-62FBAAA9786C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libOsi", "..\..\..\Osi\MSVisualStudio\v9\libOsi\libOsi.vcproj", "{7D98E2CB-876E-4F75-9F71-77D3FE87E149}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cbcCInterfaceDll", "cbcCInterfaceDll\cbcCInterfaceDll.vcproj", "{F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}" ProjectSection(ProjectDependencies) = postProject {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42} = {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42} {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} {363BA154-FEC9-4E1E-BC23-93CEC58AB785} = {363BA154-FEC9-4E1E-BC23-93CEC58AB785} {02D45875-A8CF-41B9-990B-3699C0ECFE10} = {02D45875-A8CF-41B9-990B-3699C0ECFE10} {7D98E2CB-876E-4F75-9F71-77D3FE87E149} = {7D98E2CB-876E-4F75-9F71-77D3FE87E149} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cbcCSosDllSample", "cbcCSosDllSample\cbcCSosDllSample.vcproj", "{8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}" ProjectSection(ProjectDependencies) = postProject {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB} = {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libCbcSolver", "libCbcSolver\libCbcSolver.vcproj", "{71DA4595-E8A7-4B21-A00A-D96D29D11E3E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libOsiClp", "..\..\..\Clp\MSVisualStudio\v9\libOsiClp\libOsiClp.vcproj", "{02D45875-A8CF-41B9-990B-3699C0ECFE10}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libOsiCbc", "libOsiCbc\libOsiCbc.vcproj", "{431ED9C6-FDF6-4836-8B33-BE4EC5378640}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OsiCbcUnitTest", "OsiCbcUnitTest\OsiCbcUnitTest.vcproj", "{BB058D80-D376-4F0F-87F7-E4760BC2C84D}" ProjectSection(ProjectDependencies) = postProject {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42} = {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42} {E2294708-C5BA-460A-B0A7-060A4023684A} = {E2294708-C5BA-460A-B0A7-060A4023684A} {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} {363BA154-FEC9-4E1E-BC23-93CEC58AB785} = {363BA154-FEC9-4E1E-BC23-93CEC58AB785} {109D6E6F-6D91-460F-86AE-DF27400E09A9} = {109D6E6F-6D91-460F-86AE-DF27400E09A9} {02D45875-A8CF-41B9-990B-3699C0ECFE10} = {02D45875-A8CF-41B9-990B-3699C0ECFE10} {431ED9C6-FDF6-4836-8B33-BE4EC5378640} = {431ED9C6-FDF6-4836-8B33-BE4EC5378640} {7D98E2CB-876E-4F75-9F71-77D3FE87E149} = {7D98E2CB-876E-4F75-9F71-77D3FE87E149} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libOsiCommonTest", "..\..\..\Osi\MSVisualStudio\v9\libOsiCommonTest\libOsiCommonTest.vcproj", "{109D6E6F-6D91-460F-86AE-DF27400E09A9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Debug|Win32.ActiveCfg = Debug|Win32 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Debug|Win32.Build.0 = Debug|Win32 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Debug|x64.ActiveCfg = Debug|Win32 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Release|Win32.ActiveCfg = Release|Win32 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Release|Win32.Build.0 = Release|Win32 {4C0B8243-2876-4C92-B6CB-2472B0571CC3}.Release|x64.ActiveCfg = Release|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Debug|Win32.ActiveCfg = Debug|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Debug|Win32.Build.0 = Debug|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Debug|x64.ActiveCfg = Debug|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Release|Win32.ActiveCfg = Release|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Release|Win32.Build.0 = Release|Win32 {E2294708-C5BA-460A-B0A7-060A4023684A}.Release|x64.ActiveCfg = Release|Win32 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Debug|Win32.ActiveCfg = Debug|Win32 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Debug|Win32.Build.0 = Debug|Win32 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Debug|x64.ActiveCfg = Debug|x64 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Debug|x64.Build.0 = Debug|x64 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Release|Win32.ActiveCfg = Release|Win32 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Release|Win32.Build.0 = Release|Win32 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Release|x64.ActiveCfg = Release|x64 {363BA154-FEC9-4E1E-BC23-93CEC58AB785}.Release|x64.Build.0 = Release|x64 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Debug|Win32.ActiveCfg = Debug|Win32 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Debug|Win32.Build.0 = Debug|Win32 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Debug|x64.ActiveCfg = Debug|x64 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Debug|x64.Build.0 = Debug|x64 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Release|Win32.ActiveCfg = Release|Win32 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Release|Win32.Build.0 = Release|Win32 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Release|x64.ActiveCfg = Release|x64 {DBEA3904-F0B8-408A-9E1A-6497FEBE8C42}.Release|x64.Build.0 = Release|x64 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Debug|Win32.ActiveCfg = Debug|Win32 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Debug|Win32.Build.0 = Debug|Win32 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Debug|x64.ActiveCfg = Debug|x64 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Debug|x64.Build.0 = Debug|x64 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Release|Win32.ActiveCfg = Release|Win32 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Release|Win32.Build.0 = Release|Win32 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Release|x64.ActiveCfg = Release|x64 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994}.Release|x64.Build.0 = Release|x64 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Debug|Win32.ActiveCfg = Debug|Win32 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Debug|Win32.Build.0 = Debug|Win32 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Debug|x64.ActiveCfg = Debug|x64 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Debug|x64.Build.0 = Debug|x64 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Release|Win32.ActiveCfg = Release|Win32 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Release|Win32.Build.0 = Release|Win32 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Release|x64.ActiveCfg = Release|x64 {C4867F15-438D-4FF8-8388-62FBAAA9786C}.Release|x64.Build.0 = Release|x64 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Debug|Win32.ActiveCfg = Debug|Win32 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Debug|Win32.Build.0 = Debug|Win32 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Debug|x64.ActiveCfg = Debug|x64 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Debug|x64.Build.0 = Debug|x64 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Release|Win32.ActiveCfg = Release|Win32 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Release|Win32.Build.0 = Release|Win32 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Release|x64.ActiveCfg = Release|x64 {7D98E2CB-876E-4F75-9F71-77D3FE87E149}.Release|x64.Build.0 = Release|x64 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}.Debug|Win32.ActiveCfg = Debug|Win32 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}.Debug|x64.ActiveCfg = Debug|x64 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}.Debug|x64.Build.0 = Debug|x64 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}.Release|Win32.ActiveCfg = Release|Win32 {F1E9E3F0-6639-4A84-8E0F-A2D5F11978FB}.Release|x64.ActiveCfg = Release|x64 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}.Debug|Win32.ActiveCfg = Debug|Win32 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}.Debug|x64.ActiveCfg = Debug|x64 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}.Debug|x64.Build.0 = Debug|x64 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}.Release|Win32.ActiveCfg = Release|Win32 {8AFDEA7E-BC40-4F31-80A8-8D05485E0A1E}.Release|x64.ActiveCfg = Release|x64 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Debug|Win32.ActiveCfg = Debug|Win32 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Debug|Win32.Build.0 = Debug|Win32 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Debug|x64.ActiveCfg = Debug|Win32 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Release|Win32.ActiveCfg = Release|Win32 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Release|Win32.Build.0 = Release|Win32 {71DA4595-E8A7-4B21-A00A-D96D29D11E3E}.Release|x64.ActiveCfg = Release|Win32 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Debug|Win32.ActiveCfg = Debug|Win32 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Debug|Win32.Build.0 = Debug|Win32 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Debug|x64.ActiveCfg = Debug|x64 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Debug|x64.Build.0 = Debug|x64 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Release|Win32.ActiveCfg = Release|Win32 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Release|Win32.Build.0 = Release|Win32 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Release|x64.ActiveCfg = Release|x64 {02D45875-A8CF-41B9-990B-3699C0ECFE10}.Release|x64.Build.0 = Release|x64 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Debug|Win32.ActiveCfg = Debug|Win32 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Debug|Win32.Build.0 = Debug|Win32 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Debug|x64.ActiveCfg = Debug|x64 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Debug|x64.Build.0 = Debug|x64 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Release|Win32.ActiveCfg = Release|Win32 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Release|Win32.Build.0 = Release|Win32 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Release|x64.ActiveCfg = Release|x64 {431ED9C6-FDF6-4836-8B33-BE4EC5378640}.Release|x64.Build.0 = Release|x64 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Debug|Win32.ActiveCfg = Debug|Win32 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Debug|Win32.Build.0 = Debug|Win32 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Debug|x64.ActiveCfg = Debug|x64 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Debug|x64.Build.0 = Debug|x64 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Release|Win32.ActiveCfg = Release|Win32 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Release|Win32.Build.0 = Release|Win32 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Release|x64.ActiveCfg = Release|x64 {BB058D80-D376-4F0F-87F7-E4760BC2C84D}.Release|x64.Build.0 = Release|x64 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Debug|Win32.ActiveCfg = Debug|Win32 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Debug|Win32.Build.0 = Debug|Win32 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Debug|x64.ActiveCfg = Debug|x64 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Debug|x64.Build.0 = Debug|x64 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Release|Win32.ActiveCfg = Release|Win32 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Release|Win32.Build.0 = Release|Win32 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Release|x64.ActiveCfg = Release|x64 {109D6E6F-6D91-460F-86AE-DF27400E09A9}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal Cbc-2.8.12/MSVisualStudio/v9/cbcCInterfaceDll/0000755000076600007660000000000012377555231017323 5ustar coincoinCbc-2.8.12/MSVisualStudio/v9/cbcCInterfaceDll/cbcCInterfaceDll.vcproj0000644000076600007660000002233711512601133023645 0ustar coincoin Cbc-2.8.12/MSVisualStudio/v9/cbcExamplesSample2/0000755000076600007660000000000012377555231017666 5ustar coincoinCbc-2.8.12/MSVisualStudio/v9/cbcExamplesSample2/cbcExamplesSample2.vcproj0000644000076600007660000005444712131315050024560 0ustar coincoin Cbc-2.8.12/MSVisualStudio/v9/cbcCSosDllSample/0000755000076600007660000000000012377555231017331 5ustar coincoinCbc-2.8.12/MSVisualStudio/v9/cbcCSosDllSample/cbcCSosDllSample.vcproj0000644000076600007660000002573611512601133023667 0ustar coincoin Cbc-2.8.12/MSVisualStudio/v9/libOsiCbc/0000755000076600007660000000000012377555231016045 5ustar coincoinCbc-2.8.12/MSVisualStudio/v9/libOsiCbc/libOsiCbc.vcproj0000644000076600007660000001631411577425227021132 0ustar coincoin Cbc-2.8.12/MSVisualStudio/v9/libCbc/0000755000076600007660000000000012377555231015372 5ustar coincoinCbc-2.8.12/MSVisualStudio/v9/libCbc/libCbc.vcproj0000644000076600007660000013235511654573107020005 0ustar coincoin Cbc-2.8.12/MSVisualStudio/v9/cbc/0000755000076600007660000000000012377555231014743 5ustar coincoinCbc-2.8.12/MSVisualStudio/v9/cbc/cbc.vcproj0000644000076600007660000002475212131315050016706 0ustar coincoin Cbc-2.8.12/MSVisualStudio/v9/OsiCbcUnitTest/0000755000076600007660000000000012377555231017056 5ustar coincoinCbc-2.8.12/MSVisualStudio/v9/OsiCbcUnitTest/OsiCbcUnitTest.vcproj0000644000076600007660000002234511512601133023132 0ustar coincoin Cbc-2.8.12/MSVisualStudio/v9/libCbcSolver/0000755000076600007660000000000012377555231016565 5ustar coincoinCbc-2.8.12/MSVisualStudio/v9/libCbcSolver/libCbcSolver.vcproj0000644000076600007660000002514112131315050022343 0ustar coincoin Cbc-2.8.12/osi-cbc-uninstalled.pc.in0000644000076600007660000000040311507673264015551 0ustar coincoinprefix=@prefix@ libdir=@ABSBUILDDIR@/src/OsiCbc Name: OsiCbc Description: COIN-OR Open Solver Interface for CBC URL: https://projects.coin-or.org/Osi Version: @PACKAGE_VERSION@ Libs: ${libdir}/libOsiCbc.la Cflags: -I@abs_source_dir@/src/OsiCbc Requires: cbc Cbc-2.8.12/Makefile.in0000644000076600007660000011145712253617675013045 0ustar coincoin# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Copyright (C) 2006 International Business Machines and others. # All Rights Reserved. # This file is distributed under the Eclipse Public License. # Author: Andreas Waechter IBM 2006-04-13 # Copyright (C) 2006, 2007 International Business Machines and others. # All Rights Reserved. # This file is distributed under the Eclipse Public License. # Author: Andreas Waechter IBM 2006-04-13 ######################################################################## # Documentation installation # ######################################################################## srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ # We don't want to compile the test subdirectory, unless the test target is # specified. But we need to list it as subdirectory to make sure that it is # included in the tarball @ALWAYS_FALSE@am__append_1 = test DIST_COMMON = README $(am__configure_deps) \ $(srcdir)/BuildTools/Makemain.inc $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/cbc-uninstalled.pc.in \ $(srcdir)/cbc.pc.in $(srcdir)/osi-cbc-uninstalled.pc.in \ $(srcdir)/osi-cbc.pc.in $(top_srcdir)/configure \ $(top_srcdir)/doxydoc/doxygen.conf.in \ $(top_srcdir)/examples/Makefile.in AUTHORS INSTALL \ config.guess config.sub depcomp install-sh ltmain.sh missing @HAVE_EXTERNALS_TRUE@am__append_2 = Dependencies @HAVE_EXTERNALS_TRUE@am__append_3 = .Dependencies-stamp subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno configure.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h \ $(top_builddir)/src/config_cbc.h CONFIG_CLEAN_FILES = examples/Makefile cbc.pc cbc-uninstalled.pc \ osi-cbc.pc osi-cbc-uninstalled.pc doxydoc/doxygen.conf SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ install-recursive installcheck-recursive installdirs-recursive \ pdf-recursive ps-recursive uninstall-info-recursive \ uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(pkgconfiglibdir)" pkgconfiglibDATA_INSTALL = $(INSTALL_DATA) DATA = $(pkgconfiglib_DATA) ETAGS = etags CTAGS = ctags DIST_SUBDIRS = src src/OsiCbc test DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ABSBUILDDIR = @ABSBUILDDIR@ ACLOCAL = @ACLOCAL@ ADD_CFLAGS = @ADD_CFLAGS@ ADD_CXXFLAGS = @ADD_CXXFLAGS@ ALWAYS_FALSE_FALSE = @ALWAYS_FALSE_FALSE@ ALWAYS_FALSE_TRUE = @ALWAYS_FALSE_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ ASL_CFLAGS = @ASL_CFLAGS@ ASL_CFLAGS_INSTALLED = @ASL_CFLAGS_INSTALLED@ ASL_DATA = @ASL_DATA@ ASL_DATA_INSTALLED = @ASL_DATA_INSTALLED@ ASL_DEPENDENCIES = @ASL_DEPENDENCIES@ ASL_LIBS = @ASL_LIBS@ ASL_LIBS_INSTALLED = @ASL_LIBS_INSTALLED@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUX_DIR = @AUX_DIR@ AWK = @AWK@ BUILDTOOLSDIR = @BUILDTOOLSDIR@ CBCGENERIC_CFLAGS = @CBCGENERIC_CFLAGS@ CBCGENERIC_CFLAGS_INSTALLED = @CBCGENERIC_CFLAGS_INSTALLED@ CBCGENERIC_DEPENDENCIES = @CBCGENERIC_DEPENDENCIES@ CBCGENERIC_LIBS = @CBCGENERIC_LIBS@ CBCGENERIC_LIBS_INSTALLED = @CBCGENERIC_LIBS_INSTALLED@ CBCGENERIC_PCLIBS = @CBCGENERIC_PCLIBS@ CBCGENERIC_PCREQUIRES = @CBCGENERIC_PCREQUIRES@ CBCLIB_CFLAGS = @CBCLIB_CFLAGS@ CBCLIB_CFLAGS_INSTALLED = @CBCLIB_CFLAGS_INSTALLED@ CBCLIB_DEPENDENCIES = @CBCLIB_DEPENDENCIES@ CBCLIB_LIBS = @CBCLIB_LIBS@ CBCLIB_LIBS_INSTALLED = @CBCLIB_LIBS_INSTALLED@ CBCLIB_PCLIBS = @CBCLIB_PCLIBS@ CBCLIB_PCREQUIRES = @CBCLIB_PCREQUIRES@ CBC_BUILD_CBC_GENERIC_FALSE = @CBC_BUILD_CBC_GENERIC_FALSE@ CBC_BUILD_CBC_GENERIC_TRUE = @CBC_BUILD_CBC_GENERIC_TRUE@ CBC_SVN_REV = @CBC_SVN_REV@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDEFS = @CDEFS@ CFLAGS = @CFLAGS@ CLP_CFLAGS = @CLP_CFLAGS@ CLP_CFLAGS_INSTALLED = @CLP_CFLAGS_INSTALLED@ CLP_DATA = @CLP_DATA@ CLP_DATA_INSTALLED = @CLP_DATA_INSTALLED@ CLP_DEPENDENCIES = @CLP_DEPENDENCIES@ CLP_LIBS = @CLP_LIBS@ CLP_LIBS_INSTALLED = @CLP_LIBS_INSTALLED@ COINDEPEND_CFLAGS = @COINDEPEND_CFLAGS@ COINDEPEND_CFLAGS_INSTALLED = @COINDEPEND_CFLAGS_INSTALLED@ COINDEPEND_DATA = @COINDEPEND_DATA@ COINDEPEND_DATA_INSTALLED = @COINDEPEND_DATA_INSTALLED@ COINDEPEND_DEPENDENCIES = @COINDEPEND_DEPENDENCIES@ COINDEPEND_LIBS = @COINDEPEND_LIBS@ COINDEPEND_LIBS_INSTALLED = @COINDEPEND_LIBS_INSTALLED@ COIN_CC_IS_CL_FALSE = @COIN_CC_IS_CL_FALSE@ COIN_CC_IS_CL_TRUE = @COIN_CC_IS_CL_TRUE@ COIN_CXX_IS_CL_FALSE = @COIN_CXX_IS_CL_FALSE@ COIN_CXX_IS_CL_TRUE = @COIN_CXX_IS_CL_TRUE@ COIN_HAS_ASL_FALSE = @COIN_HAS_ASL_FALSE@ COIN_HAS_ASL_TRUE = @COIN_HAS_ASL_TRUE@ COIN_HAS_CLP_FALSE = @COIN_HAS_CLP_FALSE@ COIN_HAS_CLP_TRUE = @COIN_HAS_CLP_TRUE@ COIN_HAS_COINDEPEND_FALSE = @COIN_HAS_COINDEPEND_FALSE@ COIN_HAS_COINDEPEND_TRUE = @COIN_HAS_COINDEPEND_TRUE@ COIN_HAS_CPX_FALSE = @COIN_HAS_CPX_FALSE@ COIN_HAS_CPX_TRUE = @COIN_HAS_CPX_TRUE@ COIN_HAS_DYLP_FALSE = @COIN_HAS_DYLP_FALSE@ COIN_HAS_DYLP_TRUE = @COIN_HAS_DYLP_TRUE@ COIN_HAS_GLPK_FALSE = @COIN_HAS_GLPK_FALSE@ COIN_HAS_GLPK_TRUE = @COIN_HAS_GLPK_TRUE@ COIN_HAS_GRB_FALSE = @COIN_HAS_GRB_FALSE@ COIN_HAS_GRB_TRUE = @COIN_HAS_GRB_TRUE@ COIN_HAS_MIPLIB3_FALSE = @COIN_HAS_MIPLIB3_FALSE@ COIN_HAS_MIPLIB3_TRUE = @COIN_HAS_MIPLIB3_TRUE@ COIN_HAS_MSK_FALSE = @COIN_HAS_MSK_FALSE@ COIN_HAS_MSK_TRUE = @COIN_HAS_MSK_TRUE@ COIN_HAS_NETLIB_FALSE = @COIN_HAS_NETLIB_FALSE@ COIN_HAS_NETLIB_TRUE = @COIN_HAS_NETLIB_TRUE@ COIN_HAS_OSITESTS_FALSE = @COIN_HAS_OSITESTS_FALSE@ COIN_HAS_OSITESTS_TRUE = @COIN_HAS_OSITESTS_TRUE@ COIN_HAS_PKGCONFIG_FALSE = @COIN_HAS_PKGCONFIG_FALSE@ COIN_HAS_PKGCONFIG_TRUE = @COIN_HAS_PKGCONFIG_TRUE@ COIN_HAS_SAMPLE_FALSE = @COIN_HAS_SAMPLE_FALSE@ COIN_HAS_SAMPLE_TRUE = @COIN_HAS_SAMPLE_TRUE@ COIN_HAS_SPX_FALSE = @COIN_HAS_SPX_FALSE@ COIN_HAS_SPX_TRUE = @COIN_HAS_SPX_TRUE@ COIN_HAS_VOL_FALSE = @COIN_HAS_VOL_FALSE@ COIN_HAS_VOL_TRUE = @COIN_HAS_VOL_TRUE@ COIN_HAS_XPR_FALSE = @COIN_HAS_XPR_FALSE@ COIN_HAS_XPR_TRUE = @COIN_HAS_XPR_TRUE@ COIN_PKG_CONFIG_PATH = @COIN_PKG_CONFIG_PATH@ COIN_PKG_CONFIG_PATH_UNINSTALLED = @COIN_PKG_CONFIG_PATH_UNINSTALLED@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPX_CFLAGS = @CPX_CFLAGS@ CPX_CFLAGS_INSTALLED = @CPX_CFLAGS_INSTALLED@ CPX_DATA = @CPX_DATA@ CPX_DATA_INSTALLED = @CPX_DATA_INSTALLED@ CPX_DEPENDENCIES = @CPX_DEPENDENCIES@ CPX_LIBS = @CPX_LIBS@ CPX_LIBS_INSTALLED = @CPX_LIBS_INSTALLED@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEFS = @CXXDEFS@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBG_CFLAGS = @DBG_CFLAGS@ DBG_CXXFLAGS = @DBG_CXXFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DEPENDENCY_LINKING_FALSE = @DEPENDENCY_LINKING_FALSE@ DEPENDENCY_LINKING_TRUE = @DEPENDENCY_LINKING_TRUE@ DYLP_CFLAGS = @DYLP_CFLAGS@ DYLP_CFLAGS_INSTALLED = @DYLP_CFLAGS_INSTALLED@ DYLP_DATA = @DYLP_DATA@ DYLP_DATA_INSTALLED = @DYLP_DATA_INSTALLED@ DYLP_DEPENDENCIES = @DYLP_DEPENDENCIES@ DYLP_LIBS = @DYLP_LIBS@ DYLP_LIBS_INSTALLED = @DYLP_LIBS_INSTALLED@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GLPK_CFLAGS = @GLPK_CFLAGS@ GLPK_CFLAGS_INSTALLED = @GLPK_CFLAGS_INSTALLED@ GLPK_DATA = @GLPK_DATA@ GLPK_DATA_INSTALLED = @GLPK_DATA_INSTALLED@ GLPK_DEPENDENCIES = @GLPK_DEPENDENCIES@ GLPK_LIBS = @GLPK_LIBS@ GLPK_LIBS_INSTALLED = @GLPK_LIBS_INSTALLED@ GRB_CFLAGS = @GRB_CFLAGS@ GRB_CFLAGS_INSTALLED = @GRB_CFLAGS_INSTALLED@ GRB_DATA = @GRB_DATA@ GRB_DATA_INSTALLED = @GRB_DATA_INSTALLED@ GRB_DEPENDENCIES = @GRB_DEPENDENCIES@ GRB_LIBS = @GRB_LIBS@ GRB_LIBS_INSTALLED = @GRB_LIBS_INSTALLED@ HAVE_EXTERNALS_FALSE = @HAVE_EXTERNALS_FALSE@ HAVE_EXTERNALS_TRUE = @HAVE_EXTERNALS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBEXT = @LIBEXT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOLM4 = @LIBTOOLM4@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_LDFLAGS = @LT_LDFLAGS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MIPLIB3_CFLAGS = @MIPLIB3_CFLAGS@ MIPLIB3_CFLAGS_INSTALLED = @MIPLIB3_CFLAGS_INSTALLED@ MIPLIB3_DATA = @MIPLIB3_DATA@ MIPLIB3_DATA_INSTALLED = @MIPLIB3_DATA_INSTALLED@ MIPLIB3_DEPENDENCIES = @MIPLIB3_DEPENDENCIES@ MIPLIB3_LIBS = @MIPLIB3_LIBS@ MIPLIB3_LIBS_INSTALLED = @MIPLIB3_LIBS_INSTALLED@ MPICC = @MPICC@ MPICXX = @MPICXX@ MSK_CFLAGS = @MSK_CFLAGS@ MSK_CFLAGS_INSTALLED = @MSK_CFLAGS_INSTALLED@ MSK_DATA = @MSK_DATA@ MSK_DATA_INSTALLED = @MSK_DATA_INSTALLED@ MSK_DEPENDENCIES = @MSK_DEPENDENCIES@ MSK_LIBS = @MSK_LIBS@ MSK_LIBS_INSTALLED = @MSK_LIBS_INSTALLED@ NETLIB_CFLAGS = @NETLIB_CFLAGS@ NETLIB_CFLAGS_INSTALLED = @NETLIB_CFLAGS_INSTALLED@ NETLIB_DATA = @NETLIB_DATA@ NETLIB_DATA_INSTALLED = @NETLIB_DATA_INSTALLED@ NETLIB_DEPENDENCIES = @NETLIB_DEPENDENCIES@ NETLIB_LIBS = @NETLIB_LIBS@ NETLIB_LIBS_INSTALLED = @NETLIB_LIBS_INSTALLED@ OBJEXT = @OBJEXT@ OPT_CFLAGS = @OPT_CFLAGS@ OPT_CXXFLAGS = @OPT_CXXFLAGS@ OSICBC_DFLT_SOLVER_CLP_FALSE = @OSICBC_DFLT_SOLVER_CLP_FALSE@ OSICBC_DFLT_SOLVER_CLP_TRUE = @OSICBC_DFLT_SOLVER_CLP_TRUE@ OSICBC_DFLT_SOLVER_CPX_FALSE = @OSICBC_DFLT_SOLVER_CPX_FALSE@ OSICBC_DFLT_SOLVER_CPX_TRUE = @OSICBC_DFLT_SOLVER_CPX_TRUE@ OSICBC_DFLT_SOLVER_DYLP_FALSE = @OSICBC_DFLT_SOLVER_DYLP_FALSE@ OSICBC_DFLT_SOLVER_DYLP_TRUE = @OSICBC_DFLT_SOLVER_DYLP_TRUE@ OSICBC_DFLT_SOLVER_GLPK_FALSE = @OSICBC_DFLT_SOLVER_GLPK_FALSE@ OSICBC_DFLT_SOLVER_GLPK_TRUE = @OSICBC_DFLT_SOLVER_GLPK_TRUE@ OSICBC_DFLT_SOLVER_GRB_FALSE = @OSICBC_DFLT_SOLVER_GRB_FALSE@ OSICBC_DFLT_SOLVER_GRB_TRUE = @OSICBC_DFLT_SOLVER_GRB_TRUE@ OSICBC_DFLT_SOLVER_MSK_FALSE = @OSICBC_DFLT_SOLVER_MSK_FALSE@ OSICBC_DFLT_SOLVER_MSK_TRUE = @OSICBC_DFLT_SOLVER_MSK_TRUE@ OSICBC_DFLT_SOLVER_SPX_FALSE = @OSICBC_DFLT_SOLVER_SPX_FALSE@ OSICBC_DFLT_SOLVER_SPX_TRUE = @OSICBC_DFLT_SOLVER_SPX_TRUE@ OSICBC_DFLT_SOLVER_SYM_FALSE = @OSICBC_DFLT_SOLVER_SYM_FALSE@ OSICBC_DFLT_SOLVER_SYM_TRUE = @OSICBC_DFLT_SOLVER_SYM_TRUE@ OSICBC_DFLT_SOLVER_VOL_FALSE = @OSICBC_DFLT_SOLVER_VOL_FALSE@ OSICBC_DFLT_SOLVER_VOL_TRUE = @OSICBC_DFLT_SOLVER_VOL_TRUE@ OSICBC_DFLT_SOLVER_XPR_FALSE = @OSICBC_DFLT_SOLVER_XPR_FALSE@ OSICBC_DFLT_SOLVER_XPR_TRUE = @OSICBC_DFLT_SOLVER_XPR_TRUE@ OSITESTS_CFLAGS = @OSITESTS_CFLAGS@ OSITESTS_CFLAGS_INSTALLED = @OSITESTS_CFLAGS_INSTALLED@ OSITESTS_DATA = @OSITESTS_DATA@ OSITESTS_DATA_INSTALLED = @OSITESTS_DATA_INSTALLED@ OSITESTS_DEPENDENCIES = @OSITESTS_DEPENDENCIES@ OSITESTS_LIBS = @OSITESTS_LIBS@ OSITESTS_LIBS_INSTALLED = @OSITESTS_LIBS_INSTALLED@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ RPATH_FLAGS = @RPATH_FLAGS@ SAMPLE_CFLAGS = @SAMPLE_CFLAGS@ SAMPLE_CFLAGS_INSTALLED = @SAMPLE_CFLAGS_INSTALLED@ SAMPLE_DATA = @SAMPLE_DATA@ SAMPLE_DATA_INSTALLED = @SAMPLE_DATA_INSTALLED@ SAMPLE_DEPENDENCIES = @SAMPLE_DEPENDENCIES@ SAMPLE_LIBS = @SAMPLE_LIBS@ SAMPLE_LIBS_INSTALLED = @SAMPLE_LIBS_INSTALLED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPX_CFLAGS = @SPX_CFLAGS@ SPX_CFLAGS_INSTALLED = @SPX_CFLAGS_INSTALLED@ SPX_DATA = @SPX_DATA@ SPX_DATA_INSTALLED = @SPX_DATA_INSTALLED@ SPX_DEPENDENCIES = @SPX_DEPENDENCIES@ SPX_LIBS = @SPX_LIBS@ SPX_LIBS_INSTALLED = @SPX_LIBS_INSTALLED@ STRIP = @STRIP@ VERSION = @VERSION@ VOL_CFLAGS = @VOL_CFLAGS@ VOL_CFLAGS_INSTALLED = @VOL_CFLAGS_INSTALLED@ VOL_DATA = @VOL_DATA@ VOL_DATA_INSTALLED = @VOL_DATA_INSTALLED@ VOL_DEPENDENCIES = @VOL_DEPENDENCIES@ VOL_LIBS = @VOL_LIBS@ VOL_LIBS_INSTALLED = @VOL_LIBS_INSTALLED@ VPATH_DISTCLEANFILES = @VPATH_DISTCLEANFILES@ XPR_CFLAGS = @XPR_CFLAGS@ XPR_CFLAGS_INSTALLED = @XPR_CFLAGS_INSTALLED@ XPR_DATA = @XPR_DATA@ XPR_DATA_INSTALLED = @XPR_DATA_INSTALLED@ XPR_DEPENDENCIES = @XPR_DEPENDENCIES@ XPR_LIBS = @XPR_LIBS@ XPR_LIBS_INSTALLED = @XPR_LIBS_INSTALLED@ abs_bin_dir = @abs_bin_dir@ abs_include_dir = @abs_include_dir@ abs_lib_dir = @abs_lib_dir@ abs_source_dir = @abs_source_dir@ ac_c_preproc_warn_flag = @ac_c_preproc_warn_flag@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ ac_ct_PKG_CONFIG = @ac_ct_PKG_CONFIG@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_cxx_preproc_warn_flag = @ac_cxx_preproc_warn_flag@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ coin_doxy_excludes = @coin_doxy_excludes@ coin_doxy_logname = @coin_doxy_logname@ coin_doxy_tagfiles = @coin_doxy_tagfiles@ coin_doxy_tagname = @coin_doxy_tagname@ coin_doxy_usedot = @coin_doxy_usedot@ coin_have_doxygen = @coin_have_doxygen@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_autoconf = @have_autoconf@ have_automake = @have_automake@ have_svn = @have_svn@ have_svnversion = @have_svnversion@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sol_cc_compiler = @sol_cc_compiler@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AUTOMAKE_OPTIONS = foreign ######################################################################## # Subdirectories # ######################################################################## # Don't do src/OsiCbc recursively, since src/OsiCbc/libOsiCbc depends on src/libCbc SUBDIRS = src src/OsiCbc $(am__append_1) ######################################################################## # Additional files to be included in tarball # ######################################################################## # Here we need include all files that are not mentioned in other Makefiles EXTRA_DIST = doc/authors.xml doc/cbcexe.xml doc/cbcmodelclass.xml \ doc/cbcuserguide.xml doc/doxygen.xml doc/faqcontent.xml \ doc/faq.xml doc/intro.xml doc/legal.xml doc/messages.xml \ doc/moresamples.xml doc/osibuild.xml doc/otherclasses.xml \ doc/revhist.xml examples/CbcBranchFollow2.cpp \ examples/CbcBranchFollow2.hpp examples/CbcBranchLink.cpp \ examples/CbcBranchLink.hpp examples/CbcBranchUser.cpp \ examples/CbcBranchUser.hpp examples/CbcCompareUser.cpp \ examples/CbcCompareUser.hpp examples/CbcSolver2.cpp \ examples/CbcSolver2.hpp examples/CbcSolver3.cpp \ examples/CbcSolver3.hpp examples/CbcSolverLongThin.cpp \ examples/CbcSolverLongThin.hpp examples/CbcSolverLink.hpp \ examples/CbcSolverLink.cpp examples/ClpQuadInterface.cpp \ examples/ClpQuadInterface.hpp examples/OsiBranchLink.cpp \ examples/OsiBranchLink.hpp examples/OsiSolverLink.hpp \ examples/OsiSolverLink.cpp examples/crew.cpp \ examples/driver2.cpp examples/driver.cpp \ examples/fast0507b.cpp examples/fast0507.cpp examples/gear.cpp \ examples/hotstart.cpp examples/link.cpp examples/longthin.cpp \ examples/lotsize.cpp examples/Makefile.in examples/minimum.cpp \ examples/nway.cpp examples/qmip.cpp examples/quad2.mps \ examples/quad.mps examples/repeat.cpp examples/sample1.cpp \ examples/sample2.cpp examples/sample3.cpp examples/sample4.cpp \ examples/sample5.cpp examples/sos.cpp examples/sudoku.cpp \ examples/sudoku_sample.csv $(am__append_2) ######################################################################## # Installation of the addlibs file # ######################################################################## pkgconfiglibdir = $(libdir)/pkgconfig pkgconfiglib_DATA = cbc.pc osi-cbc.pc addlibsdir = $(DESTDIR)$(datadir)/coin/doc/Cbc ######################################################################## # Maintainer Stuff # ######################################################################## CLEANFILES = # Files that are generated and should be cleaned with make distclean DISTCLEANFILES = $(am__append_3) $(VPATH_DISTCLEANFILES) DocFiles = README AUTHORS LICENSE DocInstallDir = $(datadir)/coin/doc/$(PACKAGE_NAME) all: all-recursive .SUFFIXES: am--refresh: @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/BuildTools/Makemain.inc $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ cd $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) examples/Makefile: $(top_builddir)/config.status $(top_srcdir)/examples/Makefile.in cd $(top_builddir) && $(SHELL) ./config.status $@ cbc.pc: $(top_builddir)/config.status $(srcdir)/cbc.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ cbc-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/cbc-uninstalled.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ osi-cbc.pc: $(top_builddir)/config.status $(srcdir)/osi-cbc.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ osi-cbc-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/osi-cbc-uninstalled.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ doxydoc/doxygen.conf: $(top_builddir)/config.status $(top_srcdir)/doxydoc/doxygen.conf.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: install-pkgconfiglibDATA: $(pkgconfiglib_DATA) @$(NORMAL_INSTALL) test -z "$(pkgconfiglibdir)" || $(mkdir_p) "$(DESTDIR)$(pkgconfiglibdir)" @list='$(pkgconfiglib_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(pkgconfiglibDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfiglibdir)/$$f'"; \ $(pkgconfiglibDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfiglibdir)/$$f"; \ done uninstall-pkgconfiglibDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfiglib_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(pkgconfiglibdir)/$$f'"; \ rm -f "$(DESTDIR)$(pkgconfiglibdir)/$$f"; \ done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) $(mkdir_p) $(distdir)/. $(distdir)/BuildTools $(distdir)/doc $(distdir)/doxydoc $(distdir)/examples @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(mkdir_p) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(pkgconfiglibdir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool \ distclean-local distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-pkgconfiglibDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-exec-am: install-exec-local install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-info-am uninstall-local \ uninstall-pkgconfiglibDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ check-am clean clean-generic clean-libtool clean-local \ clean-recursive ctags ctags-recursive dist dist-all dist-bzip2 \ dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \ distclean-generic distclean-libtool distclean-local \ distclean-recursive distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-hook install-exec install-exec-am \ install-exec-local install-info install-info-am install-man \ install-pkgconfiglibDATA install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive \ mostlyclean mostlyclean-generic mostlyclean-libtool \ mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-hook uninstall-info-am \ uninstall-local uninstall-pkgconfiglibDATA ######################################################################## # Extra Targets # ######################################################################## test: all cd test; $(MAKE) test unitTest: test # Doxygen documentation doxydoc: doxygen doxydoc/doxygen.conf clean-doxydoc: ( cd doxydoc ; rm -rf html *.log *.tag ) clean-local: clean-doxydoc if test -r test/Makefile; then cd test; $(MAKE) clean; fi distclean-local: if test -r test/Makefile; then cd test; $(MAKE) distclean; fi install-exec-local: install-doc uninstall-local: uninstall-doc .PHONY: test unitTest doxydoc install-data-hook: @$(mkdir_p) "$(addlibsdir)" @COIN_HAS_PKGCONFIG_TRUE@ PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ \ @COIN_HAS_PKGCONFIG_TRUE@ $(PKG_CONFIG) --libs cbc > $(addlibsdir)/cbc_addlibs.txt @COIN_CXX_IS_CL_TRUE@@COIN_HAS_PKGCONFIG_FALSE@ echo "-libpath:`$(CYGPATH_W) @abs_lib_dir@` libCbc.lib @CBCLIB_LIBS_INSTALLED@" > $(addlibsdir)/cbc_addlibs.txt @COIN_CXX_IS_CL_FALSE@@COIN_HAS_PKGCONFIG_FALSE@ echo -L@abs_lib_dir@ -lCbcSolver -lCbc @CBCLIB_LIBS_INSTALLED@ > $(addlibsdir)/cbc_addlibs.txt uninstall-hook: rm -f $(addlibsdir)/cbc_addlibs.txt install-doc: $(DocFiles) test -z "$(DocInstallDir)" || $(mkdir_p) "$(DESTDIR)$(DocInstallDir)" for file in $(DocFiles); do \ if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ if test -f "$$dir$$file"; then $(INSTALL_DATA) "$$dir$$file" "$(DESTDIR)$(DocInstallDir)/$$file"; fi; \ done uninstall-doc: for file in $(DocFiles); do \ rm -f "$(DESTDIR)$(DocInstallDir)/$$file"; \ done ######################################################################## # Maintainer Stuff # ######################################################################## # Make sure acinclude is using most recent coin.m4 @MAINTAINER_MODE_TRUE@$(srcdir)/acinclude.m4: $(BUILDTOOLSDIR)/coin.m4 @MAINTAINER_MODE_TRUE@ cat $(LIBTOOLM4) $< > $@ # Make sure the autotools scripts are up to date @MAINTAINER_MODE_TRUE@$(AUX_DIR)/install-sh: $(BUILDTOOLSDIR)/install-sh @MAINTAINER_MODE_TRUE@ cp $< $@ @MAINTAINER_MODE_TRUE@$(AUX_DIR)/missing: $(BUILDTOOLSDIR)/missing @MAINTAINER_MODE_TRUE@ cp $< $@ @MAINTAINER_MODE_TRUE@$(AUX_DIR)/config.guess: $(BUILDTOOLSDIR)/config.guess @MAINTAINER_MODE_TRUE@ cp $< $@ @MAINTAINER_MODE_TRUE@$(AUX_DIR)/config.sub: $(BUILDTOOLSDIR)/config.sub @MAINTAINER_MODE_TRUE@ cp $< $@ @MAINTAINER_MODE_TRUE@$(AUX_DIR)/depcomp: $(BUILDTOOLSDIR)/depcomp @MAINTAINER_MODE_TRUE@ cp $< $@ @MAINTAINER_MODE_TRUE@$(AUX_DIR)/ltmain.sh: $(BUILDTOOLSDIR)/ltmain.sh @MAINTAINER_MODE_TRUE@ cp $< $@ # Take care of updating externals (if Dependencies file exists) @HAVE_EXTERNALS_TRUE@@MAINTAINER_MODE_TRUE@$(top_builddir)/Makefile: .Dependencies-stamp @HAVE_EXTERNALS_TRUE@@MAINTAINER_MODE_TRUE@.Dependencies-stamp: $(srcdir)/Dependencies @HAVE_EXTERNALS_TRUE@@MAINTAINER_MODE_TRUE@ cd $(srcdir); BuildTools/set_externals Dependencies @HAVE_EXTERNALS_TRUE@@MAINTAINER_MODE_TRUE@ touch .Dependencies-stamp @HAVE_EXTERNALS_TRUE@@MAINTAINER_MODE_TRUE@update-externals: .Dependencies-stamp @HAVE_EXTERNALS_TRUE@@MAINTAINER_MODE_TRUE@ cd $(srcdir); svn update .PHONY: install-doc uninstall-doc update-externals # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: Cbc-2.8.12/CbcSourceFilesTable2.xls0000644000076600007660000012000011305575712015365 0ustar coincoinÐÏࡱá>þÿ NþÿÿÿþÿÿÿMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ | ÍÉá°Áâ\pBjarni Kristjansson B°aÀ=œ¯¼=âÿŸQé%8X@"·Ú1Èÿ Arial1Èÿ Arial1Èÿ Arial1Èÿ Arial1 ÿ Arial1Èÿ¼ Arial1Èÿ Arial1Ü Calibri1Ü  Calibri1Ü Calibri1Ü4¼ Calibri1Ü ¼ Calibri1Ü Calibri1Ü Calibri1,8¼ Calibri18¼ Calibri1Ü8¼ Calibri1Ü> Calibri1Ü4 Calibri1Ü< Calibri1Ü?¼ Calibri1h8¼ Cambria1ܼ Calibri1Ü  Calibri"$"#,##0_);\("$"#,##0\)!"$"#,##0_);[Red]\("$"#,##0\)""$"#,##0.00_);\("$"#,##0.00\)'""$"#,##0.00_);[Red]\("$"#,##0.00\)7*2_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_).))_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)?,:_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)6+1_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)àõÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ à À àõÿ ´Ÿ àõÿ ´­ àõÿ ´ª àõÿ ´® àõÿ ´› àõÿ ´¯ àõÿ ´¬ àõÿ ´ àõÿ ´‹ àõÿ ´® àõÿ ´¬ àõÿ ´³ à õÿ ´ž à õÿ ´ à õÿ ´‹ à õÿ ´¤ à õÿ ´± à õÿ ´´ à õÿ ´¾ à õÿ ´Š à õÿ ´¹ à õÿ ´¤ à õÿ ´± à õÿ ´µ à õÿ ´­ à õÿ ”— — – à õÿ ”ff¿¿· à+õÿ øÀ à)õÿ øÀ à,õÿ øÀ à*õÿ øÀ à õÿ ôÀ àõÿ ´ª àõÿ ÔPÀ àõÿ ÔP À àõÿ Ô À àõÿ ôÀ àõÿ ”— — ¯ àõÿ Ô`À àõÿ ´« àõÿ œ  š àõÿ ”¿¿– à õÿ øÀ àõÿ ôÀ àõÿ Ôa>À àõÿ ôÀ à À à @À “ 20% - Accent1“ 20% - Accent2“ 20% - Accent3“ 20% - Accent4“ 20% - Accent5“ 20% - Accent6“ 40% - Accent1“ 40% - Accent2“ 40% - Accent3“ 40% - Accent4“ 40% - Accent5“ 40% - Accent6“ 60% - Accent1“ 60% - Accent2“ 60% - Accent3“ 60% - Accent4“ 60% - Accent5“! 60% - Accent6“ "Accent1“ #Accent2“ $Accent3“ %Accent4“ &Accent5“ 'Accent6“(Bad“) Calculation“* Check Cell“+€ÿ“,€ÿ“-€ÿ“.€ÿ“/Explanatory Text“ 0Good“1 Heading 1“2 Heading 2“3 Heading 3“4 Heading 4“ 5Input“6 Linked Cell“ 7Neutral“€ÿ“ 8Note“ 9Output“:€ÿ“ ;Title“ <Total“= Warning Text`…±ASheet1…/wSheet2…xSheet3Œ®ÁÁ"¾üOÂÞCbcBranchActual.cppCbcBranchBase.cppCbcBranchCut.cppCbcBranchDynamic.cppCbcBranchLotsize.cppCbcCbcParam.cppCbcCompareActual.cppCbcCountRowCut.cppCbcCutGenerator.cppCbcEventHandler.cpp CbcFathom.cppCbcFathomDynamicProgramming.cpp CbcGenBaB.cppCbcGenCbcParam.cppCbcGenCbcParamUtils.cppCbcGenCtlBlk.cppCbcGeneric.cppCbcGenMessages.cppCbcGenOsiParam.cppCbcGenOsiParamUtils.cppCbcGenParam.cppCbcGenParamUtils.cppCbcGenSolution.cppCbcGenSolvers.cppCbcHeuristic.cppCbcHeuristicDive.cppCbcHeuristicDiveCoefficient.cppCbcHeuristicDiveFractional.cppCbcHeuristicDiveGuided.cppCbcHeuristicDiveLineSearch.cppCbcHeuristicDivePseudoCost.cpp CbcHeuristicDiveVectorLength.cppCbcHeuristicFPump.cppCbcHeuristicGreedy.cppCbcHeuristicLocal.cppCbcHeuristicPivotAndFix.cppCbcHeuristicRandRound.cppCbcHeuristicRINS.cpp CbcLinked.cpp CbcMain.cppCbcMessage.cpp CbcModel.cpp CbcNode.cpp CbcParam.cpp CbcSolver.cppCbcStatistics.cppCbcStrategy.cpp CbcTree.cppCbcTreeLocal.cpp Cbc_ampl.cppCbc_C_Interface.cppClpAmplObjective.cppClpAmplStuff.cpp CoinSolve.cpp unitTest.cppunitTestClp.cppBranch InterfaceAmplTest HeuristicGenericFilenameGroup CPP LinesAThe support functions for the main branch-and-cut action routine.4Implementation functions for CbcGenParam parameters.,Constructors and destructors for CbcCbcParamDUnnamed local namespace for cbc-generic support types and functions.,Constructors and destructors for CbcOsiParam3Implementation functions for CbcOsiParam parameters,Constructors and destructors for CbcGenParam3Implementation functions for CbcGenParam parameters‚Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise.¥This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers.libCbcxcbcSolve cbcGeneric*Constructor for cbc-generic control block.Message definitions.CommentCbcAmpl Other ObjectsMultiple CbcTreeLocalCbcTree CbcTreeArray CbcStrategyCbcStrategyDefault*CbcAmpl*, Multiple CbcStatisticsCbcParam2CbcNodeInfo, CbcFullNodeInfo, CbcPartialNodeInfo, CbcNodeCbcModel CbcMessage OsiSolverLink_OsiLinkedBound, OsiHeuristicDynamic3, OsiOldLink, OsiBiLinear*, OsiSimpleFixedInteger, MultipleCbcHeuristicRINSCbcHeuristicRandRoundCbcHeuristicPivotAndFixCbcHeuristicLocalCbcHeuristicNaiveCbcHeuristicGreedyCoverCbcHeuristicGreedyEqualityCbcHeuristicFPumpCbcDisasterHandlerCbcHeuristicDiveVectorLengthCbcHeuristicDivePseudoCostCbcHeuristicDiveLineSearchCbcHeuristicDiveGuidedCbcHeuristicDiveFractionalCbcHeuristicDiveCoefficientCbcHeuristicDive CbcHeuristicmCbcHeuristicNode, CbcHeuristicNodeList, CbcRounding, CbcHeuristicPartial, CbcSerendipity, CbcHeuristicJustOneCbcFathomDynamicProgramming CbcFathom CbcOsiSolverCbcEventHandlerCbcCutGenerator$CbcCutModifier, CbcCutSubsetModifierCbcCountRowCutCbcCompareDepth:CbcCompareObjective, CbcCompareDefault, CbcCompareEstimate#include "CbcOrClpParam.cpp" CbcLotsizeCbcLotsizeBranchingObject!CbcSimpleIntegerDynamicPseudoCost=CbcDynamicPseudoCostBranchingObject, CbcBranchDynamicDecision CbcBranchCut@CbcCutBranchingObject, CbcBranchToFixLots, CbcBranchAllDifferent CbcObjectJCbcBranchingObject, CbcBranchDecision, CbcConsequence, CbcObjectUpdateData CbcGenCtlBlk CbcCbcParamnamespace CbcCbcParamUtils CbcOsiParamnamespace CbcOsiParamUtils CbcGenParamnamespace CbcGenSolversCbcGenParamUtils namespacenamespace CbcGenParamUtilsnamespace CbcGenSolvers, CbcCompareUser, namespacemain CbcSolverCbcMainglobalClpAmplObjectiveMyMessageHandler2¾CbcClique, CbcSos, CbcSimpleInteger, CbcIntegerBranchingObject, CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject, CbcSosBranchingObject, CbcBranchDefaultDecision, CbcFollowOn, CbcFixingBranchingObject, CbcNWay, CbcNWayBranchingObject, CbcFixVariable, CbcDummyBranchingObject, CbcGeneral, CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject, CbcSubProblem First ObjectPersonBjarniLou HPP Lines3CbcHeuristicRENS, CbcHeuristicDINS, CbcHeuristicVNDCbcCompareBase.hppCbcCompareBaseCbcCompare, CbcChooseVariable CbcConfig.h#definesCbcFeasibilityBase.hppCbcFeasibilityBaseClpConstraintAmpl.hppOther ProjectsAge Total LinesStatusEdwin CbcClique.cpp CbcSos.cppCbcSimpleIntegerCbcIntegerBranchingObjectCbcSimpleIntegerPseudoCost#CbcIntegerPseudoCostBranchingObjectCbcCliqueBranchingObjectCbcLongCliqueBranchingObjectCbcSosBranchingObjectCbcBranchDefaultDecision CbcFollowOnCbcFixingBranchingObjectCbcNWayCbcNWayBranchingObjectCbcFixVariableCbcDummyBranchingObject CbcGeneralCbcGeneralDepthCbcGeneralBranchingObjectCbcOneGeneralBranchingObject CbcSubProblem CbcCompareCbcChooseVariableCbcBranchDecisionCbcBranchObjectCbcConsequenceCbcObjectUpdateDataCbcBranchAllDifferentCbcBranchToFixLotsCbcCutBranchingObjectCbcDynamicPseudoCostBranchingCbcFullNodeInfo.cppCbcNodeInfo.cppCbcPartialNodeInfo.cpp NodeStratCutsAPICoreCbcCutSubsetModifier.cppCbcCutModifier.cpCbcCompareDefault.cppCbcCompareDepth.cppCbcCompareEstimate.cppCbcCompareObjective.cppInherits Nonlinear/OsiAPI?Dan Dan/EdwinÿâP ùµ©eP ?û÷³x4 ÇWè¤Y Ç©e •Q g# m) D ~:שeç £Œ!Hò!®Ì"ˆp#, $É¿${I%ccÒ||@Ñ/£}A} 00\);_(*ef;_(@_) }A} 00\);_(*ef;_(@_) }A} 00\);_(*ef;_(@_) }A} 00\);_(*ef;_(@_) }A} 00\);_(*ef;_(@_) }A} 00\);_(*ef ;_(@_) }A} 00\);_(*ÌL;_(@_) }A} 00\);_(*ÌL;_(@_) }A} 00\);_(*ÌL;_(@_) }A} 00\);_(*ÌL;_(@_) }A} 00\);_(*ÌL;_(@_) }A} 00\);_(*ÌL ;_(@_) }A} 00\);_(*23;_(@_) }A} 00\);_(*23;_(@_) }A} 00\);_(*23;_(@_) }A} 00\);_(*23;_(@_) }A}  00\);_(*23;_(@_) }A}! 00\);_(*23 ;_(@_) }A}" 00\);_(*;_(@_) }A}# 00\);_(*;_(@_) }A}$ 00\);_(*;_(@_) }A}% 00\);_(*;_(@_) }A}& 00\);_(*;_(@_) }A}' 00\);_(* ;_(@_) }A}( œÿ00\);_(*ÿÇÎÿ;_(@_) }‘}) ú}ÿ00\);_(*òòòÿ;_(@_) ÿ ÿ ÿ ÿ}‘}* 00\);_(*¥¥¥ÿ;_(@_) ???ÿ ???ÿ ???ÿ ???ÿ}-}/ ÿ00\);_(*}A}0 aÿ00\);_(*ÆïÎÿ;_(@_) }A}1 00\);_(*;_(@_) }A}2 00\);_(*ÿ?;_(@_) }A}3 00\);_(*23;_(@_) }-}4 00\);_(*}‘}5 ??vÿ00\);_(*ÿÌ™ÿ;_(@_) ÿ ÿ ÿ ÿ}A}6 ú}ÿ00\);_(*ÿ€ÿ;_(@_) }A}7 œeÿ00\);_(*ÿëœÿ;_(@_) }x}8ÿÿÌÿ00\);_(*²²²ÿÿëœÿ;_(²²²ÿÿ ²²²ÿÿ ²²²ÿÿ}‘}9 ???ÿ00\);_(*òòòÿ;_(???ÿ ???ÿ  ???ÿ ???ÿ}-}; 00\);_(*}U}< 00\);_(*;_( }-}= ÿÿ00\);_(*’M’ÿ 20% - Accent1 efÛåñÿ ÿ%’M’"ÿ 20% - Accent2 efòÝÜÿ ÿ%’M’&ÿ 20% - Accent3 efêñÝÿ ÿ%’M’*ÿ 20% - Accent4 efåàìÿ ÿ%’M’.ÿ 20% - Accent5 efÛîóÿ ÿ%’M’2ÿ 20% - Accent6  efýéÙÿ ÿ%’M’ÿ 40% - Accent1 ÌL¸Ìäÿ ÿ%’M’#ÿ 40% - Accent2 ÌL湸ÿ ÿ%’M’'ÿ 40% - Accent3 ÌL×ä¼ÿ ÿ%’M’+ÿ 40% - Accent4 ÌLÌÀÚÿ ÿ%’M’/ÿ 40% - Accent5 ÌL¶Ýèÿ ÿ%’M’3ÿ 40% - Accent6  ÌLüÕ´ÿ ÿ%’M’ ÿ 60% - Accent1 23•³×ÿ ÿÿÿÿ%’M’$ÿ 60% - Accent2 23Ù—•ÿ ÿÿÿÿ%’M’(ÿ 60% - Accent3 23ÂÖšÿ ÿÿÿÿ%’M’,ÿ 60% - Accent4 23²¡Çÿ ÿÿÿÿ%’M’0ÿ 60% - Accent5 23“ÍÝÿ ÿÿÿÿ%’M’4ÿ 60% - Accent6  23úÀÿ ÿÿÿÿ%’A’ÿAccent1 O½ÿ ÿÿÿÿ%’A’!ÿAccent2 ÀPMÿ ÿÿÿÿ%’A’%ÿAccent3 ›»Yÿ ÿÿÿÿ%’A’)ÿAccent4 €d¢ÿ ÿÿÿÿ%’A’-ÿAccent5 K¬Æÿ ÿÿÿÿ%’A’1ÿAccent6  ÷–Fÿ ÿÿÿÿ%’9’ÿBad ÿÿÇÎÿ ÿœÿ%’’ÿ Calculation ÿòòòÿ ÿú}ÿ%ÿÿÿÿÿÿ ÿÿ’’ÿ Check Cell ÿ¥¥¥ÿ ÿÿÿÿ%ÿ???ÿÿ???ÿÿ???ÿ ÿ???ÿ’ ’ÿComma’(’ÿ Comma [0]’&’ÿCurrency’.’ÿ Currency [0]’G’5ÿExplanatory Text ÿÿ%’;’ÿGood ÿÆïÎÿ ÿaÿ%’G’ÿ Heading 1 I}ÿ%O½ÿ’G’ÿ Heading 2 I}ÿ%ÿ?¨ÀÞÿ’G’ÿ Heading 3 I}ÿ%23•³×ÿ’9’ÿ Heading 4 I}ÿ%’u’ÿInput ÿÿÌ™ÿ ÿ??vÿ%ÿÿÿÿÿÿ ÿÿ’K’ÿ Linked Cell ÿú}ÿ%ÿÿ€ÿ’A’ÿNeutral ÿÿëœÿ ÿœeÿ%’"’ÿNormal’b’ ÿNote ÿÿÿÌÿÿ²²²ÿÿ²²²ÿÿ²²²ÿ ÿ²²²ÿ’w’ÿOutput ÿòòòÿ ÿ???ÿ%ÿ???ÿÿ???ÿÿ???ÿ ÿ???ÿ’$’ÿPercent’1’ÿTitle I}ÿ%’M’ÿTotal ÿ%O½ÿO½ÿ’?’ ÿ Warning Text ÿÿÿ%ŽXŽTableStyleMedium9PivotStyleLight16šš££––Bå››ŒŒ | ÍÉ  gçFQÐ`krhv  dü©ñÒMbP?_*+‚€%ÿÁƒ„Mj\\OFFICE1\Dell Printer 5100cn ÜŒSÿ€ê odXXLetterPRIVâ0''''ÄÈ\KhCŸ}­ôÿÿÈDFBF0040/#Ñùgü-¤Oµ_ÉûËÜ}Ìd¡"dXXà?à?U} $} $!} $ } I+} I(gÿ€>ÿÿÿÿÿÿÿÿ ÿ ÿ ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿý >>ý >?ý >›ý >Ùý >«ý >©ý >@ý >žý >ªý >Ký >Mý >Ný >¨ý >šý >Sý >Qý ý 8ý ¬½ @Ü´@|œ@! û»@ +ý DÀDÀý  Lý Tý ™ý ­ý 8ý ¬ý ®ý 8ý ¬ý ¯ý 8ý ¬ý °ý 8ý ¬ý ±ý 8ý ¬ý ²ý 8ý ¬ý ³ý 8ý ¬ý ´ý 8ý ¬ý µý 8ý ¬ý ¶ý 8ý ¬ý ·ý 8ý ¬ý ¸ý 8ý ¬ý ¹ý 8ý ¬ý ºý 8ý ¬ý »ý 8ý ¬ý ¼ý 8ý ¬ý ½ý 8ý ¬ý ¾ý 8ý ¬ý ¿ý 8ý ¬ý Àý 8ý ¬ý Áý 8ý ¬ý ý 8ý ¬½$@v@†@ Œ@ þ ¼f ; LþÀLÿÀý  Lý …ý †ý Äý 8ý ¬ý Åý 8ý ¬ý Æý 8ý ¬ý …ý 8ý ¬ý Çý 8ý ¬ý ý 8ý ¬½$@ø@°s@ è”@! ÿ ý  Lý ƒý „ý Èý 8ý ¬ý Éý 8ý ¬×DÄ là•*********************¨****** ÿ!ÿ"ÿ#ÿ$ÿ%ÿ&ÿ'ÿ(ÿ)ÿ*ÿ+ÿ,ÿ-ÿ.ÿ/ÿ0ÿ1ÿ2ÿ3ÿ4ÿ5ÿ6ÿ7ÿ8ÿ9ÿ:ÿ;ÿ<ÿ=ÿ>ÿ?ÿý Êý 8ý ¬ý !ý !8ý !¬½! @Ü@h@! H£@$ ÿ ý ! Lý !ý !‚ý "Ëý "8ý "¬ý #ý #8ý #¬ý $ý $8ý $¬½$.@H‰@@o@$ Œ@% ÿ ý $ Lý $ý $€ý %ý %Ñý %œ½%8@ð?% ð?& ÿ ý % Lý %~ý &ý &Ïý &¬½& @ð|@ d@&  ƒ@+ ÿ ý & Lý &|ý &}ý 'Õý 'Ïý '¬ý (Öý (Ïý (¬ý )×ý )Ïý )¬ý *Øý *Ïý *¬ý + ý +Ïý +¬~ +8@~ +@e@+ @e@. ÿ ý + Lý +¡ý +¢ý ,Âý ,Ïý ,¬ý -Ãý -Ïý -¬ý .£~ .4@~ .€Y@. €Y@/ ÿ ý . Lý .¤ý /ý /н/$@€_@À\@/  n@0 ÿ ý / Lý /{ý 0ý 0Ðý 0¬½0@“@à@0 ›@3 ÿ ý 0 Lý 0yý 0zý 1Ôý 1Ðý 1¬ý 2Óý 2Ðý 2¬ý 3 ý 3ѽ3B@@Y@ k@3  t@4 ÿ ý 3 Lý 3xý 4 ý 4Ïý 4¬½43@€Z@€_@4 m@5 ÿ ý 4 Lý 4vý 4wý 5 ý 5Ïý 5¬½5$@l@Àd@5 “@6 ÿ ý 5 Lý 5uý 6¥ý 6Û~ 68@~ 6€J@6 €J@7 ÿ ý 6 Lý 6¦ý 7 ý 7=ý 7½7,@°‹@7 °‹@8 ÿ ý 7 Lý 7ý 7ý 7Aý 8 ý 8=ý 8½88@`c@ g@8 €u@9 ÿ ý 8 Lý 8ˆý 8Cý 9ý 9=ý 9½92@y@9 y@: ÿ ý 9 Lý 9‰ý 9Bý :ý :=ý :½:8@H…@ @: t™@; ÿ ý : Lý : Lý :‡ý :Oý ;ý ;=ý ;½;8@ðy@; ðy@< ÿ ý ; Lý ;ý ;ý ;Dý <ý <=ý <½<8@h@< h@= ÿ ý < Lý <‡ý <Pý =ý ==ý =½=8@€c@ h@= v@> ÿ ý = Lý =Šý =Eý >ý >=ý >½>2@€€@> €€@? ÿ ý > Lý >‹ý >Fý ?ý ?=ý ?½?8@@c@`k@? Pw@@ ÿ ý ? Lý ?Œý ?G×Dul***{******es**ss—‰—‰‰@ÿAÿBÿCÿDÿEÿFÿGÿHÿIÿJÿKÿLÿMÿNÿOÿPÿQÿRÿSÿTÿUÿVÿWÿXÿYÿZÿ[ÿ\ÿ]ÿ^ÿ_ÿý @ý @=ý @½@2@d—@@ d—@A ÿ ý @ Lý @ý @‘ý @Hý Aý A=ý A½A6@@‚@A @‚@B ÿ ý A Lý AŽý Aý AIý Bý B=ý B½B8@Pp@B Pp@C ÿ ý B Lý Bý Bý BJý Cý C<½C$@ª¦@P„@C ¾«@D ÿ ý C Lý Csý Ctý Dý D<½D$@°@d@D 0“@E ÿ ý D Lý Drý Eý E<½E(@`@€H@E  f@F ÿ ý E Lý Eqý Fý F<½F2@\@€H@F  d@G ÿ ý F Lý Fpý Gý G<½G2@À^@J@G àe@H ÿ ý G Lý Goý Hý H<½H2@^@€H@H  e@I ÿ ý H Lý Hný Iý I<½I2@`l@€L@I Àq@J ÿ ý I Lý Imý Jý J<½J$@À^@€H@J €e@K ÿ ý J Lý Jlý K ý K<½K @˜¥@ðs@K ¨@L ÿ ý K Lý Kjý Kký L!ý L<½L1@èŠ@ g@L h@M ÿ ý L Lý Lhý Liý M"ý M<½M @@‘@j@M €”@N ÿ ý M Lý Mfý Mgý N#ý N<½N,@È€@€K@N €‚@O ÿ ý N Lý Neý O$ý O<½O$@€@€K@O È@P ÿ ý O Lý Odý P%ý P<½P$@Ü’@€r@P |—@Q ÿ ý P Lý Pcý PŸý Q&ý QÚ½Q$@7À@ì•@Q €ôÂ@R ÿ ý Q Lý Qaý Qbý R'ý RѽR,@?Ì™@R Ì™@S ÿ ý R Lý R“ý R’ý S(ý SѽS*@Z@ÀU@S àg@T ÿ ý S Lý S`ý T)ý TÒý T¬½T@+Ð@|¤@T ÀºÒ@U ÿ ý T Lý T_ý U*ý UÒý UܽU´@0‰@U 5·@Y ÿ ý U Lý U^ý U]ý VÌý VÒý VÜý WÍý WÒý WÜý XÎý XÒý XÜý Y+ý YÑý Yœ½Y8@`@ m@Y ‡@Z ÿ ý Y Lý Y\ý Z,ý ZÑý Zœ½Z€2Æ@Z €2Æ@[ ÿ ý Z Lý Z”ý Z•ý [-ý [ѽ[5@a@€X@[ @m@\ ÿ ý [ Lý [[ý \.ý \Òý \ݽ\ @`@ào@\ ¬’@] ÿ ý \ Lý \Xý \Yý ]/ý ]Òý ]ݽ] @h’@0z@] ô˜@^ ÿ ý ] Lý ]Vý ]Wý ^0ý ^<½^$@L›@w@^ ˆ @_ ÿ ý ^ Lý ^Uý _1ý _:½_@?€—@@P@_ „˜@` ÿ ý _ Lý _–×DSl———sssssssss{s***‰ss`ÿaÿbÿcÿdÿeÿfÿý `2ý `9ý `œ½`@?ô£@„@` ©@a ÿ ý ` Lý `–ý a3ý a:½a,@?p‡@€[@a àŠ@b ÿ ý a Lý a—ý b4ý b:½b@h•@b h•@c ÿ ý b Lý bRý bZý c§ý c:~ c8@~ c@Z@c @Z@d ÿ ý d5ý dÑý dœ½d @?`u@d `u@e ÿ ý d Lý d˜ý d“ý e6ý e;½e @? z@e  z@f ÿ ý e Lý e–ý f7ý f;½f@?P†@f P†@ ÿ ý f Lý f–×µxs{W‰m>¶@A à!@ÿ?666ï7ggÿÿÿÿDœ&œ‹‹P | ÍÉ çw  dü©ñÒMbP?_*+‚€%ÿÁƒ„¡"ÿPà?à?U>¶@ï7ggÿÿÿÿDœ&œ‹‹ | ÍÉ Gy  dü©ñÒMbP?_*+‚€%ÿÁƒ„¡"ÿà?à?U>¶@ï7ggÿÿÿÿDœ&œ‹‹ þÿà…ŸòùOh«‘+'³Ù0¸@Hd€ ˜ ¤°äBjarni KristjanssonBjarni KristjanssonMicrosoft Excel@Sðü|NÊ@è*©sÊþÿÕÍÕœ.“—+,ù®0ì PXx €ˆ˜   ÉäMaximal Software, Inc.' Sheet1Sheet2Sheet3  Worksheets  !"#$%&'()*+,-./0123456789:;<þÿÿÿ>?@ABCDþÿÿÿFGHIJKLþÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿ ÀFþÿÿÿWorkbookÿÿÿÿÿÿÿÿÿÿÿÿïySummaryInformation(ÿÿÿÿ=DocumentSummaryInformation8ÿÿÿÿÿÿÿÿÿÿÿÿECbc-2.8.12/ltmain.sh0000755000076600007660000057753011405215312012607 0ustar coincoin# ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. basename="s,^.*/,,g" # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" # The name of this program: progname=`echo "$progpath" | $SED $basename` modename="$progname" # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 PROGRAM=ltmain.sh PACKAGE=libtool VERSION=1.5.22 TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell, and then maybe $echo will work. exec $SHELL "$progpath" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <&2 $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit $EXIT_FAILURE fi # Global variables. mode=$default_mode nonopt= prev= prevopt= run= show="$echo" show_help= execute_dlfiles= duplicate_deps=no preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" ##################################### # Shell function definitions: # This seems to be the best place for them # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $mkdir "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || { $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 exit $EXIT_FAILURE } fi $echo "X$my_tmpdir" | $Xsed } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. func_win32_libid () { win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | \ $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $echo $win32_libid_type } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac CC_quoted="$CC_quoted $arg" done case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac CC_quoted="$CC_quoted $arg" done case "$@ " in " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then $echo "$modename: unable to infer tagged configuration" $echo "$modename: specify a tag with \`--tag'" 1>&2 exit $EXIT_FAILURE # else # $echo "$modename: using $tagname tagged configuration" fi ;; esac fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 exit $EXIT_FAILURE fi } # func_extract_archives gentop oldlib ... func_extract_archives () { my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" my_status="" $show "${rm}r $my_gentop" $run ${rm}r "$my_gentop" $show "$mkdir $my_gentop" $run $mkdir "$my_gentop" my_status=$? if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then exit $my_status fi for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` my_xdir="$my_gentop/$my_xlib" $show "${rm}r $my_xdir" $run ${rm}r "$my_xdir" $show "$mkdir $my_xdir" $run $mkdir "$my_xdir" exit_status=$? if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then exit $exit_status fi case $host in *-darwin*) $show "Extracting $my_xabs" # Do not bother doing anything if just a dry run if test -z "$run"; then darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` if test -n "$darwin_arches"; then darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= $show "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we have a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` lipo -create -output "$darwin_file" $darwin_files done # $darwin_filelist ${rm}r unfat-$$ cd "$darwin_orig_dir" else cd "$darwin_orig_dir" func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches fi # $run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # End of Shell function definitions ##################################### # Darwin sucks eval std_shrext=\"$shrext_cmds\" disable_libs=no # Parse our command line options once, thoroughly. while test "$#" -gt 0 do arg="$1" shift case $arg in -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in execute_dlfiles) execute_dlfiles="$execute_dlfiles $arg" ;; tag) tagname="$arg" preserve_args="${preserve_args}=$arg" # Check whether tagname contains only valid characters case $tagname in *[!-_A-Za-z0-9,/]*) $echo "$progname: invalid tag name: $tagname" 1>&2 exit $EXIT_FAILURE ;; esac case $tagname in CC) # Don't test for the "default" C tag, as we know, it's there, but # not specially marked. ;; *) if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then taglist="$taglist $tagname" # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" else $echo "$progname: ignoring unknown tag $tagname" 1>&2 fi ;; esac ;; *) eval "$prev=\$arg" ;; esac prev= prevopt= continue fi # Have we seen a non-optional argument yet? case $arg in --help) show_help=yes ;; --version) $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" $echo $echo "Copyright (C) 2005 Free Software Foundation, Inc." $echo "This is free software; see the source for copying conditions. There is NO" $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." exit $? ;; --config) ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath # Now print the configurations for the tags. for tagname in $taglist; do ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" done exit $? ;; --debug) $echo "$progname: enabling shell trace mode" set -x preserve_args="$preserve_args $arg" ;; --dry-run | -n) run=: ;; --features) $echo "host: $host" if test "$build_libtool_libs" = yes; then $echo "enable shared libraries" else $echo "disable shared libraries" fi if test "$build_old_libs" = yes; then $echo "enable static libraries" else $echo "disable static libraries" fi exit $? ;; --finish) mode="finish" ;; --mode) prevopt="--mode" prev=mode ;; --mode=*) mode="$optarg" ;; --preserve-dup-deps) duplicate_deps="yes" ;; --quiet | --silent) show=: preserve_args="$preserve_args $arg" ;; --tag) prevopt="--tag" prev=tag preserve_args="$preserve_args --tag" ;; --tag=*) set tag "$optarg" ${1+"$@"} shift prev=tag preserve_args="$preserve_args --tag" ;; -dlopen) prevopt="-dlopen" prev=execute_dlfiles ;; -*) $echo "$modename: unrecognized option \`$arg'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; *) nonopt="$arg" break ;; esac done if test -n "$prevopt"; then $echo "$modename: option \`$prevopt' requires an argument" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi case $disable_libs in no) ;; shared) build_libtool_libs=no build_old_libs=yes ;; static) build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` ;; esac # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 case $nonopt in *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) mode=link for arg do case $arg in -c) mode=compile break ;; esac done ;; *db | *dbx | *strace | *truss) mode=execute ;; *install*|cp|mv) mode=install ;; *rm) mode=uninstall ;; *) # If we have no mode, but dlfiles were specified, then do execute mode. test -n "$execute_dlfiles" && mode=execute # Just use the default operation mode. if test -z "$mode"; then if test -n "$nonopt"; then $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 else $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 fi fi ;; esac fi # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then $echo "$modename: unrecognized option \`-dlopen'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$modename --help --mode=$mode' for more information." # These modes are in order of execution frequency so that they run quickly. case $mode in # libtool compile mode compile) modename="$modename: compile" # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) if test -n "$libobj" ; then $echo "$modename: you cannot specify \`-o' more than once" 1>&2 exit $EXIT_FAILURE fi arg_mode=target continue ;; -static | -prefer-pic | -prefer-non-pic) later="$later $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac lastarg="$lastarg $arg" done IFS="$save_ifs" lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` # Add the arguments to base_compile. base_compile="$base_compile $lastarg" continue ;; * ) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` case $lastarg in # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, and some SunOS ksh mistreat backslash-escaping # in scan sets (worked around with variable expansion), # and furthermore cannot handle '|' '&' '(' ')' in scan sets # at all, so we specify them separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; esac base_compile="$base_compile $lastarg" done # for arg case $arg_mode in arg) $echo "$modename: you must specify an argument for -Xcompile" exit $EXIT_FAILURE ;; target) $echo "$modename: you must specify a target with \`-o'" 1>&2 exit $EXIT_FAILURE ;; *) # Get the name of the library object. [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo xform='[cCFSifmso]' case $libobj in *.ada) xform=ada ;; *.adb) xform=adb ;; *.ads) xform=ads ;; *.asm) xform=asm ;; *.c++) xform=c++ ;; *.cc) xform=cc ;; *.ii) xform=ii ;; *.class) xform=class ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; *.f90) xform=f90 ;; *.for) xform=for ;; *.java) xform=java ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` case $libobj in *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; *) $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 exit $EXIT_FAILURE ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -static) build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` case $qlibobj in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qlibobj="\"$qlibobj\"" ;; esac test "X$libobj" != "X$qlibobj" \ && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir= else xdir=$xdir/ fi lobj=${xdir}$objdir/$objname if test -z "$base_compile"; then $echo "$modename: you must specify a compilation command" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi $run $rm $removelist trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" removelist="$removelist $output_obj $lockfile" trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $run ln "$progpath" "$lockfile" 2>/dev/null; do $show "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $echo "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit $EXIT_FAILURE fi $echo "$srcfile" > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` case $qsrcfile in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qsrcfile="\"$qsrcfile\"" ;; esac $run $rm "$libobj" "${libobj}T" # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then $echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then $show "$mv $output_obj $lobj" if $run $mv $output_obj $lobj; then : else error=$? $run $rm $removelist exit $error fi fi # Append the name of the PIC object to the libtool object file. test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then $echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then $show "$mv $output_obj $obj" if $run $mv $output_obj $obj; then : else error=$? $run $rm $removelist exit $error fi fi # Append the name of the non-PIC object the libtool object file. # Only append if the libtool object file exists. test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built fi build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test ;; *) qarg=$arg ;; esac libtool_args="$libtool_args $qarg" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) compile_command="$compile_command @OUTPUT@" finalize_command="$finalize_command @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. compile_command="$compile_command @SYMFILE@" finalize_command="$finalize_command @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" if test ! -f "$arg"; then $echo "$modename: symbol file \`$arg' does not exist" exit $EXIT_FAILURE fi prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat $save_arg` do # moreargs="$moreargs $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then pic_object= non_pic_object= # Read the .lo file # If there is no directory component, then add one. case $arg in */* | *\\*) . $arg ;; *) . ./$arg ;; esac if test -z "$pic_object" || \ test -z "$non_pic_object" || test "$pic_object" = none && \ test "$non_pic_object" = none; then $echo "$modename: cannot find name of object for \`$arg'" 1>&2 exit $EXIT_FAILURE fi # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. libobjs="$libobjs $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object non_pic_objects="$non_pic_objects $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi else # Only an error if not doing a dry-run. if test -z "$run"; then $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 exit $EXIT_FAILURE else # Dry-run case. # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` libobjs="$libobjs $pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi fi done else $echo "$modename: link input file \`$save_arg' does not exist" exit $EXIT_FAILURE fi arg=$save_arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit $EXIT_FAILURE ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= compile_command="$compile_command $wl$qarg" finalize_command="$finalize_command $wl$qarg" continue ;; xcclinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; shrext) shrext_cmds="$arg" prev= continue ;; darwin_framework|darwin_framework_skip) test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" prev= continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 continue ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: more than one -exported-symbols argument is not allowed" exit $EXIT_FAILURE fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework|-arch|-isysroot) case " $CC " in *" ${arg} ${1} "* | *" ${arg} ${1} "*) prev=darwin_framework_skip ;; *) compiler_flags="$compiler_flags $arg" prev=darwin_framework ;; esac compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" ;; esac continue ;; -L*) dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" notinst_path="$notinst_path $dir" fi dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; *) dllsearchpath="$dllsearchpath:$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework deplibs="$deplibs -framework System" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. -model) compile_command="$compile_command $arg" compiler_flags="$compiler_flags $arg" finalize_command="$finalize_command $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) compiler_flags="$compiler_flags $arg" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" continue ;; -module) module=yes continue ;; # -64, -mips[0-9] enable 64-bit mode on the SGI compiler # -r[0-9][0-9]* specifies the processor on the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler # +DA*, +DD* enable 64-bit mode on the HP compiler # -q* pass through compiler args for the IBM compiler # -m* pass through architecture-specific compiler args for GCC # -m*, -t[45]*, -txscale* pass through architecture-specific # compiler args for GCC # -pg pass through profiling flag for GCC # @file GCC response files -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ -t[45]*|-txscale*|@*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" compiler_flags="$compiler_flags $arg" continue ;; -shrext) prev=shrext continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # The PATH hackery in wrapper scripts is required on Windows # in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit $EXIT_FAILURE ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -static) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Wl,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $wl$flag" linker_flags="$linker_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # Some other compiler flag. -* | +*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; *.$objext) # A standard object. objs="$objs $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then pic_object= non_pic_object= # Read the .lo file # If there is no directory component, then add one. case $arg in */* | *\\*) . $arg ;; *) . ./$arg ;; esac if test -z "$pic_object" || \ test -z "$non_pic_object" || test "$pic_object" = none && \ test "$non_pic_object" = none; then $echo "$modename: cannot find name of object for \`$arg'" 1>&2 exit $EXIT_FAILURE fi # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. libobjs="$libobjs $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object non_pic_objects="$non_pic_objects $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi else # Only an error if not doing a dry-run. if test -z "$run"; then $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 exit $EXIT_FAILURE else # Dry-run case. # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` libobjs="$libobjs $pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi done # argument parsing loop if test -n "$prev"; then $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi oldlibs= # calculate the name of the file, without its directory outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi # Create the object directory. if test ! -d "$output_objdir"; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir exit_status=$? if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then exit $exit_status fi fi # Determine the type of output case $output in "") $echo "$modename: you must specify an output file" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac case $host in *cygwin* | *mingw* | *pw32*) # don't eliminate duplications in $postdeps and $predeps duplicate_compiler_generated_deps=yes ;; *) duplicate_compiler_generated_deps=$duplicate_deps ;; esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if test "X$duplicate_deps" = "Xyes" ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; esac pre_post_deps="$pre_post_deps $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries case $linkmode in lib) passes="conv link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 exit $EXIT_FAILURE ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else compiler_flags="$compiler_flags $deplib" fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then library_names= old_library= case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; *) $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` if eval $echo \"$deplib\" 2>/dev/null \ | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then $echo $echo "*** Warning: Trying to link with static lib archive $deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because the file extensions .$libext of this argument makes me believe" $echo "*** that it is just a static archive that I should not used here." else $echo $echo "*** Warning: Linking the shared library $output against the" $echo "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 exit $EXIT_FAILURE fi # Check to see that this really is a libtool archive. if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." dlname= dlopen= dlpreopen= libdir= library_names= old_library= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit $EXIT_FAILURE fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then $echo "$modename: \`$lib' is not a convenience library" 1>&2 exit $EXIT_FAILURE fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit $EXIT_FAILURE fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 exit $EXIT_FAILURE fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. dlprefiles="$dlprefiles $lib $dependency_libs" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 abs_ladir="$ladir" fi ;; esac laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then $echo "$modename: warning: library \`$lib' was moved." 1>&2 dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi fi # $installed = yes name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 exit $EXIT_FAILURE fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; *) temp_rpath="$temp_rpath $absdir" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes ; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi # This is a shared library # Warn about portability, can't link against -module's on # some systems (darwin) if test "$shouldnotlink" = yes && test "$pass" = link ; then $echo if test "$linkmode" = prog; then $echo "*** Warning: Linking the executable $output against the loadable module" else $echo "*** Warning: Linking the shared library $output against the loadable module" fi $echo "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names realname="$2" shift; shift libname=`eval \\$echo \"$libname_spec\"` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw*) major=`expr $current - $age` versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" soname=`$echo $soroot | ${SED} -e 's/^.*\///'` newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else $show "extracting exported symbol list from \`$soname'" save_ifs="$IFS"; IFS='~' cmds=$extract_expsyms_cmds for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else $show "generating import library for \`$soname'" save_ifs="$IFS"; IFS='~' cmds=$old_archive_from_expsyms_cmds for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a module then we can not link against # it, someone is ignoring the new warnings I added if /usr/bin/file -L $add 2> /dev/null | $EGREP ": [^:]* bundle" >/dev/null ; then $echo "** Warning, lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $echo $echo "** And there doesn't seem to be a static archive available" $echo "** The link will probably fail, sorry" else add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then $echo "$modename: configuration error: unsupported hardcode properties" exit $EXIT_FAILURE fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && \ test "$hardcode_minus_L" != yes && \ test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. $echo $echo "*** Warning: This system can not link to static lib archive $lib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then $echo "*** But as you try to build a module library, libtool will still create " $echo "*** a static module, that should work as long as the dlopening application" $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then $echo $echo "*** However, this would only work if libtool was able to extract symbol" $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" $echo "*** not find such a program. So, this module is probably useless." $echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$deplib" && dir="." # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" fi ;; esac if grep "^installed=no" $deplib > /dev/null; then path="$absdir/$objdir" else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi if test "$absdir" != "$libdir"; then $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 fi path="$absdir" fi depdepl= case $host in *-*-darwin*) # we do not want to link against static libs, # but need to link against shared eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$path/$depdepl" ; then depdepl="$path/$depdepl" fi # do not add paths which are already there case " $newlib_search_path " in *" $path "*) ;; *) newlib_search_path="$newlib_search_path $path";; esac fi path="" ;; *) path="-L$path" ;; esac ;; -l*) case $host in *-*-darwin*) # Again, we only want to link against shared libraries eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` for tmp in $newlib_search_path ; do if test -f "$tmp/lib$tmp_libs.dylib" ; then eval depdepl="$tmp/lib$tmp_libs.dylib" break fi done path="" ;; *) continue ;; esac ;; *) continue ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac case " $deplibs " in *" $depdepl "*) ;; *) deplibs="$depdepl $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then tmp_libs="$tmp_libs $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 fi if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 fi # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) if test "$module" = no; then $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 exit $EXIT_FAILURE else $echo $echo "*** Warning: Linking the shared library $output against the non-libtool" $echo "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi if test "$dlself" != no; then $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 fi set dummy $rpath if test "$#" -gt 2; then $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 fi else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 IFS="$save_ifs" if test -n "$8"; then $echo "$modename: too many parameters to \`-version-info'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$2" number_minor="$3" number_revision="$4" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows) current=`expr $number_major + $number_minor` age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) current=`expr $number_major + $number_minor - 1` age="$number_minor" revision="$number_minor" ;; esac ;; no) current="$2" revision="$3" age="$4" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE ;; esac if test "$age" -gt "$current"; then $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header major=.`expr $current - $age` versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current"; ;; irix | nonstopux) major=`expr $current - $age + 1` case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do iface=`expr $revision - $loop` loop=`expr $loop - 1` verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) major=.`expr $current - $age` versuffix="$major.$age.$revision" ;; osf) major=.`expr $current - $age` versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do iface=`expr $current - $loop` loop=`expr $loop - 1` verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. major=`expr $current - $age` versuffix="-$major" ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit $EXIT_FAILURE ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$echo "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi removelist="$removelist $p" ;; *) ;; esac done if test -n "$removelist"; then $show "${rm}r $removelist" $run ${rm}r $removelist fi fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. for path in $notinst_path; do lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs -framework System" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $rm conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null \ | grep " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ | ${SED} 10q \ | $EGREP "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $echo $echo "*** Warning: linker path does not have real file for library $a_deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $echo "*** with $libname but no candidates were found. (...for file magic test)" else $echo "*** with $libname and none of the candidates passed a file format test" $echo "*** using a file magic. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do name=`expr $a_deplib : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) newdeplibs="$newdeplibs $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval \\$echo \"$libname_spec\"` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval $echo \"$potent_lib\" 2>/dev/null \ | ${SED} 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $echo $echo "*** Warning: linker path does not have real file for library $a_deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $echo "*** with $libname but no candidates were found. (...for regex pattern test)" else $echo "*** with $libname and none of the candidates passed a file format test" $echo "*** using a regex pattern. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ -e 's/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` done fi if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ | grep . >/dev/null; then $echo if test "X$deplibs_check_method" = "Xnone"; then $echo "*** Warning: inter-library dependencies are not supported in this platform." else $echo "*** Warning: inter-library dependencies are not known to be supported." fi $echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then $echo $echo "*** Warning: libtool could not satisfy all declared inter-library" $echo "*** dependencies of module $libname. Therefore, libtool will create" $echo "*** a static module, that should work as long as the dlopening" $echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then $echo $echo "*** However, this would only work if libtool was able to extract symbol" $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" $echo "*** not find such a program. So, this module is probably useless." $echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else $echo "*** The inter-library dependencies that have been dropped here will be" $echo "*** automatically added whenever a program is linked with this library" $echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then $echo $echo "*** Since this library must not contain undefined symbols," $echo "*** because either the platform does not support them or" $echo "*** it was explicitly requested with -no-undefined," $echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names realname="$2" shift; shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do linknames="$linknames $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" if len=`expr "X$cmd" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then $show "$cmd" $run eval "$cmd" || exit $? skipped_export=false else # The command line is too long to execute in one step. $show "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex"; then $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' $show "$mv \"${export_symbols}T\" \"$export_symbols\"" $run eval '$mv "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $convenience libobjs="$libobjs $func_extract_archives_result" fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise. $echo "creating reloadable object files..." # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output output_la=`$echo "X$output" | $Xsed -e "$basename"` # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= delfiles= last_robj= k=1 output=$output_objdir/$output_la-${k}.$objext # Loop over the list of objects to be linked. for obj in $save_libobjs do eval test_cmds=\"$reload_cmds $objlist $last_robj\" if test "X$objlist" = X || { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len"; }; then objlist="$objlist $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else # All subsequent reloadable object files will link in # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext k=`expr $k + 1` output=$output_objdir/$output_la-${k}.$objext objlist=$obj len=1 fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if ${skipped_export-false}; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols libobjs=$output # Append the command to create the export file. eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" fi # Set up a command to remove the reloadable object files # after they are used. i=0 while test "$i" -lt "$k" do i=`expr $i + 1` delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" done $echo "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi # Append the command to remove the reloadable object files # to the just-reset $cmds. eval cmds=\"\$cmds~\$rm $delfiles\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then $show "${rm}r $gentop" $run ${rm}r "$gentop" fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 fi case $output in *.lo) if test -n "$objs$old_deplibs"; then $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 exit $EXIT_FAILURE fi libobj="$output" obj=`$echo "X$output" | $Xsed -e "$lo2o"` ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $run $rm $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" generated="$generated $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" cmds=$reload_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $run eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" cmds=$reload_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; esac if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 fi if test "$preload" = yes; then if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && test "$dlopen_self_static" = unknown; then $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." fi fi case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac case $host in *darwin*) # Don't allow lazy linking, it breaks C++ global constructors if test "$tagname" = CXX ; then compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" fi ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done compile_deplibs="$new_libs" compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; *) dllsearchpath="$dllsearchpath:$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then dlsyms="${outputname}S.c" else $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 fi fi if test -n "$dlsyms"; then case $dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${outputname}.nm" $show "$rm $nlist ${nlist}S ${nlist}T" $run $rm "$nlist" "${nlist}S" "${nlist}T" # Parse the name list into a source file. $show "creating $output_objdir/$dlsyms" test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ /* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ /* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ #ifdef __cplusplus extern \"C\" { #endif /* Prevent the only kind of declaration conflicts we can make. */ #define lt_preloaded_symbols some_other_symbol /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then $show "generating symbol list for \`$output'" test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for arg in $progfiles; do $show "extracting global C symbols from \`$arg'" $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi if test -n "$export_symbols_regex"; then $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $run $rm $export_symbols $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* ) $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac else $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* ) $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac fi fi for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` $run eval '$echo ": $name " >> "$nlist"' $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -z "$run"; then # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $mv "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if grep -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else grep -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' else $echo '/* NONE */' >> "$output_objdir/$dlsyms" fi $echo >> "$output_objdir/$dlsyms" "\ #undef lt_preloaded_symbols #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ " case $host in *cygwin* | *mingw* ) $echo >> "$output_objdir/$dlsyms" "\ /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs */ struct { " ;; * ) $echo >> "$output_objdir/$dlsyms" "\ const struct { " ;; esac $echo >> "$output_objdir/$dlsyms" "\ const char *name; lt_ptr address; } lt_preloaded_symbols[] = {\ " eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" $echo >> "$output_objdir/$dlsyms" "\ {0, (lt_ptr) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " fi pic_flag_for_symtable= case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; esac;; *-*-hpux*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag";; esac esac # Now compile the dynamic symbol file. $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. case $host in *cygwin* | *mingw* ) if test -f "$output_objdir/${outputname}.def" ; then compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` else compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` fi ;; * ) compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` ;; esac ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 exit $EXIT_FAILURE ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi if test "$need_relink" = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" exit_status=$? # Delete the generated files. if test -n "$dlsyms"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi exit $exit_status fi if test -n "$shlibpath_var"; then # We should set the shlibpath_var rpath= for dir in $temp_rpath; do case $dir in [\\/]* | [A-Za-z]:[\\/]*) # Absolute path. rpath="$rpath$dir:" ;; *) # Relative path: add a thisdir entry. rpath="$rpath\$thisdir/$dir:" ;; esac done temp_rpath="$rpath" fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $run $rm $output # Link the executable and exit $show "$link_command" $run eval "$link_command" || exit $? exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 $echo "$modename: \`$output' will be relinked during installation" 1>&2 else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname $show "$link_command" $run eval "$link_command" || exit $? # Now create the wrapper script. $show "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $echo for shipping. if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then case $progpath in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; esac qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if our run command is non-null. if test -z "$run"; then # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) output_name=`basename $output` output_path=`dirname $output` cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $rm $cwrappersource $cwrapper trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 cat > $cwrappersource <> $cwrappersource<<"EOF" #include #include #include #include #include #include #include #include #include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) /* -DDEBUG is fairly common in CFLAGS. */ #undef DEBUG #if defined DEBUGWRAPPER # define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) #else # define DEBUG(format, ...) #endif const char *program_name = NULL; void * xmalloc (size_t num); char * xstrdup (const char *string); const char * base_name (const char *name); char * find_executable(const char *wrapper); int check_executable(const char *path); char * strendzap(char *str, const char *pat); void lt_fatal (const char *message, ...); int main (int argc, char *argv[]) { char **newargz; int i; program_name = (char *) xstrdup (base_name (argv[0])); DEBUG("(main) argv[0] : %s\n",argv[0]); DEBUG("(main) program_name : %s\n",program_name); newargz = XMALLOC(char *, argc+2); EOF cat >> $cwrappersource <> $cwrappersource <<"EOF" newargz[1] = find_executable(argv[0]); if (newargz[1] == NULL) lt_fatal("Couldn't find %s", argv[0]); DEBUG("(main) found exe at : %s\n",newargz[1]); /* we know the script has the same name, without the .exe */ /* so make sure newargz[1] doesn't end in .exe */ strendzap(newargz[1],".exe"); for (i = 1; i < argc; i++) newargz[i+1] = xstrdup(argv[i]); newargz[argc+1] = NULL; for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" return 127; } void * xmalloc (size_t num) { void * p = (void *) malloc (num); if (!p) lt_fatal ("Memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL ; } const char * base_name (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha ((unsigned char)name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return base; } int check_executable(const char * path) { struct stat st; DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); if ((!path) || (!*path)) return 0; if ((stat (path, &st) >= 0) && ( /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ #if defined (S_IXOTH) ((st.st_mode & S_IXOTH) == S_IXOTH) || #endif #if defined (S_IXGRP) ((st.st_mode & S_IXGRP) == S_IXGRP) || #endif ((st.st_mode & S_IXUSR) == S_IXUSR)) ) return 1; else return 0; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise */ char * find_executable (const char* wrapper) { int has_slash = 0; const char* p; const char* p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char* concat_name; DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable(concat_name)) return concat_name; XFREE(concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable(concat_name)) return concat_name; XFREE(concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char* path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char* q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR(*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen(tmp); concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable(concat_name)) return concat_name; XFREE(concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen(tmp); concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable(concat_name)) return concat_name; XFREE(concat_name); return NULL; } char * strendzap(char *str, const char *pat) { size_t len, patlen; assert(str != NULL); assert(pat != NULL); len = strlen(str); patlen = strlen(pat); if (patlen <= len) { str += len - patlen; if (strcmp(str, pat) == 0) *str = '\0'; } return str; } static void lt_error_core (int exit_status, const char * mode, const char * message, va_list ap) { fprintf (stderr, "%s: %s: ", program_name, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, "FATAL", message, ap); va_end (ap); } EOF # we should really use a build-platform specific compiler # here, but OTOH, the wrappers (shell script and this C one) # are only useful if you want to execute the "real" binary. # Since the "real" binary is built for $host, then this # wrapper might as well be built for $host, too. $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource ;; esac $rm $output trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 $echo > $output "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variable: notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$echo are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then echo=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then # Yippee, \$echo works! : else # Restart under the correct shell, and then maybe \$echo will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $echo >> $output "\ # Find the directory that this script lives in. thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $echo >> $output "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || \\ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $mkdir \"\$progdir\" else $rm \"\$progdir/\$file\" fi" $echo >> $output "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $echo \"\$relink_command_output\" >&2 $rm \"\$progdir/\$file\" exit $EXIT_FAILURE fi fi $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $rm \"\$progdir/\$program\"; $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } $rm \"\$progdir/\$file\" fi" else $echo >> $output "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $echo >> $output "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $echo >> $output "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $echo >> $output "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $echo >> $output "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $echo >> $output "\ exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $echo >> $output "\ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" exit $EXIT_FAILURE fi else # The program doesn't exist. \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 $echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit $EXIT_FAILURE fi fi\ " chmod +x $output fi exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $addlibs oldobjs="$oldobjs $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do $echo "X$obj" | $Xsed -e 's%^.*/%%' done | sort | sort -uc >/dev/null 2>&1); then : else $echo "copying selected object files to avoid basename conflicts..." if test -z "$gentop"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "$mkdir $gentop" $run $mkdir "$gentop" exit_status=$? if test "$exit_status" -ne 0 && test ! -d "$gentop"; then exit $exit_status fi fi save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase counter=`expr $counter + 1` case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" $run ln "$obj" "$gentop/$newobj" || $run cp "$obj" "$gentop/$newobj" oldobjs="$oldobjs $gentop/$newobj" ;; *) oldobjs="$oldobjs $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" if len=`expr "X$cmds" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts $echo "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done for obj in $save_oldobjs do oldobjs="$objlist $obj" objlist="$objlist $obj" eval test_cmds=\"$old_archive_cmds\" if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do eval cmd=\"$cmd\" IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$generated"; then $show "${rm}r$generated" $run ${rm}r$generated fi # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" $show "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. if test -z "$run"; then for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi newdlfiles="$newdlfiles $libdir/$name" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi newdlprefiles="$newdlprefiles $libdir/$name" done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlfiles="$newdlfiles $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlprefiles="$newdlprefiles $abs" done dlprefiles="$newdlprefiles" fi $rm $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $echo > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $echo >> $output "\ relink_command=\"$relink_command\"" fi done fi # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? ;; esac exit $EXIT_SUCCESS ;; # libtool install mode install) modename="$modename: install" # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $echo "X$nonopt" | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac install_prog="$arg " arg="$1" shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac install_prog="$install_prog$arg" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) case " $install_prog " in *[\\\ /]cp\ *) ;; *) prev=$arg ;; esac ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac install_prog="$install_prog $arg" done if test -z "$install_prog"; then $echo "$modename: you must specify an install program" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi if test -n "$prev"; then $echo "$modename: the \`$prev' option requires an argument" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi if test -z "$files"; then if test -z "$dest"; then $echo "$modename: no file or destination specified" 1>&2 else $echo "$modename: you must specify a destination" 1>&2 fi $echo "$help" 1>&2 exit $EXIT_FAILURE fi # Strip any trailing slash from the destination. dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` test "X$destdir" = "X$dest" && destdir=. destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` # Not a directory, so check to see that there is only one file specified. set dummy $files if test "$#" -gt 2; then $echo "$modename: \`$dest' is not a directory" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi library_names= old_library= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ test "X$dir" = "X$file/" && dir= dir="$dir$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. if test "$inst_prefix_dir" = "$destdir"; then $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 exit $EXIT_FAILURE fi if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi $echo "$modename: warning: relinking \`$file'" 1>&2 $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 exit $EXIT_FAILURE fi fi # See the names of the shared library. set dummy $library_names if test -n "$2"; then realname="$2" shift shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. $show "$install_prog $dir/$srcname $destdir/$realname" $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$striplib $destdir/$realname" $run eval "$striplib $destdir/$realname" || exit $? fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do if test "$linkname" != "$realname"; then $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" fi done fi # Do each command in the postinstall commands. lib="$destdir/$realname" cmds=$postinstall_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' fi exit $lt_exit } done IFS="$save_ifs" fi # Install the pseudo-library for information purposes. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` instname="$dir/$name"i $show "$install_prog $instname $destdir/$name" $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` ;; *.$objext) staticdest="$destfile" destfile= ;; *) $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; esac # Install the libtool object if requested. if test -n "$destfile"; then $show "$install_prog $file $destfile" $run eval "$install_prog $file $destfile" || exit $? fi # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` $show "$install_prog $staticobj $staticdest" $run eval "$install_prog \$staticobj \$staticdest" || exit $? fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then file=`$echo $file|${SED} 's,.exe$,,'` stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin*|*mingw*) wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` ;; *) wrapper=$file ;; esac if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then notinst_deplibs= relink_command= # Note that it is not necessary on cygwin/mingw to append a dot to # foo even if both foo and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. # # If there is no directory component, then add one. case $wrapper in */* | *\\*) . ${wrapper} ;; *) . ./${wrapper} ;; esac # Check the variables that should have been set. if test -z "$notinst_deplibs"; then $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 exit $EXIT_FAILURE fi finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then # If there is no directory component, then add one. case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac fi libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 finalize=no fi done relink_command= # Note that it is not necessary on cygwin/mingw to append a dot to # foo even if both foo and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. # # If there is no directory component, then add one. case $wrapper in */* | *\\*) . ${wrapper} ;; *) . ./${wrapper} ;; esac outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then tmpdir=`func_mktempdir` file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 ${rm}r "$tmpdir" continue fi file="$outputname" else $echo "$modename: warning: cannot relink \`$file'" 1>&2 fi else # Install the binary that we compiled earlier. file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` ;; esac ;; esac $show "$install_prog$stripme $file $destfile" $run eval "$install_prog\$stripme \$file \$destfile" || exit $? test -n "$outputname" && ${rm}r "$tmpdir" ;; esac done for file in $staticlibs; do name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` # Set up the ranlib parameters. oldlib="$destdir/$name" $show "$install_prog $file $oldlib" $run eval "$install_prog \$file \$oldlib" || exit $? if test -n "$stripme" && test -n "$old_striplib"; then $show "$old_striplib $oldlib" $run eval "$old_striplib $oldlib" || exit $? fi # Do each command in the postinstall commands. cmds=$old_postinstall_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$future_libdirs"; then $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 fi if test -n "$current_libdirs"; then # Maybe just do a dry run. test -n "$run" && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi ;; # libtool finish mode finish) modename="$modename: finish" libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. cmds=$finish_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || admincmds="$admincmds $cmd" done IFS="$save_ifs" fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $run eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. test "$show" = : && exit $EXIT_SUCCESS $echo "X----------------------------------------------------------------------" | $Xsed $echo "Libraries have been installed in:" for libdir in $libdirs; do $echo " $libdir" done $echo $echo "If you ever happen to want to link against installed libraries" $echo "in a given directory, LIBDIR, you must either use libtool, and" $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" $echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" $echo " during execution" fi if test -n "$runpath_var"; then $echo " - add LIBDIR to the \`$runpath_var' environment variable" $echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $echo " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $echo " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi $echo $echo "See any operating system documentation about shared libraries for" $echo "more information, such as the ld(1) and ld.so(8) manual pages." $echo "X----------------------------------------------------------------------" | $Xsed exit $EXIT_SUCCESS ;; # libtool execute mode execute) modename="$modename: execute" # The first argument is the command name. cmd="$nonopt" if test -z "$cmd"; then $echo "$modename: you must specify a COMMAND" 1>&2 $echo "$help" exit $EXIT_FAILURE fi # Handle -dlopen flags immediately. for file in $execute_dlfiles; do if test ! -f "$file"; then $echo "$modename: \`$file' is not a file" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi dir= case $file in *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi # Read the libtool library. dlname= library_names= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" continue fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 exit $EXIT_FAILURE fi ;; *.lo) # Just add the directory containing the .lo file. dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. ;; *) $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` args="$args \"$file\"" done if test -z "$run"; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables if test "${save_LC_ALL+set}" = set; then LC_ALL="$save_LC_ALL"; export LC_ALL fi if test "${save_LANG+set}" = set; then LANG="$save_LANG"; export LANG fi # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" $echo "export $shlibpath_var" fi $echo "$cmd$args" exit $EXIT_SUCCESS fi ;; # libtool clean and uninstall mode clean | uninstall) modename="$modename: $mode" rm="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) rm="$rm $arg"; rmforce=yes ;; -*) rm="$rm $arg" ;; *) files="$files $arg" ;; esac done if test -z "$rm"; then $echo "$modename: you must specify an RM program" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi rmdirs= origobjdir="$objdir" for file in $files; do dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$file"; then dir=. objdir="$origobjdir" else objdir="$dir/$origobjdir" fi name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` test "$mode" = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test "$mode" = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if (test -L "$file") >/dev/null 2>&1 \ || (test -h "$file") >/dev/null 2>&1 \ || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then . $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" case "$mode" in clean) case " $library_names " in # " " in the beginning catches empty $dlname *" $dlname "*) ;; *) rmfiles="$rmfiles $objdir/$dlname" ;; esac test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. cmds=$postuninstall_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" if test "$?" -ne 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. cmds=$old_postuninstall_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" if test "$?" -ne 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # Read the .lo file . $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" \ && test "$pic_object" != none; then rmfiles="$rmfiles $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" \ && test "$non_pic_object" != none; then rmfiles="$rmfiles $dir/$non_pic_object" fi fi ;; *) if test "$mode" = clean ; then noexename=$name case $file in *.exe) file=`$echo $file|${SED} 's,.exe$,,'` noexename=`$echo $name|${SED} 's,.exe$,,'` # $file with .exe has already been added to rmfiles, # add $file without .exe rmfiles="$rmfiles $file" ;; esac # Do a test to see if this is a libtool program. if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then relink_command= . $dir/$noexename # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi if test "X$noexename" != "X$name" ; then rmfiles="$rmfiles $objdir/lt-${noexename}.c" fi fi fi ;; esac $show "$rm $rmfiles" $run $rm $rmfiles || exit_status=1 done objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then $show "rmdir $dir" $run rmdir $dir >/dev/null 2>&1 fi done exit $exit_status ;; "") $echo "$modename: you must specify a MODE" 1>&2 $echo "$generic_help" 1>&2 exit $EXIT_FAILURE ;; esac if test -z "$exec_cmd"; then $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$generic_help" 1>&2 exit $EXIT_FAILURE fi fi # test -z "$show_help" if test -n "$exec_cmd"; then eval exec $exec_cmd exit $EXIT_FAILURE fi # We need to display help for each of the modes. case $mode in "") $echo \ "Usage: $modename [OPTION]... [MODE-ARG]... Provide generalized library-building support services. --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --finish same as \`--mode=finish' --help display this help message and exit --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] --quiet same as \`--silent' --silent don't print informational messages --tag=TAG use configuration variables from tag TAG --version print version information MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for a more detailed description of MODE. Report bugs to ." exit $EXIT_SUCCESS ;; clean) $echo \ "Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $echo \ "Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -static always build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $echo \ "Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $echo \ "Usage: $modename [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $echo \ "Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $echo \ "Usage: $modename [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -static do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $echo \ "Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; esac $echo $echo "Try \`$modename --help' for more information about other modes." exit $? # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared disable_libs=shared # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static disable_libs=static # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: Cbc-2.8.12/missing0000755000076600007660000002540611405215312012351 0ustar coincoin#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2005-06-08.21 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). case "$1" in lex|yacc) # Not GNU programs, they don't have --version. ;; tar) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: Cbc-2.8.12/osi-cbc.pc.in0000644000076600007660000000043211510112067013212 0ustar coincoinprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@/coin Name: OsiCbc Description: COIN-OR Open Solver Interface for CBC URL: https://projects.coin-or.org/Osi Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lOsiCbc Cflags: -I${includedir} Requires: cbc Cbc-2.8.12/README0000644000076600007660000002107212171207002011623 0ustar coincoinCBC README ========== Welcome to the README for the COIN Branch and Cut Solver (CBC). CBC is distributed under the Eclipse Public License and is freely redistributable. All source code and documentation is Copyright IBM and others. This README may be redistributed freely. DOCUMENTATION ============= For a quick start guide, please see the INSTALL file in this distribution. A (somehwat outdated) user's manual is available here: http://www.coin-or.org/Cbc More up-to-date automatically generated documentation of the source code can be found here: http://www.coin-or.org/Doxygen/Cbc/ Further information can be found here: http://projects.coin-or.org/Cbc WHAT'S NEW ========== Release 2.8.3: 1. Fix for handling SOS. Release 2.8.2: 1. Fixed recognition of Glpk source in main configure. 2. Minor bugfixes in CoinUtils, Clp, and Cbc. Release 2.8.1: Ted, please fill this in! Release 2.8.0: 1. Introduced new secondaryStatus 8 to indicate that solving stopped due to an iteration limit. 2. Solution pool is now accessible via the command line and the CbcMain* interface. 3. New mipstart option to read an initial feasible solution from a file. Only values for discrete variables need to be provided. 4. Added Proximity Search heuristic by Fischetti and Monaci (off by default): The simplest way to switch it on using stand-alone version is "-proximity on". Proximity Search is the new "No-Neighborhood Search" 0-1 MIP refinement heuristic recently proposed by Fischetti and Monaci (2012). The idea is to define a sub-MIP without additional constraints but with a modified objective function intended to attract the search in the proximity of the incumbent. The approach works well for 0-1 MIPs whose solution landscape is not too irregular (meaning the there is reasonable probability of finding an improved solution by flipping a small number of binary variables), in particular when it is applied to the first heuristic solutions found at the root node. 5. An implementation of Zero-Half-Cuts by Alberto Caprara is now available. By default, these cuts are off. To use add to your command line -zerohalfCuts root (or other options) or just -zero. So far, they may help only on a small subset of problems and may need some tuning. The implementation of these cuts is described in G. Andreello, A. Caprara, and M. Fischetti "Embedding Cuts in a Branch and Cut Framework: a Computational Study with {0,1/2}-Cuts" INFORMS Journal on Computing 19(2), 229-238, 2007 http://dx.doi.org/10.1287/ijoc.1050.0162 6. An alternative implementation of a reduce and split cut generator by Giacomo Nannicini is now available. By default, these cuts are off. To use add to your command line -reduce2AndSplitCuts root (or other options). The implementation of these cuts is described in G. Cornuejols and G. Nannicini "Practical strategies for generating rank-1 split cuts in mixed-integer linear programming" Mathematical Programming Computation 3(4), 281-318, 2011 http://dx.doi.org/10.1007/s12532-011-0028-6 7. An alternative robust implementation of a Gomory cut generator by Giacomo Nannicini is now available. By default, these cuts are off. To use add to your command line -GMI root (or other options). The implementation of these cuts is described in G. Cornuejols, F. Margot, and G. Nannicini "On the safety of Gomory cut generators" http://faculty.sutd.edu.sg/~nannicini/index.php?page=publications 8. To encourage the use of some of the more exotic/expensive cut generators a parameter -slowcutpasses has been added. The idea is that the code does these cuts just a few times - less than the more usual cuts. The default is 10. The cut generators identified by "may be slow" at present are just Lift and project and ReduceAndSplit (both versions). 9. Allow initialization of random seed by user. Pseudo-random numbers are used in Cbc and Clp. In Clp they are used to break ties in degenerate problems, while in Cbc heuristics such as the Feasibility Pump use them to decide whether to round up or down. So if a different pseudo-random seed is given to Clp then you may get a different continuous optimum and so different cuts and heuristic solutions. This can be switched on by setting randomSeed for Clp and/or randomCbcSeed for Cbc. The special value of 0 tells code to use time of day for initial seed. 10. Building on this idea, Andrea Lodi, Matteo Fischetti, Michele Monaci, Domenico Salvagnin, Yuji Shinano, and Andrea Tramontani suggest that this idea be improved by running at the root node with multiple copies of solver, each with its own different seed and then passing in the solutions and cuts so that the main solver has a richer set of solutions and possibly stronger cuts. This is switched on by setting -multipleRootPasses. These can also be done in parallel. 11. Few changes to presolve for special variables and badly scaled problems (in CoinUtils). 12. New option -extraVariables which switches on a trivial re-formulation that introduces extra integer variables to group together variables with same cost. 13. For some problems, cut generators and general branching work better if the problem would be infeasible if the cost is too high. If the new option -constraintFromCutoff is set, the objective function is added as a constraint which rhs is set to the current cutoff value (objective value of best known solution). Release 2.7.8: Look at https://projects.coin-or.org/Cbc/changeset?old_path=%2Freleases%2F2.7.7&new_path=%2Freleases%2F2.7.8 to see all changes. 1. Change message when LP simplex iteration limit is hit from "Exiting on maximum nodes" to "Exiting on maximum number of iterations" 2. Fix for using overlapping SOS. 3. Fixes in buildsystem. Release 2.7.7: Look at https://projects.coin-or.org/Cbc/changeset?old_path=%2Freleases%2F2.7.6&new_path=%2Freleases%2F2.7.7 to see all changes. 1. Fix to report interruption on user event if SIGINT is received by CbcSolver. model->status() should now be 5 if this event happened. Added method CbcModel::sayEventHappened() to make cbc stop due to an 'user event'. 2. Other minor fixes. Release 2.7.6: Look at https://projects.coin-or.org/Cbc/changeset?old_path=%2Freleases%2F2.7.5&new_path=%2Freleases%2F2.7.6 to see all changes. 1. Fixes to build system. 2. Other minor fixes. Release 2.7.5: Look at https://projects.coin-or.org/Cbc/changeset?old_path=%2Freleases%2F2.7.4&new_path=%2Freleases%2F2.7.5 to see all changes. 1. Fixes to get AMPL interface working again. 2. More fixes to MSVC++ files. Release 2.7.4: Look at https://projects.coin-or.org/Cbc/changeset?old_path=%2Freleases%2F2.7.3&new_path=%2Freleases%2F2.7.4 to see all changes. 1. Minor bugfixes. Release 2.7.3: Look at https://projects.coin-or.org/Cbc/changeset?old_path=%2Freleases%2F2.7.2&new_path=%2Freleases%2F2.7.3 to see all changes. 1. Minor bugfixes. 2. Fixes to MSVC++ files. Release 2.7.2: Look at https://projects.coin-or.org/Cbc/changeset?old_path=%2Freleases%2F2.7.1&new_path=%2Freleases%2F2.7.2 to see all changes. 1. Allow row/column names for GMPL models. 2. Added CbcModel::haveMultiThreadSupport() to indicate whether Cbc library has been compiled with multithread support. 3. Added CbcModel::waitingForMiniBranchAndBound() to indicate whether sub-MIP heuristic is currently running. 4. Cbc shell should work with readline if configured with --enable-gnu-packages. 5. Support for compressed input files (.gz, .bz2) is now enabled by default. 6. Fix problems with relative gap tolerance > 100% and further bugs. 7. Fixes for MSVC++ Version 9 files. 8. Minor fixes in buildsystem; update to BuildTools 0.7.1. Release 2.7.1: Look at https://projects.coin-or.org/Cbc/changeset?old_path=%2Freleases%2F2.7.0&new_path=%2Freleases%2F2.7.1 to see all changes. 1. Fixes to MSVC++ files Release 2.7.0: 1. License has been changed to the EPL. 2. Support for MSVC++ version 10 added. 3. Support for BuildTools version 0.7 to incorporate recent enhancements, including proper library versioning in Linux, prohibiting installation of private headers, etc. 4. Updated externals to new stable versions of dependent projects. 5. Improvements to heuristics. 6. New options for cut generation. 7. Improved reporting of results. 8. Improvements to documentation. 9. Minor bug fixes. SUPPORT ======= 1. List Serve CBC users should use the Cbc mailing list. To subscribe, go to http://list.coin-or.org/mailman/listinfo/cbc 3. Bug Reports Bug reports should be reported on the CBC development web site at https://projects.coin-or.org/Cbc/newticket Cbc-2.8.12/test/0000755000076600007660000000000012377555230011741 5ustar coincoinCbc-2.8.12/test/OsiCbcSolverInterfaceTest.cpp0000644000076600007660000011647512101340057017461 0ustar coincoin// $Id: OsiCbcSolverInterfaceTest.cpp 1854 2013-01-28 00:02:55Z stefan $ // Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" //#include //#include //#include //#include #include "OsiCbcSolverInterface.hpp" #include "OsiCuts.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" #include "OsiUnitTests.hpp" #include "CoinMessage.hpp" #include "CoinModel.hpp" //############################################################################# namespace { CoinPackedMatrix &BuildExmip1Mtx () /* Simple function to build a packed matrix for the exmip1 example used in tests. The function exists solely to hide the intermediate variables. Probably could be written as an initialised declaration. See COIN/Mps/Sample/exmip1.mps for a human-readable presentation. Ordered triples seem easiest. They're listed in row-major order. */ { int rowndxs[] = { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4 } ; int colndxs[] = { 0, 1, 3, 4, 7, 1, 2, 2, 5, 3, 6, 0, 4, 7 } ; double coeffs[] = { 3.0, 1.0, -2.0, -1.0, -1.0, 2.0, 1.1, 1.0, 1.0, 2.8, -1.2, 5.6, 1.0, 1.9 } ; static CoinPackedMatrix exmip1mtx = CoinPackedMatrix(true,&rowndxs[0],&colndxs[0],&coeffs[0],14) ; return (exmip1mtx) ; } } //-------------------------------------------------------------------------- // test solution methods. void OsiCbcSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir) { { CoinRelFltEq eq; OsiCbcSolverInterface m; std::string fn = mpsDir+"exmip1"; m.readMps(fn.c_str(),"mps"); { OsiCbcSolverInterface im; OSIUNITTEST_ASSERT_ERROR(im.getNumCols() == 0, {}, "cbc", "default constructor"); OSIUNITTEST_ASSERT_ERROR(im.getModelPtr() != NULL, {}, "cbc", "default constructor"); } // Test copy constructor and assignment operator { OsiCbcSolverInterface lhs; { OsiCbcSolverInterface im(m); OsiCbcSolverInterface imC1(im); OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC1.getNumCols() == im.getNumCols(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC1.getNumRows() == im.getNumRows(), {}, "cbc", "copy constructor"); OsiCbcSolverInterface imC2(im); OSIUNITTEST_ASSERT_ERROR(imC2.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC2.getNumCols() == im.getNumCols(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC2.getNumRows() == im.getNumRows(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != imC2.getModelPtr(), {}, "cbc", "copy constructor"); lhs = imC2; } // Test that lhs has correct values even though rhs has gone out of scope OSIUNITTEST_ASSERT_ERROR(lhs.getModelPtr() != m.getModelPtr(), {}, "cbc", "assignment operator"); OSIUNITTEST_ASSERT_ERROR(lhs.getNumCols() == m.getNumCols(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(lhs.getNumRows() == m.getNumRows(), {}, "cbc", "copy constructor"); } // Test clone { OsiCbcSolverInterface cbcSi(m); OsiSolverInterface * siPtr = &cbcSi; OsiSolverInterface * siClone = siPtr->clone(); OsiCbcSolverInterface * cbcClone = dynamic_cast(siClone); OSIUNITTEST_ASSERT_ERROR(cbcClone != NULL, {}, "cbc", "clone"); OSIUNITTEST_ASSERT_ERROR(cbcClone->getModelPtr() != cbcSi.getModelPtr(), {}, "cbc", "clone"); OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumRows() == cbcSi.getNumRows(), {}, "cbc", "clone"); OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumCols() == m.getNumCols(), {}, "cbc", "clone"); delete siClone; } // test infinity { OsiCbcSolverInterface si; OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == OsiCbcInfinity, {}, "cbc", "infinity"); } // Test some catches if (!OsiCbcHasNDEBUG()) { OsiCbcSolverInterface solver; try { solver.setObjCoeff(0,0.0); OSIUNITTEST_ADD_OUTCOME("cbc", "setObjCoeff on empty model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false); } catch (CoinError e) { if (OsiUnitTest::verbosity >= 1) std::cout<<"Correct throw from setObjCoeff on empty model"<= 1) std::cout<<"Correct throw from setObjCoeff on empty model"<getMajorDim() == 5, return, "cbc", "getMatrixByRow: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim() == 8, return, "cbc", "getMatrixByRow: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByRow: num elements"); OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 6, return, "cbc", "getMatrixByRow: num elements"); #ifdef OSICBC_TEST_MTX_STRUCTURE CoinRelFltEq eq; const double * ev = smP->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[0], 3.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[1], 1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[2], -2.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[3], -1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[4], -1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[5], 2.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[6], 1.1), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[7], 1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[8], 1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[9], 2.8), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "getMatrixByRow: elements"); const int * mi = smP->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "getMatrixByRow: vector starts"); const int * ei = smP->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "getMatrixByRow: indices"); #else // OSICBC_TEST_MTX_STRUCTURE CoinPackedMatrix exmip1Mtx ; exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ; OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByRow") ; #endif // OSICBC_TEST_MTX_STRUCTURE } // Test adding several cuts, and handling of a coefficient of infinity // in the constraint matrix. { OsiCbcSolverInterface fim; std::string fn = mpsDir+"exmip1"; fim.readMps(fn.c_str(),"mps"); // exmip1.mps has 2 integer variables with index 2 & 3 fim.initialSolve(); OsiRowCut cuts[3]; // Generate one ineffective cut plus two trivial cuts int c; int nc = fim.getNumCols(); int *inx = new int[nc]; for (c=0;cgetMajorDim() == 8, return, "cbc", "getMatrixByCol: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim() == 5, return, "cbc", "getMatrixByCol: minor dim"); OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByCol: number of elements"); OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 9, return, "cbc", "getMatrixByCol: vector starts size"); #ifdef OSICBC_TEST_MTX_STRUCTURE CoinRelFltEq eq; const double * ev = smP->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 5.6), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2], 1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 2.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 1.1), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6],-2.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 2.8), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8],-1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11],-1.2), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12],-1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "getMatrixByCol: elements"); const CoinBigIndex * mi = smP->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 2, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 4, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 6, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 8, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 10, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[6] == 11, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[7] == 12, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[8] == 14, {}, "cbc", "getMatrixByCol: vector starts"); const int * ei = smP->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 1, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 3, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 4, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 2, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 3, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 4, {}, "cbc", "getMatrixByCol: indices"); #else // OSICBC_TEST_MTX_STRUCTURE CoinPackedMatrix &exmip1Mtx = BuildExmip1Mtx() ; OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByCol"); #endif // OSICBC_TEST_MTX_STRUCTURE } //-------------- // Test rowsense, rhs, rowrange, matrixByRow, solver assignment { OsiCbcSolverInterface lhs; { OsiCbcSolverInterface siC1(m); const char * siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense"); const double * siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "cbc", "right hand side"); const double * siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "cbc", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "cbc", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "cbc", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "cbc", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "cbc", "row range"); const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "cbc", "matrix by row"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim() == 5, return, "cbc", "matrix by row: major dim"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMinorDim() == 8, return, "cbc", "matrix by row: major dim"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "cbc", "matrix by row: num elements"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getSizeVectorStarts() == 6, return, "cbc", "matrix by row: num elements"); #ifdef OSICBC_TEST_MTX_STRUCTURE const double * ev = siC1mbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row: elements"); const CoinBigIndex * mi = siC1mbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row: vector starts"); const int * ei = siC1mbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row: indices"); #else // OSICBC_TEST_MTX_STRUCTURE CoinPackedMatrix exmip1Mtx ; exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ; OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*siC1mbr), {}, "cbc", "matrix by row"); #endif // OSICBC_TEST_MTX_STRUCTURE OSIUNITTEST_ASSERT_WARNING(siC1rs == siC1.getRowSense(), {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_WARNING(siC1rr == siC1.getRowRange(), {}, "cbc", "row range"); // Change CBC Model by adding free row OsiRowCut rc; rc.setLb(-COIN_DBL_MAX); rc.setUb( COIN_DBL_MAX); OsiCuts cuts; cuts.insert(rc); siC1.applyCuts(cuts); siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "cbc", "row sense after adding row"); siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5],0.0), {}, "cbc", "right hand side after adding row"); siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5],0.0), {}, "cbc", "row range after adding row"); lhs = siC1; } // Test that lhs has correct values even though siC1 has gone out of scope const char * lhsrs = lhs.getRowSense(); OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "cbc", "row sense after assignment"); const double * lhsrhs = lhs.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0],2.5), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1],2.1), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2],4.0), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3],5.0), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4],15.), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5],0.0), {}, "cbc", "right hand side after assignment"); const double *lhsrr = lhs.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0],0.0), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1],0.0), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2],0.0), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3],5.0-1.8), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4],15.0-3.0), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5],0.0), {}, "cbc", "row range after assignment"); const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, {}, "cbc", "matrix by row after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim() == 6, return, "cbc", "matrix by row after assignment: major dim"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "cbc", "matrix by row after assignment: num elements"); #ifdef OSICBC_TEST_MTX_STRUCTURE const double * ev = lhsmbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row after assignment: elements"); const CoinBigIndex * mi = lhsmbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row after assignment: vector starts"); const int * ei = lhsmbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row after assignment: indices"); #else // OSICBC_TEST_MTX_STRUCTURE /* This admittedly looks bogus, but it's the equivalent operation on the matrix for inserting a cut of the form -Inf <= +Inf (i.e., a cut with no coefficients). */ CoinPackedMatrix exmip1Mtx ; exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ; CoinPackedVector freeRow ; exmip1Mtx.appendRow(freeRow) ; OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*lhsmbr), {}, "cbc", "matrix by row after assignment"); #endif // OSICBC_TEST_MTX_STRUCTURE } } // Test add/delete columns { OsiCbcSolverInterface m; std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); double inf = m.getInfinity(); CoinPackedVector c0; c0.insert(0, 4); c0.insert(1, 1); m.addCol(c0, 0, inf, 3); m.initialSolve(); double objValue = m.getObjValue(); CoinRelFltEq eq(1.0e-2); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "cbc", "objvalue after adding col"); // Try deleting first column that's nonbasic at lower bound (0). int * d = new int[1]; CoinWarmStartBasis *cwsb = dynamic_cast(m.getWarmStart()) ; OSIUNITTEST_ASSERT_ERROR(cwsb != NULL, {}, "cbc", "get warmstart basis"); CoinWarmStartBasis::Status stati ; int iCol ; for (iCol = 0 ; iCol < cwsb->getNumStructural() ; iCol++) { stati = cwsb->getStructStatus(iCol) ; if (stati == CoinWarmStartBasis::atLowerBound) break ; } d[0]=iCol; m.deleteCols(1,d); delete [] d; delete cwsb; d=NULL; m.resolve(); objValue = m.getObjValue(); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting first col"); // Try deleting column we added. If basic, go to initialSolve as deleting // basic variable trashes basis required for warm start. iCol = m.getNumCols()-1; cwsb = dynamic_cast(m.getWarmStart()) ; stati = cwsb->getStructStatus(iCol) ; delete cwsb; m.deleteCols(1,&iCol); if (stati == CoinWarmStartBasis::basic) { m.initialSolve() ; } else { m.resolve(); } objValue = m.getObjValue(); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting added col"); } // Build a model { OsiCbcSolverInterface model; std::string fn = mpsDir+"p0033"; model.readMps(fn.c_str(),"mps"); // Point to data int numberRows = model.getNumRows(); const double * rowLower = model.getRowLower(); const double * rowUpper = model.getRowUpper(); int numberColumns = model.getNumCols(); const double * columnLower = model.getColLower(); const double * columnUpper = model.getColUpper(); const double * columnObjective = model.getObjCoefficients(); // get row copy CoinPackedMatrix rowCopy = *model.getMatrixByRow(); const int * column = rowCopy.getIndices(); const int * rowLength = rowCopy.getVectorLengths(); const CoinBigIndex * rowStart = rowCopy.getVectorStarts(); const double * element = rowCopy.getElements(); // solve model.initialSolve(); // Now build new model CoinModel build; // Row bounds int iRow; for (iRow=0;iRow=0;iRow--) { int start = rowStart[iRow]; for (int j=start;j=0) { int iColumn = triple.column(); if (iColumn*2setLogLevel(0); m.getModelPtr()->messageHandler()->setLogLevel(0); m.branchAndBound(); } // branch and bound using CbcModel!!!!!!! { OsiCbcSolverInterface mm; OsiCbcSolverInterface m(&mm); std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); m.initialSolve(); m.branchAndBound(); } // Do common solverInterface testing { OsiCbcSolverInterface m; OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir); } { OsiCbcSolverInterface mm; OsiCbcSolverInterface m(&mm); OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir); } } Cbc-2.8.12/test/CInterfaceTest.c0000644000076600007660000002313612376140747014757 0ustar coincoin/* $Id$ */ /* Copyright (C) 2014, International Business Machines Corporation and others. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). */ #undef NDEBUG /* force asserts to work */ #include "Cbc_C_Interface.h" #include #include #include #include static int callback_called = 0; void (COINLINKAGE_CB test_callback)(Cbc_Model * model,int msgno, int ndouble, const double * dvec, int nint, const int * ivec, int nchar, char ** cvec) { callback_called = 1; printf("In callback: message %d\n", msgno); } void testKnapsack() { Cbc_Model *model = Cbc_newModel(); /* Simple knapsack problem Maximize 5x[1] + 3x[2] + 2x[3] + 7x[4] + 4x[5] s.t. 2x[1] + 8x[2] + 4x[3] + 2x[4] + 5x[5] <= 10 All x binary */ CoinBigIndex start[] = {0, 1, 2, 3, 4, 5, 6}; int rowindex[] = {0, 0, 0, 0, 0}; double value[] = {2, 8, 4, 2, 5}; double collb[] = {0,0,0,0,0}; double colub[] = {1,1,1,1,1}; double obj[] = {5, 3, 2, 7, 4}; double feasible[] = {1,1,0,0,0}; double rowlb[] = {-INFINITY}; double rowub[] = {10}; const double *sol; const char* setname = "test model"; char *getname = malloc(20); int i; printf("Interface reports Cbc version %s\n", Cbc_getVersion()); Cbc_loadProblem(model, 5, 1, start, rowindex, value, collb, colub, obj, rowlb, rowub); Cbc_setColName(model, 2, "var2"); Cbc_setRowName(model, 0, "constr0"); assert(Cbc_getNumCols(model) == 5); assert(Cbc_getNumRows(model) == 1); for (i = 0; i < 5; i++) { Cbc_setInteger(model, i); assert(Cbc_isInteger(model,i)); } Cbc_setObjSense(model, -1); assert(Cbc_getObjSense(model) == -1); Cbc_setProblemName(model, setname); Cbc_registerCallBack(model, test_callback); Cbc_setInitialSolution(model, feasible); Cbc_solve(model); assert(Cbc_isProvenOptimal(model)); assert(!Cbc_isAbandoned(model)); assert(!Cbc_isProvenInfeasible(model)); assert(!Cbc_isContinuousUnbounded(model)); assert(!Cbc_isNodeLimitReached(model)); assert(!Cbc_isSecondsLimitReached(model)); assert(!Cbc_isSolutionLimitReached(model)); assert(fabs( Cbc_getObjValue(model)- (16.0) < 1e-6)); assert(fabs( Cbc_getBestPossibleObjValue(model)- (16.0) < 1e-6)); assert(callback_called == 1); sol = Cbc_getColSolution(model); assert(fabs(sol[0] - 1.0) < 1e-6); assert(fabs(sol[1] - 0.0) < 1e-6); assert(fabs(sol[2] - 0.0) < 1e-6); assert(fabs(sol[3] - 1.0) < 1e-6); assert(fabs(sol[4] - 1.0) < 1e-6); Cbc_problemName(model, 20, getname); i = strcmp(getname,setname); assert( (i == 0) ); Cbc_getColName(model, 2, getname, 20); i = strcmp(getname, "var2"); assert( (i == 0) ); Cbc_getRowName(model, 0, getname, 20); i = strcmp(getname, "constr0"); assert( (i == 0) ); assert( Cbc_maxNameLength(model) >= 7 ); Cbc_deleteModel(model); } /* void testProblemModification() { Cbc_Model *model = Cbc_newModel(); / * Simple knapsack problem Maximize 5x[1] + 3x[2] + 2x[3] + 7x[4] + 4x[5] s.t. 2x[1] + 8x[2] + 4x[3] + 2x[4] + 5x[5] <= 10 All x binary * / CoinBigIndex start[] = {0, 1, 2, 3, 4, 5, 6}; int rowindex[] = {0, 0, 0, 0, 0}; double value[] = {2, 8, 4, 2, 5}; double collb[] = {0,0,0,0,0}; double colub[] = {1,1,1,1,1}; double obj[] = {5, 3, 2, 7, 4}; double rowlb[] = {-INFINITY}; double rowub[] = {10}; const double *sol; int i; printf("Interface reports Cbc version %s\n", Cbc_getVersion()); Cbc_loadProblem(model, 5, 1, start, rowindex, value, collb, colub, obj, rowlb, rowub); for (i = 0; i < 5; i++) { Cbc_setInteger(model, i); assert(Cbc_isInteger(model,i)); } Cbc_setObjSense(model, -1); assert(Cbc_getObjSense(model) == -1); Cbc_solve(model); assert(Cbc_isProvenOptimal(model)); assert(fabs( Cbc_getObjValue(model)- (16.0) < 1e-6)); sol = Cbc_getColSolution(model); assert(fabs(sol[0] - 1.0) < 1e-6); assert(fabs(sol[1] - 0.0) < 1e-6); assert(fabs(sol[2] - 0.0) < 1e-6); assert(fabs(sol[3] - 1.0) < 1e-6); assert(fabs(sol[4] - 1.0) < 1e-6); Cbc_setColUpper(model, 0, 0.0); Cbc_solve(model); assert(Cbc_isProvenOptimal(model)); assert(fabs( Cbc_getObjValue(model)- (11.0) < 1e-6)); sol = Cbc_getColSolution(model); assert(fabs(sol[0] - 0.0) < 1e-6); assert(fabs(sol[1] - 0.0) < 1e-6); assert(fabs(sol[2] - 0.0) < 1e-6); assert(fabs(sol[3] - 1.0) < 1e-6); assert(fabs(sol[4] - 1.0) < 1e-6); Cbc_setColLower(model, 1, 1.0); assert(Cbc_isProvenOptimal(model)); assert(fabs( Cbc_getObjValue(model)- (10.0) < 1e-6)); sol = Cbc_getColSolution(model); assert(fabs(sol[0] - 0.0) < 1e-6); assert(fabs(sol[1] - 1.0) < 1e-6); assert(fabs(sol[2] - 0.0) < 1e-6); assert(fabs(sol[3] - 1.0) < 1e-6); assert(fabs(sol[4] - 0.0) < 1e-6); Cbc_deleteModel(model); } */ void testSOS() { Cbc_Model *model = Cbc_newModel(); /* Maximize 5x[1] + 3x[2] + 2x[3] + 7x[4] + 4x[5] s.t. x[1] + x[2] + x[3] + x[4] + x[5] == 1 All x binary */ CoinBigIndex start[] = {0, 0, 0, 0, 0, 0, 0}; double collb[] = {0,0,0,0,0}; double colub[] = {1,1,1,1,1}; double obj[] = {5, 3, 2, 7, 4}; int sosrowstart[] = {0,5}; int soscolindex[] = {0,1,2,3,4}; const double *sol; int i; Cbc_loadProblem(model, 5, 0, start, NULL, NULL, collb, colub, obj, NULL, NULL); assert(Cbc_getNumCols(model) == 5); assert(Cbc_getNumRows(model) == 0); for (i = 0; i < 5; i++) { Cbc_setInteger(model, i); assert(Cbc_isInteger(model,i)); } Cbc_setObjSense(model, -1); assert(Cbc_getObjSense(model) == -1); Cbc_addSOS(model,1,sosrowstart,soscolindex,obj,1); Cbc_solve(model); assert(Cbc_isProvenOptimal(model)); assert(!Cbc_isAbandoned(model)); assert(!Cbc_isProvenInfeasible(model)); assert(!Cbc_isContinuousUnbounded(model)); assert(!Cbc_isNodeLimitReached(model)); assert(!Cbc_isSecondsLimitReached(model)); assert(!Cbc_isSolutionLimitReached(model)); assert(fabs( Cbc_getObjValue(model)- (7.0) < 1e-6)); assert(fabs( Cbc_getBestPossibleObjValue(model)- (7.0) < 1e-6)); sol = Cbc_getColSolution(model); assert(fabs(sol[0] - 0.0) < 1e-6); assert(fabs(sol[1] - 0.0) < 1e-6); assert(fabs(sol[2] - 0.0) < 1e-6); assert(fabs(sol[3] - 1.0) < 1e-6); assert(fabs(sol[4] - 0.0) < 1e-6); Cbc_deleteModel(model); } void testIntegerInfeasible() { Cbc_Model *model = Cbc_newModel(); /* Minimize x * s.t. x <= -10 * x binary */ CoinBigIndex start[] = {0, 1}; int rowindex[] = {0}; double value[] = {1.0}; double rowlb[] = {-INFINITY}; double rowub[] = {-10}; double collb[] = {0.0}; double colub[] = {1.0}; double obj[] = {1.0}; Cbc_loadProblem(model, 1, 1, start, rowindex, value, collb, colub, obj, rowlb, rowub); Cbc_setInteger(model, 0); assert(Cbc_getNumCols(model) == 1); assert(Cbc_getNumRows(model) == 1); Cbc_solve(model); assert(!Cbc_isProvenOptimal(model)); assert(Cbc_isProvenInfeasible(model)); Cbc_deleteModel(model); } void testIntegerUnbounded() { Cbc_Model *model = Cbc_newModel(); /* http://list.coin-or.org/pipermail/cbc/2014-March/001276.html * Minimize x * s.t. x + y <= 3 * x - y == 0 * x,y Free * x integer */ CoinBigIndex start[] = {0,2,4}; int rowindex[] = {0, 1, 0, 1}; double value[] = {1, 1, 1, -1}; double rowlb[] = {-INFINITY, 0.0}; double rowub[] = {3.0,0.0}; double collb[] = {-INFINITY, -INFINITY}; double colub[] = {INFINITY, INFINITY}; double obj[] = {1.0,0.0}; Cbc_loadProblem(model, 2, 2, start, rowindex, value, collb, colub, obj, rowlb, rowub); Cbc_setInteger(model, 0); Cbc_setParameter(model, "log", "0"); printf("About to solve problem silently. You should see no output except \"Done\".\n"); Cbc_solve(model); printf("Done\n"); assert(!Cbc_isProvenOptimal(model)); assert(!Cbc_isProvenInfeasible(model)); assert(Cbc_isContinuousUnbounded(model)); Cbc_deleteModel(model); } void testIntegerBounds() { /* max 1.1x + 100.0z st x + z <= 3 0 <= x <= 3 0 <= z <= 1.5, Integer x* = 2, z* = 1 */ Cbc_Model *model = Cbc_newModel(); CoinBigIndex start[] = {0,1,2}; int rowindex[] = {0, 0}; double value[] = {1, 1}; double rowlb[] = {-INFINITY}; double rowub[] = {3.0}; double collb[] = {0.0, 0.0}; double colub[] = {3.0, 1.5}; double obj[] = {1.1,100.0}; const double *sol; Cbc_loadProblem(model, 2, 1, start, rowindex, value, collb, colub, obj, rowlb, rowub); Cbc_setInteger(model, 1); Cbc_setObjSense(model, -1); Cbc_solve(model); assert(Cbc_isProvenOptimal(model)); sol = Cbc_getColSolution(model); assert(fabs(sol[0] - 2.0) < 1e-6); assert(fabs(sol[1] - 1.0) < 1e-6); Cbc_deleteModel(model); } int main() { printf("Knapsack test\n"); testKnapsack(); printf("SOS test\n"); testSOS(); printf("Infeasible test\n"); testIntegerInfeasible(); printf("Unbounded test\n"); testIntegerUnbounded(); /*printf("Problem modification test\n"); testProblemModification();*/ printf("Integer bounds test\n"); testIntegerBounds(); return 0; } Cbc-2.8.12/test/Makefile.am0000644000076600007660000000730512376140747014004 0ustar coincoin# Copyright (C) 2006 International Business Machines and others. # All Rights Reserved. # This file is distributed under the Eclipse Public License. ## $Id: Makefile.am 2059 2014-08-23 16:31:35Z tkr $ # Author: Andreas Waechter IBM 2006-04-13 AUTOMAKE_OPTIONS = foreign ######################################################################## # unitTest for Cbc # ######################################################################## CBC_TEST_TGTS = gamstests ositests if COIN_HAS_CLP CBC_TEST_TGTS += test_cbc ctests endif if CBC_BUILD_CBC_GENERIC if COIN_HAS_SAMPLE CBC_TEST_TGTS += test_cbc_generic endif endif cbcflags = ositestsflags = if COIN_HAS_SAMPLE cbcflags += -dirSample `$(CYGPATH_W) $(SAMPLE_DATA)` ositestsflags += -mpsDir=`$(CYGPATH_W) $(SAMPLE_DATA)` endif cbcflags += -unitTest if COIN_HAS_MIPLIB3 cbcflags += -dirMiplib `$(CYGPATH_W) $(MIPLIB3_DATA)` -miplib endif if COIN_HAS_NETLIB ositestsflags += -netlibDir=`$(CYGPATH_W) $(NETLIB_DATA)` -testOsiSolverInterface endif # We are using the solver executables to do the unit test test: $(CBC_TEST_TGTS) test_cbc: ../src/cbc$(EXEEXT) ../src/cbc$(EXEEXT) $(cbcflags) if COIN_HAS_SAMPLE test_cbc_generic: ../src/cbc-generic$(EXEEXT) echo "A minimal test is all that cbc-generic can manage just yet." ../src/cbc-generic$(EXEEXT) \ -directory `$(CYGPATH_W) $(SAMPLE_DATA)` -import p0033.mps -branch endif gamstests: gamsTest$(EXEEXT) ./gamsTest$(EXEEXT) .PHONY: test bin_PROGRAMS = gamsTest osiUnitTest CInterfaceTest gamsTest_SOURCES = gamsTest.cpp gamsTest_LDADD = ../src/libCbcSolver.la ../src/libCbc.la $(CBCLIB_LIBS) gamsTest_DEPENDENCIES = ../src/libCbcSolver.la ../src/libCbc.la $(CBCLIB_DEPENDENCIES) AM_CPPFLAGS = -I`$(CYGPATH_W) $(srcdir)/../src` $(COINDEPEND_CFLAGS) AM_CPPFLAGS += $(CLP_CFLAGS) $(CPX_CFLAGS) $(DYLP_CFLAGS) $(GLPK_CFLAGS) $(MSK_CFLAGS) $(VOL_CFLAGS) $(XPR_CFLAGS) # This line is necessary to allow VPATH compilation DEFAULT_INCLUDES = -I. -I`$(CYGPATH_W) $(srcdir)` -I$(top_builddir)/src ######################################################################## # unitTest for OsiCbc # ######################################################################## osiUnitTest_SOURCES = osiUnitTest.cpp OsiCbcSolverInterfaceTest.cpp osiUnitTest_LDADD = ../src/OsiCbc/libOsiCbc.la ../src/libCbc.la \ $(CBCLIB_LIBS) $(OSITESTS_LIBS) osiUnitTest_DEPENDENCIES = ../src/OsiCbc/libOsiCbc.la ../src/libCbc.la \ $(CBCLIB_DEPENDENCIES) $(OSITESTS_DEPENDENCIES) AM_CPPFLAGS += -I`$(CYGPATH_W) $(srcdir)/../src/OsiCbc` $(OSITESTS_CFLAGS) ositests: osiUnitTest$(EXEEXT) ./osiUnitTest$(EXEEXT) $(ositestsflags) ######################################################################## # unitTest for CbcCInterface # ######################################################################## CInterfaceTest_SOURCES = CInterfaceTest.c nodist_EXTRA_CInterfaceTest_SOURCES = dummy.cpp # force using C++ linker CInterfaceTest_LDADD = ../src/libCbcSolver.la ../src/libCbc.la $(CBCLIB_LIBS) CInterfaceTest_DEPENDENCIES = ../src/libCbcSolver.la ../src/libCbc.la $(CBCLIB_DEPENDENCIES) ctests: CInterfaceTest$(EXEEXT) ./CInterfaceTest$(EXEEXT) ######################################################################## # Cleaning stuff # ######################################################################## # Here we list everything that is not generated by the compiler, e.g., # output files of a program DISTCLEANFILES = yy.mps xx.mps continuous.mps integer.mps test2.lp test2.out test.lp test.mps test.out x1.mps.mps x2.mps.mps x3.mps.mps Cbc-2.8.12/test/osiUnitTest.cpp0000644000076600007660000000645712101340057014733 0ustar coincoin// Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). // $Id: osiUnitTest.cpp 1854 2013-01-28 00:02:55Z stefan $ #include "CoinPragma.hpp" #include #include "OsiUnitTests.hpp" #include "OsiCbcSolverInterface.hpp" using namespace OsiUnitTest; //---------------------------------------------------------------- // to see parameter list, call unitTest -usage //---------------------------------------------------------------- int main (int argc, const char *argv[]) { /* Start off with various bits of initialisation that don't really belong anywhere else. Synchronise C++ stream i/o with C stdio. This makes debugging output a bit more comprehensible. It still suffers from interleave of cout (stdout) and cerr (stderr), but -nobuf deals with that. */ std::ios::sync_with_stdio() ; /* Suppress an popup window that Windows shows in response to a crash. See note at head of file. */ WindowsErrorPopupBlocker(); /* Process command line parameters. */ std::map parms; if (processParameters(argc,argv,parms) == false) return 1; std::string mpsDir = parms["-mpsDir"] ; std::string netlibDir = parms["-netlibDir"] ; /* Test Osi{Row,Col}Cut routines. */ { OsiCbcSolverInterface cbcSi; testingMessage( "Testing OsiRowCut with OsiCbcSolverInterface\n" ); OSIUNITTEST_CATCH_ERROR(OsiRowCutUnitTest(&cbcSi,mpsDir), {}, cbcSi, "rowcut unittest"); } { OsiCbcSolverInterface cbcSi; testingMessage( "Testing OsiColCut with OsiCbcSolverInterface\n" ); OSIUNITTEST_CATCH_ERROR(OsiColCutUnitTest(&cbcSi,mpsDir), {}, cbcSi, "colcut unittest"); } { OsiCbcSolverInterface cbcSi; testingMessage( "Testing OsiRowCutDebugger with OsiCbcSolverInterface\n" ); OSIUNITTEST_CATCH_ERROR(OsiRowCutDebuggerUnitTest(&cbcSi,mpsDir), {}, cbcSi, "rowcut debugger unittest"); } /* Run the OsiCbc class test. This will also call OsiSolverInterfaceCommonUnitTest. */ testingMessage( "Testing OsiCbcSolverInterface\n" ); OSIUNITTEST_CATCH_ERROR(OsiCbcSolverInterfaceUnitTest(mpsDir,netlibDir), {}, "cbc", "osicbc unittest"); /* We have run the specialised unit test. Check now to see if we need to run through the Netlib problems. */ if (parms.find("-testOsiSolverInterface") != parms.end()) { // Create vector of solver interfaces std::vector vecSi(1, new OsiCbcSolverInterface); testingMessage( "Testing OsiSolverInterface on Netlib problems.\n" ); OSIUNITTEST_CATCH_ERROR(OsiSolverInterfaceMpsUnitTest(vecSi,netlibDir), {}, "cbc", "netlib unittest"); delete vecSi[0]; } else testingMessage( "***Skipped Testing of OsiCbcSolverInterface on Netlib problems, use -testOsiSolverInterface to run them.***\n" ); /* We're done. Report on the results. */ std::cout.flush(); outcomes.print(); int nerrors; int nerrors_expected; outcomes.getCountBySeverity(TestOutcome::ERROR, nerrors, nerrors_expected); if (nerrors > nerrors_expected) std::cerr << "Tests completed with " << nerrors - nerrors_expected << " unexpected errors." << std::endl ; else std::cerr << "All tests completed successfully\n"; return nerrors - nerrors_expected; } Cbc-2.8.12/test/Makefile.in0000644000076600007660000007213512376140747014020 0ustar coincoin# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Copyright (C) 2006 International Business Machines and others. # All Rights Reserved. # This file is distributed under the Eclipse Public License. # Author: Andreas Waechter IBM 2006-04-13 srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @COIN_HAS_CLP_TRUE@am__append_1 = test_cbc ctests @CBC_BUILD_CBC_GENERIC_TRUE@@COIN_HAS_SAMPLE_TRUE@am__append_2 = test_cbc_generic @COIN_HAS_SAMPLE_TRUE@am__append_3 = -dirSample `$(CYGPATH_W) $(SAMPLE_DATA)` @COIN_HAS_SAMPLE_TRUE@am__append_4 = -mpsDir=`$(CYGPATH_W) $(SAMPLE_DATA)` @COIN_HAS_MIPLIB3_TRUE@am__append_5 = -dirMiplib `$(CYGPATH_W) $(MIPLIB3_DATA)` -miplib @COIN_HAS_NETLIB_TRUE@am__append_6 = -netlibDir=`$(CYGPATH_W) $(NETLIB_DATA)` -testOsiSolverInterface bin_PROGRAMS = gamsTest$(EXEEXT) osiUnitTest$(EXEEXT) \ CInterfaceTest$(EXEEXT) subdir = test DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h \ $(top_builddir)/src/config_cbc.h CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am_CInterfaceTest_OBJECTS = CInterfaceTest.$(OBJEXT) CInterfaceTest_OBJECTS = $(am_CInterfaceTest_OBJECTS) am__DEPENDENCIES_1 = am_gamsTest_OBJECTS = gamsTest.$(OBJEXT) gamsTest_OBJECTS = $(am_gamsTest_OBJECTS) am_osiUnitTest_OBJECTS = osiUnitTest.$(OBJEXT) \ OsiCbcSolverInterfaceTest.$(OBJEXT) osiUnitTest_OBJECTS = $(am_osiUnitTest_OBJECTS) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(CInterfaceTest_SOURCES) \ $(nodist_EXTRA_CInterfaceTest_SOURCES) $(gamsTest_SOURCES) \ $(osiUnitTest_SOURCES) DIST_SOURCES = $(CInterfaceTest_SOURCES) $(gamsTest_SOURCES) \ $(osiUnitTest_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ABSBUILDDIR = @ABSBUILDDIR@ ACLOCAL = @ACLOCAL@ ADD_CFLAGS = @ADD_CFLAGS@ ADD_CXXFLAGS = @ADD_CXXFLAGS@ ALWAYS_FALSE_FALSE = @ALWAYS_FALSE_FALSE@ ALWAYS_FALSE_TRUE = @ALWAYS_FALSE_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ ASL_CFLAGS = @ASL_CFLAGS@ ASL_CFLAGS_INSTALLED = @ASL_CFLAGS_INSTALLED@ ASL_DATA = @ASL_DATA@ ASL_DATA_INSTALLED = @ASL_DATA_INSTALLED@ ASL_DEPENDENCIES = @ASL_DEPENDENCIES@ ASL_LIBS = @ASL_LIBS@ ASL_LIBS_INSTALLED = @ASL_LIBS_INSTALLED@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUX_DIR = @AUX_DIR@ AWK = @AWK@ BUILDTOOLSDIR = @BUILDTOOLSDIR@ CBCGENERIC_CFLAGS = @CBCGENERIC_CFLAGS@ CBCGENERIC_CFLAGS_INSTALLED = @CBCGENERIC_CFLAGS_INSTALLED@ CBCGENERIC_DEPENDENCIES = @CBCGENERIC_DEPENDENCIES@ CBCGENERIC_LIBS = @CBCGENERIC_LIBS@ CBCGENERIC_LIBS_INSTALLED = @CBCGENERIC_LIBS_INSTALLED@ CBCGENERIC_PCLIBS = @CBCGENERIC_PCLIBS@ CBCGENERIC_PCREQUIRES = @CBCGENERIC_PCREQUIRES@ CBCLIB_CFLAGS = @CBCLIB_CFLAGS@ CBCLIB_CFLAGS_INSTALLED = @CBCLIB_CFLAGS_INSTALLED@ CBCLIB_DEPENDENCIES = @CBCLIB_DEPENDENCIES@ CBCLIB_LIBS = @CBCLIB_LIBS@ CBCLIB_LIBS_INSTALLED = @CBCLIB_LIBS_INSTALLED@ CBCLIB_PCLIBS = @CBCLIB_PCLIBS@ CBCLIB_PCREQUIRES = @CBCLIB_PCREQUIRES@ CBC_BUILD_CBC_GENERIC_FALSE = @CBC_BUILD_CBC_GENERIC_FALSE@ CBC_BUILD_CBC_GENERIC_TRUE = @CBC_BUILD_CBC_GENERIC_TRUE@ CBC_SVN_REV = @CBC_SVN_REV@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDEFS = @CDEFS@ CFLAGS = @CFLAGS@ CLP_CFLAGS = @CLP_CFLAGS@ CLP_CFLAGS_INSTALLED = @CLP_CFLAGS_INSTALLED@ CLP_DATA = @CLP_DATA@ CLP_DATA_INSTALLED = @CLP_DATA_INSTALLED@ CLP_DEPENDENCIES = @CLP_DEPENDENCIES@ CLP_LIBS = @CLP_LIBS@ CLP_LIBS_INSTALLED = @CLP_LIBS_INSTALLED@ COINDEPEND_CFLAGS = @COINDEPEND_CFLAGS@ COINDEPEND_CFLAGS_INSTALLED = @COINDEPEND_CFLAGS_INSTALLED@ COINDEPEND_DATA = @COINDEPEND_DATA@ COINDEPEND_DATA_INSTALLED = @COINDEPEND_DATA_INSTALLED@ COINDEPEND_DEPENDENCIES = @COINDEPEND_DEPENDENCIES@ COINDEPEND_LIBS = @COINDEPEND_LIBS@ COINDEPEND_LIBS_INSTALLED = @COINDEPEND_LIBS_INSTALLED@ COIN_CC_IS_CL_FALSE = @COIN_CC_IS_CL_FALSE@ COIN_CC_IS_CL_TRUE = @COIN_CC_IS_CL_TRUE@ COIN_CXX_IS_CL_FALSE = @COIN_CXX_IS_CL_FALSE@ COIN_CXX_IS_CL_TRUE = @COIN_CXX_IS_CL_TRUE@ COIN_HAS_ASL_FALSE = @COIN_HAS_ASL_FALSE@ COIN_HAS_ASL_TRUE = @COIN_HAS_ASL_TRUE@ COIN_HAS_CLP_FALSE = @COIN_HAS_CLP_FALSE@ COIN_HAS_CLP_TRUE = @COIN_HAS_CLP_TRUE@ COIN_HAS_COINDEPEND_FALSE = @COIN_HAS_COINDEPEND_FALSE@ COIN_HAS_COINDEPEND_TRUE = @COIN_HAS_COINDEPEND_TRUE@ COIN_HAS_CPX_FALSE = @COIN_HAS_CPX_FALSE@ COIN_HAS_CPX_TRUE = @COIN_HAS_CPX_TRUE@ COIN_HAS_DYLP_FALSE = @COIN_HAS_DYLP_FALSE@ COIN_HAS_DYLP_TRUE = @COIN_HAS_DYLP_TRUE@ COIN_HAS_GLPK_FALSE = @COIN_HAS_GLPK_FALSE@ COIN_HAS_GLPK_TRUE = @COIN_HAS_GLPK_TRUE@ COIN_HAS_GRB_FALSE = @COIN_HAS_GRB_FALSE@ COIN_HAS_GRB_TRUE = @COIN_HAS_GRB_TRUE@ COIN_HAS_MIPLIB3_FALSE = @COIN_HAS_MIPLIB3_FALSE@ COIN_HAS_MIPLIB3_TRUE = @COIN_HAS_MIPLIB3_TRUE@ COIN_HAS_MSK_FALSE = @COIN_HAS_MSK_FALSE@ COIN_HAS_MSK_TRUE = @COIN_HAS_MSK_TRUE@ COIN_HAS_NETLIB_FALSE = @COIN_HAS_NETLIB_FALSE@ COIN_HAS_NETLIB_TRUE = @COIN_HAS_NETLIB_TRUE@ COIN_HAS_OSITESTS_FALSE = @COIN_HAS_OSITESTS_FALSE@ COIN_HAS_OSITESTS_TRUE = @COIN_HAS_OSITESTS_TRUE@ COIN_HAS_PKGCONFIG_FALSE = @COIN_HAS_PKGCONFIG_FALSE@ COIN_HAS_PKGCONFIG_TRUE = @COIN_HAS_PKGCONFIG_TRUE@ COIN_HAS_SAMPLE_FALSE = @COIN_HAS_SAMPLE_FALSE@ COIN_HAS_SAMPLE_TRUE = @COIN_HAS_SAMPLE_TRUE@ COIN_HAS_SPX_FALSE = @COIN_HAS_SPX_FALSE@ COIN_HAS_SPX_TRUE = @COIN_HAS_SPX_TRUE@ COIN_HAS_VOL_FALSE = @COIN_HAS_VOL_FALSE@ COIN_HAS_VOL_TRUE = @COIN_HAS_VOL_TRUE@ COIN_HAS_XPR_FALSE = @COIN_HAS_XPR_FALSE@ COIN_HAS_XPR_TRUE = @COIN_HAS_XPR_TRUE@ COIN_PKG_CONFIG_PATH = @COIN_PKG_CONFIG_PATH@ COIN_PKG_CONFIG_PATH_UNINSTALLED = @COIN_PKG_CONFIG_PATH_UNINSTALLED@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPX_CFLAGS = @CPX_CFLAGS@ CPX_CFLAGS_INSTALLED = @CPX_CFLAGS_INSTALLED@ CPX_DATA = @CPX_DATA@ CPX_DATA_INSTALLED = @CPX_DATA_INSTALLED@ CPX_DEPENDENCIES = @CPX_DEPENDENCIES@ CPX_LIBS = @CPX_LIBS@ CPX_LIBS_INSTALLED = @CPX_LIBS_INSTALLED@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEFS = @CXXDEFS@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBG_CFLAGS = @DBG_CFLAGS@ DBG_CXXFLAGS = @DBG_CXXFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DEPENDENCY_LINKING_FALSE = @DEPENDENCY_LINKING_FALSE@ DEPENDENCY_LINKING_TRUE = @DEPENDENCY_LINKING_TRUE@ DYLP_CFLAGS = @DYLP_CFLAGS@ DYLP_CFLAGS_INSTALLED = @DYLP_CFLAGS_INSTALLED@ DYLP_DATA = @DYLP_DATA@ DYLP_DATA_INSTALLED = @DYLP_DATA_INSTALLED@ DYLP_DEPENDENCIES = @DYLP_DEPENDENCIES@ DYLP_LIBS = @DYLP_LIBS@ DYLP_LIBS_INSTALLED = @DYLP_LIBS_INSTALLED@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GLPK_CFLAGS = @GLPK_CFLAGS@ GLPK_CFLAGS_INSTALLED = @GLPK_CFLAGS_INSTALLED@ GLPK_DATA = @GLPK_DATA@ GLPK_DATA_INSTALLED = @GLPK_DATA_INSTALLED@ GLPK_DEPENDENCIES = @GLPK_DEPENDENCIES@ GLPK_LIBS = @GLPK_LIBS@ GLPK_LIBS_INSTALLED = @GLPK_LIBS_INSTALLED@ GRB_CFLAGS = @GRB_CFLAGS@ GRB_CFLAGS_INSTALLED = @GRB_CFLAGS_INSTALLED@ GRB_DATA = @GRB_DATA@ GRB_DATA_INSTALLED = @GRB_DATA_INSTALLED@ GRB_DEPENDENCIES = @GRB_DEPENDENCIES@ GRB_LIBS = @GRB_LIBS@ GRB_LIBS_INSTALLED = @GRB_LIBS_INSTALLED@ HAVE_EXTERNALS_FALSE = @HAVE_EXTERNALS_FALSE@ HAVE_EXTERNALS_TRUE = @HAVE_EXTERNALS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBEXT = @LIBEXT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOLM4 = @LIBTOOLM4@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_LDFLAGS = @LT_LDFLAGS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MIPLIB3_CFLAGS = @MIPLIB3_CFLAGS@ MIPLIB3_CFLAGS_INSTALLED = @MIPLIB3_CFLAGS_INSTALLED@ MIPLIB3_DATA = @MIPLIB3_DATA@ MIPLIB3_DATA_INSTALLED = @MIPLIB3_DATA_INSTALLED@ MIPLIB3_DEPENDENCIES = @MIPLIB3_DEPENDENCIES@ MIPLIB3_LIBS = @MIPLIB3_LIBS@ MIPLIB3_LIBS_INSTALLED = @MIPLIB3_LIBS_INSTALLED@ MPICC = @MPICC@ MPICXX = @MPICXX@ MSK_CFLAGS = @MSK_CFLAGS@ MSK_CFLAGS_INSTALLED = @MSK_CFLAGS_INSTALLED@ MSK_DATA = @MSK_DATA@ MSK_DATA_INSTALLED = @MSK_DATA_INSTALLED@ MSK_DEPENDENCIES = @MSK_DEPENDENCIES@ MSK_LIBS = @MSK_LIBS@ MSK_LIBS_INSTALLED = @MSK_LIBS_INSTALLED@ NETLIB_CFLAGS = @NETLIB_CFLAGS@ NETLIB_CFLAGS_INSTALLED = @NETLIB_CFLAGS_INSTALLED@ NETLIB_DATA = @NETLIB_DATA@ NETLIB_DATA_INSTALLED = @NETLIB_DATA_INSTALLED@ NETLIB_DEPENDENCIES = @NETLIB_DEPENDENCIES@ NETLIB_LIBS = @NETLIB_LIBS@ NETLIB_LIBS_INSTALLED = @NETLIB_LIBS_INSTALLED@ OBJEXT = @OBJEXT@ OPT_CFLAGS = @OPT_CFLAGS@ OPT_CXXFLAGS = @OPT_CXXFLAGS@ OSICBC_DFLT_SOLVER_CLP_FALSE = @OSICBC_DFLT_SOLVER_CLP_FALSE@ OSICBC_DFLT_SOLVER_CLP_TRUE = @OSICBC_DFLT_SOLVER_CLP_TRUE@ OSICBC_DFLT_SOLVER_CPX_FALSE = @OSICBC_DFLT_SOLVER_CPX_FALSE@ OSICBC_DFLT_SOLVER_CPX_TRUE = @OSICBC_DFLT_SOLVER_CPX_TRUE@ OSICBC_DFLT_SOLVER_DYLP_FALSE = @OSICBC_DFLT_SOLVER_DYLP_FALSE@ OSICBC_DFLT_SOLVER_DYLP_TRUE = @OSICBC_DFLT_SOLVER_DYLP_TRUE@ OSICBC_DFLT_SOLVER_GLPK_FALSE = @OSICBC_DFLT_SOLVER_GLPK_FALSE@ OSICBC_DFLT_SOLVER_GLPK_TRUE = @OSICBC_DFLT_SOLVER_GLPK_TRUE@ OSICBC_DFLT_SOLVER_GRB_FALSE = @OSICBC_DFLT_SOLVER_GRB_FALSE@ OSICBC_DFLT_SOLVER_GRB_TRUE = @OSICBC_DFLT_SOLVER_GRB_TRUE@ OSICBC_DFLT_SOLVER_MSK_FALSE = @OSICBC_DFLT_SOLVER_MSK_FALSE@ OSICBC_DFLT_SOLVER_MSK_TRUE = @OSICBC_DFLT_SOLVER_MSK_TRUE@ OSICBC_DFLT_SOLVER_SPX_FALSE = @OSICBC_DFLT_SOLVER_SPX_FALSE@ OSICBC_DFLT_SOLVER_SPX_TRUE = @OSICBC_DFLT_SOLVER_SPX_TRUE@ OSICBC_DFLT_SOLVER_SYM_FALSE = @OSICBC_DFLT_SOLVER_SYM_FALSE@ OSICBC_DFLT_SOLVER_SYM_TRUE = @OSICBC_DFLT_SOLVER_SYM_TRUE@ OSICBC_DFLT_SOLVER_VOL_FALSE = @OSICBC_DFLT_SOLVER_VOL_FALSE@ OSICBC_DFLT_SOLVER_VOL_TRUE = @OSICBC_DFLT_SOLVER_VOL_TRUE@ OSICBC_DFLT_SOLVER_XPR_FALSE = @OSICBC_DFLT_SOLVER_XPR_FALSE@ OSICBC_DFLT_SOLVER_XPR_TRUE = @OSICBC_DFLT_SOLVER_XPR_TRUE@ OSITESTS_CFLAGS = @OSITESTS_CFLAGS@ OSITESTS_CFLAGS_INSTALLED = @OSITESTS_CFLAGS_INSTALLED@ OSITESTS_DATA = @OSITESTS_DATA@ OSITESTS_DATA_INSTALLED = @OSITESTS_DATA_INSTALLED@ OSITESTS_DEPENDENCIES = @OSITESTS_DEPENDENCIES@ OSITESTS_LIBS = @OSITESTS_LIBS@ OSITESTS_LIBS_INSTALLED = @OSITESTS_LIBS_INSTALLED@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ RPATH_FLAGS = @RPATH_FLAGS@ SAMPLE_CFLAGS = @SAMPLE_CFLAGS@ SAMPLE_CFLAGS_INSTALLED = @SAMPLE_CFLAGS_INSTALLED@ SAMPLE_DATA = @SAMPLE_DATA@ SAMPLE_DATA_INSTALLED = @SAMPLE_DATA_INSTALLED@ SAMPLE_DEPENDENCIES = @SAMPLE_DEPENDENCIES@ SAMPLE_LIBS = @SAMPLE_LIBS@ SAMPLE_LIBS_INSTALLED = @SAMPLE_LIBS_INSTALLED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPX_CFLAGS = @SPX_CFLAGS@ SPX_CFLAGS_INSTALLED = @SPX_CFLAGS_INSTALLED@ SPX_DATA = @SPX_DATA@ SPX_DATA_INSTALLED = @SPX_DATA_INSTALLED@ SPX_DEPENDENCIES = @SPX_DEPENDENCIES@ SPX_LIBS = @SPX_LIBS@ SPX_LIBS_INSTALLED = @SPX_LIBS_INSTALLED@ STRIP = @STRIP@ VERSION = @VERSION@ VOL_CFLAGS = @VOL_CFLAGS@ VOL_CFLAGS_INSTALLED = @VOL_CFLAGS_INSTALLED@ VOL_DATA = @VOL_DATA@ VOL_DATA_INSTALLED = @VOL_DATA_INSTALLED@ VOL_DEPENDENCIES = @VOL_DEPENDENCIES@ VOL_LIBS = @VOL_LIBS@ VOL_LIBS_INSTALLED = @VOL_LIBS_INSTALLED@ VPATH_DISTCLEANFILES = @VPATH_DISTCLEANFILES@ XPR_CFLAGS = @XPR_CFLAGS@ XPR_CFLAGS_INSTALLED = @XPR_CFLAGS_INSTALLED@ XPR_DATA = @XPR_DATA@ XPR_DATA_INSTALLED = @XPR_DATA_INSTALLED@ XPR_DEPENDENCIES = @XPR_DEPENDENCIES@ XPR_LIBS = @XPR_LIBS@ XPR_LIBS_INSTALLED = @XPR_LIBS_INSTALLED@ abs_bin_dir = @abs_bin_dir@ abs_include_dir = @abs_include_dir@ abs_lib_dir = @abs_lib_dir@ abs_source_dir = @abs_source_dir@ ac_c_preproc_warn_flag = @ac_c_preproc_warn_flag@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ ac_ct_PKG_CONFIG = @ac_ct_PKG_CONFIG@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_cxx_preproc_warn_flag = @ac_cxx_preproc_warn_flag@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ coin_doxy_excludes = @coin_doxy_excludes@ coin_doxy_logname = @coin_doxy_logname@ coin_doxy_tagfiles = @coin_doxy_tagfiles@ coin_doxy_tagname = @coin_doxy_tagname@ coin_doxy_usedot = @coin_doxy_usedot@ coin_have_doxygen = @coin_have_doxygen@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_autoconf = @have_autoconf@ have_automake = @have_automake@ have_svn = @have_svn@ have_svnversion = @have_svnversion@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sol_cc_compiler = @sol_cc_compiler@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AUTOMAKE_OPTIONS = foreign ######################################################################## # unitTest for Cbc # ######################################################################## CBC_TEST_TGTS = gamstests ositests $(am__append_1) $(am__append_2) cbcflags = $(am__append_3) -unitTest $(am__append_5) ositestsflags = $(am__append_4) $(am__append_6) gamsTest_SOURCES = gamsTest.cpp gamsTest_LDADD = ../src/libCbcSolver.la ../src/libCbc.la $(CBCLIB_LIBS) gamsTest_DEPENDENCIES = ../src/libCbcSolver.la ../src/libCbc.la $(CBCLIB_DEPENDENCIES) AM_CPPFLAGS = -I`$(CYGPATH_W) $(srcdir)/../src` $(COINDEPEND_CFLAGS) \ $(CLP_CFLAGS) $(CPX_CFLAGS) $(DYLP_CFLAGS) $(GLPK_CFLAGS) \ $(MSK_CFLAGS) $(VOL_CFLAGS) $(XPR_CFLAGS) -I`$(CYGPATH_W) \ $(srcdir)/../src/OsiCbc` $(OSITESTS_CFLAGS) # This line is necessary to allow VPATH compilation DEFAULT_INCLUDES = -I. -I`$(CYGPATH_W) $(srcdir)` -I$(top_builddir)/src ######################################################################## # unitTest for OsiCbc # ######################################################################## osiUnitTest_SOURCES = osiUnitTest.cpp OsiCbcSolverInterfaceTest.cpp osiUnitTest_LDADD = ../src/OsiCbc/libOsiCbc.la ../src/libCbc.la \ $(CBCLIB_LIBS) $(OSITESTS_LIBS) osiUnitTest_DEPENDENCIES = ../src/OsiCbc/libOsiCbc.la ../src/libCbc.la \ $(CBCLIB_DEPENDENCIES) $(OSITESTS_DEPENDENCIES) ######################################################################## # unitTest for CbcCInterface # ######################################################################## CInterfaceTest_SOURCES = CInterfaceTest.c nodist_EXTRA_CInterfaceTest_SOURCES = dummy.cpp # force using C++ linker CInterfaceTest_LDADD = ../src/libCbcSolver.la ../src/libCbc.la $(CBCLIB_LIBS) CInterfaceTest_DEPENDENCIES = ../src/libCbcSolver.la ../src/libCbc.la $(CBCLIB_DEPENDENCIES) ######################################################################## # Cleaning stuff # ######################################################################## # Here we list everything that is not generated by the compiler, e.g., # output files of a program DISTCLEANFILES = yy.mps xx.mps continuous.mps integer.mps test2.lp test2.out test.lp test.mps test.out x1.mps.mps x2.mps.mps x3.mps.mps all: all-am .SUFFIXES: .SUFFIXES: .c .cpp .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign test/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done CInterfaceTest$(EXEEXT): $(CInterfaceTest_OBJECTS) $(CInterfaceTest_DEPENDENCIES) @rm -f CInterfaceTest$(EXEEXT) $(CXXLINK) $(CInterfaceTest_LDFLAGS) $(CInterfaceTest_OBJECTS) $(CInterfaceTest_LDADD) $(LIBS) gamsTest$(EXEEXT): $(gamsTest_OBJECTS) $(gamsTest_DEPENDENCIES) @rm -f gamsTest$(EXEEXT) $(CXXLINK) $(gamsTest_LDFLAGS) $(gamsTest_OBJECTS) $(gamsTest_LDADD) $(LIBS) osiUnitTest$(EXEEXT): $(osiUnitTest_OBJECTS) $(osiUnitTest_DEPENDENCIES) @rm -f osiUnitTest$(EXEEXT) $(CXXLINK) $(osiUnitTest_LDFLAGS) $(osiUnitTest_OBJECTS) $(osiUnitTest_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CInterfaceTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OsiCbcSolverInterfaceTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gamsTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osiUnitTest.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< .cpp.o: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-libtool distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-binPROGRAMS install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool ctags distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-info-am # We are using the solver executables to do the unit test test: $(CBC_TEST_TGTS) test_cbc: ../src/cbc$(EXEEXT) ../src/cbc$(EXEEXT) $(cbcflags) @COIN_HAS_SAMPLE_TRUE@test_cbc_generic: ../src/cbc-generic$(EXEEXT) @COIN_HAS_SAMPLE_TRUE@ echo "A minimal test is all that cbc-generic can manage just yet." @COIN_HAS_SAMPLE_TRUE@ ../src/cbc-generic$(EXEEXT) \ @COIN_HAS_SAMPLE_TRUE@ -directory `$(CYGPATH_W) $(SAMPLE_DATA)` -import p0033.mps -branch gamstests: gamsTest$(EXEEXT) ./gamsTest$(EXEEXT) .PHONY: test ositests: osiUnitTest$(EXEEXT) ./osiUnitTest$(EXEEXT) $(ositestsflags) ctests: CInterfaceTest$(EXEEXT) ./CInterfaceTest$(EXEEXT) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: Cbc-2.8.12/test/gamsTest.cpp0000644000076600007660000006043112101340057014220 0ustar coincoin// $Id: gamsTest.cpp 1854 2013-01-28 00:02:55Z stefan $ // Copyright (C) 2008, Stefan Vigerske, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include #include using namespace std; #include "CoinHelperFunctions.hpp" #include "CoinError.hpp" #include "CbcModel.hpp" #include "CbcBranchActual.hpp" //for CbcSOS #include "CbcBranchLotsize.hpp" //for CbcLotsize #include "OsiClpSolverInterface.hpp" #define testtol 1e-6 /** model sos1a from the GAMS test library * http://www.gams.com/testlib/libhtml/sos1a.htm */ void sos1a(int& error_count, int& warning_count); /** model sos2a from the GAMS test library * http://www.gams.com/testlib/libhtml/sos2a.htm */ void sos2a(int& error_count, int& warning_count); /** model semicon1 from the GAMS test library * http://www.gams.com/testlib/libhtml/semicon1.htm */ void semicon1(int& error_count, int& warning_count); /** model semiint1 from the GAMS test library * http://www.gams.com/testlib/libhtml/semiint1.htm */ void semiint1(int& error_count, int& warning_count); int main (int argc, const char *argv[]) { WindowsErrorPopupBlocker(); // only in CoinUtils/trunk: WindowsErrorPopupBlocker(); int error_count = 0; int warning_count = 0; sos1a(error_count, warning_count); cout << "\n***********************\n" << endl; sos2a(error_count, warning_count); cout << "\n***********************\n" << endl; semicon1(error_count, warning_count); cout << "\n***********************\n" << endl; semiint1(error_count, warning_count); cout << endl << "Finished - there have been " << error_count << " errors and " << warning_count << " warnings." << endl; return error_count; } void sos1a(int& error_count, int& warning_count) { OsiClpSolverInterface solver1; int numcols = 3; int numrows = 1; int nnz = 3; CoinBigIndex *start = new int[numcols+1]; int* index = new int[nnz]; double* value = new double[nnz]; double *collb = new double[numcols]; double *colub = new double[numcols]; double *obj = new double[numcols]; double *rowlb = new double[numrows]; double *rowub = new double[numrows]; // objective obj[0] = .9; obj[1] = 1.; obj[2] = 1.1; // column bounds collb[0] = 0.; colub[0] = .8; collb[1] = 0.; colub[1] = .6; collb[2] = 0.; colub[2] = .6; // matrix start[0] = 0; index[0] = 0; value[0] = 1.; start[1] = 1; index[1] = 0; value[1] = 1.; start[2] = 2; index[2] = 0; value[2] = 1.; start[3] = 3; // row bounds rowlb[0] = -solver1.getInfinity(); rowub[0] = 1.; solver1.loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); solver1.setObjSense(-1); CbcModel model(solver1); CbcMain0(model); int which[3] = { 0, 1, 2 }; CbcObject* sosobject = new CbcSOS(&model, 3, which, NULL, 0, 1); model.addObjects(1, &sosobject); delete sosobject; const char * argv2[]={"gamstest_sos1a","-solve","-quit"}; CbcMain1(3,argv2,model); cout << endl; if (!model.isProvenOptimal()) { cerr << "Error: Model sos1a not solved to optimality." << endl; ++error_count; return; // other tests make no sense ---- memory leak here } OsiSolverInterface* solver = model.solver(); assert(solver); cout << "Objective value model: " << model.getObjValue() << "\t solver: " << solver->getObjValue() << "\t expected: 0.72" << endl; if (CoinAbs(model.getObjValue()-0.72)>testtol || CoinAbs(solver->getObjValue()-0.72)>testtol) { cerr << "Error: Objective value incorrect." << endl; ++error_count; } cout << "Primal value variable 0 in model: " << model.bestSolution()[0] << "\t in solver: " << solver->getColSolution()[0] << "\t expected: 0.8" << endl; if (CoinAbs(model.bestSolution()[0]-0.8)>testtol || CoinAbs(solver->getColSolution()[0]-0.8)>testtol) { cerr << "Error: Primal value incorrect." << endl; ++error_count; } cout << "Primal value variable 1 in model: " << model.bestSolution()[1] << "\t in solver: " << solver->getColSolution()[1] << "\t expected: 0.0" << endl; if (CoinAbs(model.bestSolution()[1])>testtol || CoinAbs(solver->getColSolution()[1])>testtol) { cerr << "Error: Primal value incorrect." << endl; ++error_count; } cout << "Primal value variable 2 in model: " << model.bestSolution()[2] << "\t in solver: " << solver->getColSolution()[2] << "\t expected: 0.0" << endl; if (CoinAbs(model.bestSolution()[2])>testtol || CoinAbs(solver->getColSolution()[2])>testtol) { cerr << "Error: Primal value incorrect." << endl; ++error_count; } delete[] start; delete[] index; delete[] value; delete[] collb; delete[] colub; delete[] obj; delete[] rowlb; delete[] rowub; } void sos2a(int& error_count, int& warning_count) { OsiClpSolverInterface solver1; int numcols = 7; // w1, w2, w3, x, fx, fplus, fminus int numrows = 5; // wsum, xdef, fxdef, gapplus, gapminus int nnz = 15; CoinBigIndex *start = new int[numcols+1]; int* index = new int[nnz]; double* value = new double[nnz]; double *collb = new double[numcols]; double *colub = new double[numcols]; double *obj = new double[numcols]; double *rowlb = new double[numrows]; double *rowub = new double[numrows]; // objective obj[0] = 0.; obj[1] = 0.; obj[2] = 0.; obj[3] = 0.; obj[4] = 0.; obj[5] = 1.; obj[6] = 1.; // column bounds collb[0] = 0.; colub[0] = solver1.getInfinity(); collb[1] = 0.; colub[1] = solver1.getInfinity(); collb[2] = 0.; colub[2] = solver1.getInfinity(); collb[3] = -solver1.getInfinity(); colub[3] = solver1.getInfinity(); collb[4] = -solver1.getInfinity(); colub[4] = solver1.getInfinity(); collb[5] = 0.; colub[5] = solver1.getInfinity(); collb[6] = 0.; colub[6] = solver1.getInfinity(); // matrix start[0] = 0; index[0] = 0; value[0] = 1.; index[1] = 1; value[1] = 1.; index[2] = 2; value[2] = 1.; start[1] = 3; index[3] = 0; value[3] = 1.; index[4] = 1; value[4] = 2.; index[5] = 2; value[5] = 2.; start[2] = 6; index[6] = 0; value[6] = 1.; index[7] = 1; value[7] = 3.; index[8] = 2; value[8] = 3.; start[3] = 9; index[9] = 1; value[9] =-1.; start[4] =10; index[10]= 2; value[10]=-1.; index[11]= 3; value[11]=-1.; index[12]= 4; value[12]= 1.; start[5] =13; index[13]= 3; value[13]= 1.; start[6] =14; index[14]= 4; value[14]= 1.; start[7] =15; // row bounds rowlb[0] = 1. ; rowub[0] = 1.; rowlb[1] = 0. ; rowub[1] = 0.; rowlb[2] = 0. ; rowub[2] = 0.; rowlb[3] = -1.3; rowub[3] = solver1.getInfinity(); rowlb[4] = 1.3; rowub[4] = solver1.getInfinity(); solver1.loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); double* primalval = new double[numcols]; double* redcost = new double[numcols]; double optvalue = solver1.getInfinity(); for (int testcase = 0; testcase < 2; ++testcase) { switch(testcase) { case 0: solver1.setColLower(0, 0.); optvalue = 0.; primalval[0] = .7; redcost[0] = 0.; primalval[1] = .3; redcost[1] = 0.; primalval[2] =0. ; redcost[2] = 0.; primalval[3] =1.3; redcost[3] = 0.; primalval[4] =1.3; redcost[4] = 0.; primalval[5] =0. ; redcost[5] = 1.; primalval[6] =0. ; redcost[6] = 1.; break; case 1: solver1.setColLower(0, .8); optvalue = 0.1; primalval[0] = .8; redcost[0] = 1.; primalval[1] = .2; redcost[1] = 0.; primalval[2] =0. ; redcost[2] =-1.; primalval[3] =1.2; redcost[3] = 0.; primalval[4] =1.2; redcost[4] = 0.; primalval[5] =0. ; redcost[5] = 1.; primalval[6] =0.1; redcost[6] = 0.; break; } CbcModel model(solver1); CbcMain0(model); int which[3] = { 0, 1, 2 }; CbcObject* sosobject = new CbcSOS(&model, 3, which, NULL, 0, 2); model.addObjects(1, &sosobject); delete sosobject; const char * argv2[]={"gamstest_sos2a","-solve","-quit"}; cout << "\nSolving sos2a model with w1 having lower bound " << solver1.getColLower()[0] << endl; CbcMain1(3,argv2,model); cout << endl; if (!model.isProvenOptimal()) { cerr << "Error: Model sos2a not solved to optimality." << endl; ++error_count; continue; // other tests make no sense } OsiSolverInterface* solver = model.solver(); assert(solver); cout << "Objective value model: " << model.getObjValue() << "\t solver: " << solver->getObjValue() << "\t expected: " << optvalue << endl; if (CoinAbs(model.getObjValue()-optvalue)>testtol || CoinAbs(solver->getObjValue()-optvalue)>testtol) { cerr << "Error: Objective value incorrect." << endl; ++error_count; } for (int i=0; igetColSolution()[i] << "\t expected: " << primalval[i] << endl; if (CoinAbs(model.bestSolution()[i]-primalval[i])>testtol || CoinAbs(solver->getColSolution()[i]-primalval[i])>testtol) { cerr << "Error: Primal value incorrect." << endl; ++error_count; } } for (int i=0; igetReducedCost()[i] << "\t expected: " << redcost[i] << endl; if (CoinAbs(model.getReducedCost()[i]-redcost[i])>testtol || CoinAbs(solver->getReducedCost()[i]-redcost[i])>testtol) { cerr << "Warning: Reduced cost incorrect." << endl; ++warning_count; } } } delete[] start; delete[] index; delete[] value; delete[] collb; delete[] colub; delete[] obj; delete[] rowlb; delete[] rowub; delete[] primalval; delete[] redcost; } void semicon1(int& error_count, int& warning_count) { OsiClpSolverInterface solver1; int numcols = 4; // s, pup, plo, x int numrows = 3; // bigx, smallx, f int nnz = 6; CoinBigIndex *start = new int[numcols+1]; int* index = new int[nnz]; double* value = new double[nnz]; double *collb = new double[numcols]; double *colub = new double[numcols]; double *obj = new double[numcols]; double *rowlb = new double[numrows]; double *rowub = new double[numrows]; // objective obj[0] = 0; obj[1] = 1.; obj[2] = 1; obj[3] = 0; // column bounds collb[0] = 0.; colub[0] = 10.; collb[1] = 0.; colub[1] = solver1.getInfinity(); collb[2] = 0.; colub[2] = solver1.getInfinity(); collb[3] = 0.; colub[3] = solver1.getInfinity(); // matrix start[0] = 0; index[0] = 2; value[0] = 1.; start[1] = 1; index[1] = 0; value[1] = -1.; start[2] = 2; index[2] = 1; value[2] = 1.; start[3] = 3; index[3] = 0; value[3] = 1.; index[4] = 1; value[4] = 1.; index[5] = 2; value[5] = 1.; start[4] = nnz; // row bounds rowlb[0] = -solver1.getInfinity(); rowub[0] = 8.9; rowlb[1] = 8.9; rowub[1] = solver1.getInfinity(); rowlb[2] = 10.; rowub[2] = 10.; solver1.loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); for (int testcase = 0; testcase < 5; ++testcase) { CbcModel model(solver1); CbcMain0(model); double points[4] = { 0., 0., 0., 10. }; double objval; double primalval[4]; double redcost[4]; double row2marg; redcost[1] = 1.0; redcost[2] = 1.0; redcost[3] = 0.0; switch(testcase) { case 0: points[2] = 0.; objval = 0.; primalval[0] = 1.1; primalval[1] = 0.0; primalval[2] = 0.0; primalval[3] = 8.9; redcost[0] = 0.0; row2marg = 0.0; break; case 1: points[2] = 1.; objval = 0.; primalval[0] = 1.1; primalval[1] = 0.0; primalval[2] = 0.0; primalval[3] = 8.9; redcost[0] = 0.0; row2marg = 0.0; break; case 2: points[2] = 1.5; objval = 0.4; primalval[0] = 1.5; primalval[1] = 0.0; primalval[2] = 0.4; primalval[3] = 8.5; redcost[0] = 1.0; row2marg = -1.0; break; case 3: points[2] = 2.1; objval = 1.0; primalval[0] = 2.1; primalval[1] = 0.0; primalval[2] = 1.0; primalval[3] = 7.9; redcost[0] = 1.0; row2marg = -1.0; break; case 4: points[2] = 2.8; objval = 1.1; primalval[0] = 0.0; primalval[1] = 1.1; primalval[2] = 0.0; primalval[3] = 10.0; redcost[0] = -1.0; row2marg = 1.0; break; default: // to please the compile redcost[0] = 0.; row2marg = 0.; objval = 0.; } CbcObject* semiconobject = new CbcLotsize(&model, 0, 2, points, true); model.addObjects(1, &semiconobject); delete semiconobject; cout << "\nSolving semicon1 model for lotsize variable being either 0 or between " << points[2] << " and 10.\n" << endl; const char * argv2[]={"gamstest_semicon1","-solve","-quit"}; CbcMain1(3,argv2,model); cout << endl; if (!model.isProvenOptimal()) { cerr << "Error: Model semicon1 not solved to optimality." << endl; ++error_count; continue; // other tests make no sense } OsiSolverInterface* solver = model.solver(); assert(solver); cout << "Objective value in model: " << model.getObjValue() << "\t in solver: " << solver->getObjValue() << "\t expected: " << objval << endl; if (CoinAbs(model.getObjValue()-objval)>testtol || CoinAbs(solver->getObjValue()-objval)>testtol) { cerr << "Error: Objective value incorrect." << endl; ++error_count; } for (int i=0; igetColSolution()[i] << "\t expected: " << primalval[i] << endl; if (CoinAbs(model.bestSolution()[i]-primalval[i])>testtol || CoinAbs(solver->getColSolution()[i]-primalval[i])>testtol) { cerr << "Error: Primal value incorrect." << endl; ++error_count; } } cout << "Reduced cost variable " << 0 << " in model: " << model.getReducedCost()[0] << "\t in solver: " << solver->getReducedCost()[0] << "\t expected: " << redcost[0] << endl; if (CoinAbs(model.getReducedCost()[0]-redcost[0])>testtol || CoinAbs(solver->getReducedCost()[0]-redcost[0])>testtol) { cerr << "Warning: Reduced cost incorrect." << endl; ++warning_count; } cout << "Reduced cost variable " << 3 << " in model: " << model.getReducedCost()[3] << "\t in solver: " << solver->getReducedCost()[3] << "\t expected: " << redcost[3] << endl; if (CoinAbs(model.getReducedCost()[3]-redcost[3])>testtol || CoinAbs(solver->getReducedCost()[3]-redcost[3])>testtol) { cerr << "Warning: Reduced cost incorrect." << endl; ++warning_count; } cout << "Reduced cost variable 1 plus - dual of row 0 in model: " << model.getReducedCost()[1]-model.getRowPrice()[0] << "\t expected: " << redcost[1] << endl; if (CoinAbs(model.getReducedCost()[1]-model.getRowPrice()[0]-redcost[1])>testtol) { cerr << "Warning: Reduced cost or row margin incorrect." << endl; ++warning_count; } cout << "Reduced cost variable 2 plus + dual of row 1 in model: " << model.getReducedCost()[2]+model.getRowPrice()[1] << "\t expected: " << redcost[2] << endl; if (CoinAbs(model.getReducedCost()[2]+model.getRowPrice()[1]-redcost[2])>testtol) { cerr << "Warning: Reduced cost or row margin incorrect." << endl; ++warning_count; } cout << "Row 2 marginal (price) in model: " << model.getRowPrice()[2] << "\t in solver: " << solver->getRowPrice()[2] << "\t expected: " << row2marg << endl; if (CoinAbs(model.getRowPrice()[2]-row2marg)>testtol || CoinAbs(solver->getRowPrice()[2]-row2marg)>testtol) { cerr << "Warning: Row price incorrect." << endl; ++warning_count; } } delete[] start; delete[] index; delete[] value; delete[] collb; delete[] colub; delete[] obj; delete[] rowlb; delete[] rowub; } void semiint1(int& error_count, int& warning_count) { OsiClpSolverInterface solver1; int numcols = 4; // s, pup, plo, x int numrows = 3; // bigx, smallx, f int nnz = 6; CoinBigIndex *start = new int[numcols+1]; int* index = new int[nnz]; double* value = new double[nnz]; double *collb = new double[numcols]; double *colub = new double[numcols]; double *obj = new double[numcols]; double *rowlb = new double[numrows]; double *rowub = new double[numrows]; // objective obj[0] = 0; obj[1] = 1.; obj[2] = 1; obj[3] = 0; // column bounds collb[0] = 0.; colub[0] = 10.; collb[1] = 0.; colub[1] = solver1.getInfinity(); collb[2] = 0.; colub[2] = solver1.getInfinity(); collb[3] = 0.; colub[3] = solver1.getInfinity(); // matrix start[0] = 0; index[0] = 2; value[0] = 1.; start[1] = 1; index[1] = 0; value[1] = -1.; start[2] = 2; index[2] = 1; value[2] = 1.; start[3] = 3; index[3] = 0; value[3] = 1.; index[4] = 1; value[4] = 1.; index[5] = 2; value[5] = 1.; start[4] = nnz; // row bounds rowlb[0] = -solver1.getInfinity(); rowub[0] = 7.9; rowlb[1] = 7.9; rowub[1] = solver1.getInfinity(); rowlb[2] = 10.; rowub[2] = 10.; solver1.loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); solver1.setInteger(0); for (int testcase = 0; testcase < 6; ++testcase) { CbcModel model(solver1); CbcMain0(model); double points[10]; points[0]=0.; int nrpoints = 0; double objval; double primalval[4]; double redcost[4]; double row2marg; redcost[2] = 1.0; redcost[3] = 0.0; switch(testcase) { case 0: nrpoints = 0; // pure integer case objval = 0.1; primalval[0] = 2.0; primalval[1] = 0.1; primalval[2] = 0.0; primalval[3] = 8; redcost[0] = -1.0; redcost[1] = 0.0; row2marg = 1.0; break; case 1: nrpoints = 0; // pure integer case too objval = 0.1; primalval[0] = 2.0; primalval[1] = 0.1; primalval[2] = 0.0; primalval[3] = 8.0; redcost[0] = -1.0; redcost[1] = 0.0; row2marg = 1.0; break; case 2: for (nrpoints=1; nrpoints<10; ++nrpoints) points[nrpoints]=nrpoints+1; objval = 0.1; primalval[0] = 2.0; primalval[1] = 0.1; primalval[2] = 0.0; primalval[3] = 8.0; redcost[0] = -1.0; redcost[1] = 0.0; row2marg = 1.0; break; case 3: for (nrpoints=1; nrpoints<9; ++nrpoints) points[nrpoints]=nrpoints+2; objval = 0.9; primalval[0] = 3.0; primalval[1] = 0.0; primalval[2] = 0.9; primalval[3] = 7.0; redcost[0] = 1.0; redcost[1] = 1.0; row2marg = -1.0; break; case 4: for (nrpoints=1; nrpoints<8; ++nrpoints) points[nrpoints]=nrpoints+3; objval = 1.9; primalval[0] = 4.0; primalval[1] = 0.0; primalval[2] = 1.9; primalval[3] = 6.0; redcost[0] = 1.0; redcost[1] = 1.0; row2marg = -1.0; break; case 5: for (nrpoints=1; nrpoints<7; ++nrpoints) points[nrpoints]=nrpoints+4; objval = 2.1; primalval[0] = 0.0; primalval[1] = 2.1; primalval[2] = 0.0; primalval[3] = 10.0; redcost[0] = -1.0; redcost[1] = 0.0; row2marg = 1.0; break; default: // to please the compile redcost[0] = 0.; redcost[1] = 0.; row2marg = 0.; objval = 0.; } if (nrpoints) { CbcObject* semiintobject = new CbcLotsize(&model, 0, nrpoints, points); model.addObjects(1, &semiintobject); delete semiintobject; } cout << "\nSolving semiint1 model for integer lotsize variable being either 0 or between " << points[2] << " and 10.\n" << endl; const char * argv2[]={"gamstest_semiint1","-solve","-quit"}; CbcMain1(3,argv2,model); cout << endl; if (!model.isProvenOptimal()) { cerr << "Error: Model semiint1 not solved to optimality." << endl; ++error_count; continue; // other tests make no sense } OsiSolverInterface* solver = model.solver(); assert(solver); cout << "Objective value in model: " << model.getObjValue() << "\t in solver: " << solver->getObjValue() << "\t expected: " << objval << endl; if (CoinAbs(model.getObjValue()-objval)>testtol || CoinAbs(solver->getObjValue()-objval)>testtol) { cerr << "Error: Objective value incorrect." << endl; ++error_count; } for (int i=0; igetColSolution()[i] << "\t expected: " << primalval[i] << endl; if (CoinAbs(model.bestSolution()[i]-primalval[i])>testtol || CoinAbs(solver->getColSolution()[i]-primalval[i])>testtol) { cerr << "Error: Primal value incorrect." << endl; ++error_count; } } cout << "Reduced cost variable " << 0 << " in model: " << model.getReducedCost()[0] << "\t in solver: " << solver->getReducedCost()[0] << "\t expected: " << redcost[0] << endl; if (CoinAbs(model.getReducedCost()[0]-redcost[0])>testtol || CoinAbs(solver->getReducedCost()[0]-redcost[0])>testtol) { cerr << "Warning: Reduced cost incorrect." << endl; ++warning_count; } cout << "Reduced cost variable " << 3 << " in model: " << model.getReducedCost()[3] << "\t in solver: " << solver->getReducedCost()[3] << "\t expected: " << redcost[3] << endl; if (CoinAbs(model.getReducedCost()[3]-redcost[3])>testtol || CoinAbs(solver->getReducedCost()[3]-redcost[3])>testtol) { cerr << "Warning: Reduced cost incorrect." << endl; ++warning_count; } cout << "Row 2 marginal (price) in model: " << model.getRowPrice()[2] << "\t in solver: " << solver->getRowPrice()[2] << "\t expected: " << row2marg << endl; if (CoinAbs(model.getRowPrice()[2]-row2marg)>testtol || CoinAbs(solver->getRowPrice()[2]-row2marg)>testtol) { cerr << "Warning: Row price incorrect." << endl; ++warning_count; } cout << "Row 2 marginal (price) in model: " << model.getRowPrice()[2] << "\t in solver: " << solver->getRowPrice()[2] << "\t expected: " << row2marg << endl; if (CoinAbs(model.getRowPrice()[2]-row2marg)>testtol || CoinAbs(solver->getRowPrice()[2]-row2marg)>testtol) { cerr << "Warning: Row price incorrect." << endl; ++warning_count; } } delete[] start; delete[] index; delete[] value; delete[] collb; delete[] colub; delete[] obj; delete[] rowlb; delete[] rowub; } Cbc-2.8.12/CbcSourceFilesTable.xls0000644000076600007660000006600011277055727015323 0ustar coincoinÐÏࡱá>þÿ 4þÿÿÿþÿÿÿ3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ s ÍÉÀá°Áâ\pBjarni Kristjansson B°aÀ=œ¯¼=âÿŸQÒ8X@"·Ú1Èÿ¨Arial1Èÿ¨Arial1Èÿ¨Arial1Èÿ¨Arial1 ÿ¨Arial1Èÿ¼¨Arial"$"#,##0_);\("$"#,##0\)!"$"#,##0_);[Red]\("$"#,##0\)""$"#,##0.00_);\("$"#,##0.00\)'""$"#,##0.00_);[Red]\("$"#,##0.00\)7*2_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_).))_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)?,:_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)6+1_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)àõÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ à À à+õÿ øÀ à)õÿ øÀ à,õÿ øÀ à*õÿ øÀ à õÿ øÀ à À à @À “€ÿ“€ÿ“€ÿ“€ÿ“€ÿ“€ÿ`…PSheet1…aBSheet2…hCSheet3ŒÁÁ"¾ü*¯CbcBranchActual.cppCbcBranchBase.cppCbcBranchCut.cppCbcBranchDynamic.cppCbcBranchLotsize.cppCbcCbcParam.cppCbcCompareActual.cppCbcCountRowCut.cppCbcCutGenerator.cppCbcEventHandler.cpp CbcFathom.cppCbcFathomDynamicProgramming.cpp CbcGenBaB.cppCbcGenCbcParam.cppCbcGenCbcParamUtils.cppCbcGenCtlBlk.cppCbcGeneric.cppCbcGenMessages.cppCbcGenOsiParam.cppCbcGenOsiParamUtils.cppCbcGenParam.cppCbcGenParamUtils.cppCbcGenSolution.cppCbcGenSolvers.cppCbcHeuristic.cppCbcHeuristicDive.cppCbcHeuristicDiveCoefficient.cppCbcHeuristicDiveFractional.cppCbcHeuristicDiveGuided.cppCbcHeuristicDiveLineSearch.cppCbcHeuristicDivePseudoCost.cpp CbcHeuristicDiveVectorLength.cppCbcHeuristicFPump.cppCbcHeuristicGreedy.cppCbcHeuristicLocal.cppCbcHeuristicPivotAndFix.cppCbcHeuristicRandRound.cppCbcHeuristicRINS.cpp CbcLinked.cpp CbcMain.cppCbcMessage.cpp CbcModel.cpp CbcNode.cpp CbcParam.cpp CbcSolver.cppCbcStatistics.cppCbcStrategy.cpp CbcTree.cppCbcTreeLocal.cpp Cbc_ampl.cppCbc_C_Interface.cppClpAmplObjective.cppClpAmplStuff.cpp CoinSolve.cpp unitTest.cppunitTestClp.cppBranch InterfaceAmplTest HeuristicGenericFilenameGroup CPP LinesAThe support functions for the main branch-and-cut action routine.4Implementation functions for CbcGenParam parameters.,Constructors and destructors for CbcCbcParamDUnnamed local namespace for cbc-generic support types and functions.,Constructors and destructors for CbcOsiParam3Implementation functions for CbcOsiParam parameters,Constructors and destructors for CbcGenParam3Implementation functions for CbcGenParam parameters‚Helper routine to generate masks for selecting names to print. Returns true if masks are generated without error, false otherwise.¥This file contains routines related to handling Osi solvers. The technique is to maintain a map of OsiSolverInterface objects as prototypes of the available solvers.libCbcxcbcSolve cbcGeneric*Constructor for cbc-generic control block.Message definitions.CommentCbcAmpl Other ObjectsMultiple CbcTreeLocalCbcTree CbcTreeArray CbcStrategyCbcStrategyDefault*CbcAmpl*, Multiple CbcStatisticsCbcParam2CbcNodeInfo, CbcFullNodeInfo, CbcPartialNodeInfo, CbcNodeCbcModel CbcMessage OsiSolverLink_OsiLinkedBound, OsiHeuristicDynamic3, OsiOldLink, OsiBiLinear*, OsiSimpleFixedInteger, MultipleCbcHeuristicRINSCbcHeuristicRandRoundCbcHeuristicPivotAndFixCbcHeuristicLocalCbcHeuristicNaiveCbcHeuristicGreedyCoverCbcHeuristicGreedyEqualityCbcHeuristicFPumpCbcDisasterHandlerCbcHeuristicDiveVectorLengthCbcHeuristicDivePseudoCostCbcHeuristicDiveLineSearchCbcHeuristicDiveGuidedCbcHeuristicDiveFractionalCbcHeuristicDiveCoefficientCbcHeuristicDive CbcHeuristicmCbcHeuristicNode, CbcHeuristicNodeList, CbcRounding, CbcHeuristicPartial, CbcSerendipity, CbcHeuristicJustOneCbcFathomDynamicProgramming CbcFathom CbcOsiSolverCbcEventHandlerCbcCutGenerator$CbcCutModifier, CbcCutSubsetModifierCbcCountRowCutCbcCompareDepth:CbcCompareObjective, CbcCompareDefault, CbcCompareEstimate#include "CbcOrClpParam.cpp" CbcLotsizeCbcLotsizeBranchingObject!CbcSimpleIntegerDynamicPseudoCost=CbcDynamicPseudoCostBranchingObject, CbcBranchDynamicDecision CbcBranchCut@CbcCutBranchingObject, CbcBranchToFixLots, CbcBranchAllDifferent CbcObjectJCbcBranchingObject, CbcBranchDecision, CbcConsequence, CbcObjectUpdateData CbcGenCtlBlk CbcCbcParamnamespace CbcCbcParamUtils CbcOsiParamnamespace CbcOsiParamUtils CbcGenParamnamespace CbcGenSolversCbcGenParamUtils namespacenamespace CbcGenParamUtilsnamespace CbcGenSolvers, CbcCompareUser, namespacemain CbcSolverCbcMainglobalClpAmplObjectiveMyMessageHandler2¾CbcClique, CbcSos, CbcSimpleInteger, CbcIntegerBranchingObject, CbcSimpleIntegerPseudoCost, CbcIntegerPseudoCostBranchingObject, CbcCliqueBranchingObject, CbcLongCliqueBranchingObject, CbcSosBranchingObject, CbcBranchDefaultDecision, CbcFollowOn, CbcFixingBranchingObject, CbcNWay, CbcNWayBranchingObject, CbcFixVariable, CbcDummyBranchingObject, CbcGeneral, CbcGeneralDepth, CbcGeneralBranchingObject, CbcOneGeneralBranchingObject, CbcSubProblem First ObjectSolverPersonBjarniLou HPP Lines3CbcHeuristicRENS, CbcHeuristicDINS, CbcHeuristicVNDCbcCompareBase.hppCbcCompareBaseCbcCompare, CbcChooseVariable CbcConfig.h#definesCbcFeasibilityBase.hppCbcFeasibilityBaseClpConstraintAmpl.hppOther ProjectsAge Total LinesStatusEdwinCompareÿ²ø ¡µQeø çûŸ ³ 4³ Çÿ  ¤EY³ÇQe =Q # ) ì &:Ã×Qebv%9ccÒ s ÍÉÀ =~ 2ÇA  dü©ñÒMbP?_*+‚€%ÿÁƒ„Mj\\OFFICE1\Dell Printer 5100cn ÜŒSÿ€ê odXXLetterPRIVâ0''''ÄÈ\KhCŸ}­ôÿÿÈDFBF0040/#Ñùgü-¤Oµ_ÉûËÜ}Ìd¡"dXXà?à?U} $"} $ } I+} I(=ÿ€ÿÿÿÿÿÿÿÿ ÿ ÿ ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿý >ý ?ý œý ¬ý ªý @ý Ÿý «ý Ký Mý Ný ©ý šý Sý Qý ý 8ý ­½ @Ü´@|œ@!û»@ÌÆý DÀDÀý Lý  Tý  ™ý ý 8ý ­½$@v@†@Œ@þ¼<; LþÀLÿÀý Lý  …ý  †ý ý 8ý ­½$@ø@°s@è”@ÿý Lý  ƒý  „ý ý 8ý ­½ @Ü@h@H£@ÿý Lý  ý  ‚ý ý 8ý ­½.@H‰@@o@Œ@ÿý Lý  ý  €ý ý ›ý ½8@ð?ð?ÿý Lý  ~ý ý ®½ @ð|@ d@ ƒ@ÿý Lý  |ý  }ý ¡ý ®~ 8@~ @e@@e@ ÿý Lý  ¢ý  £ý ¤~ 4@~ €Y@ €Y@ ÿý Lý ¥ý ½ $@€_@À\@  n@ ÿý Lý {ý ½ @“@à@ ›@ ÿý Lý yý zý  ½ B@@Y@ k@  t@ ÿý Lý xý  ½ 3@€Z@€_@ m@ÿý Lý vý wý  ½$@l@Àd@“@ÿý Lý  uý ¦~ 8@~ €J@€J@ÿý Lý  §ý  ý =ý ž½,@°‹@°‹@ÿý  Lý  ý  ý Aý  ý =ý ž½8@`c@ g@€u@ÿý  Lý  ˆý Cý ý =ý ž½2@y@y@ÿý  Lý  ‰ý Bý ý =ý ž½8@H…@ @t™@ÿý Lý  Lý  ‡ý Oý ý =ý ž½8@ðy@ðy@ÿý  Lý  ý  ý Dý ý =ý ž½8@h@h@ÿý Lý  ‡ý Pý ý =ý ž½8@€c@ h@v@ÿý  Lý  Šý Eý ý =ý ž½2@€€@€€@ÿý  Lý  ‹ý Fý ý =ý ž½8@@c@`k@Pw@ÿý  Lý  Œý Gý ý =ý ž½2@d—@d—@ÿý  Lý  ý  ‘ý Hý ý =ý ž½6@@‚@@‚@ÿý  Lý  Žý  ý Iý ý =ý ž½8@Pp@Pp@ÿý  Lý  ý  ý Jý ý <½$@ª¦@P„@¾«@ÿý Lý  sý  tý ý <½$@°@d@0“@ÿý Lý  rý ý <½(@`@€H@ f@ÿý Lý  qý ý <½2@\@€H@ d@ ÿý Lý  p×DJlÒ•¨{eesesee—‰—‰‰———ss ÿ!ÿ"ÿ#ÿ$ÿ%ÿ&ÿ'ÿ(ÿ)ÿ*ÿ+ÿ,ÿ-ÿ.ÿ/ÿ0ÿ1ÿ2ÿ3ÿ4ÿ5ÿ6ÿ7ÿ8ÿ9ÿ:ÿ;ÿ<ÿý ý <½ 2@À^@J@ àe@!ÿý Lý oý !ý !<½!2@^@€H@! e@"ÿý !Lý ! ný "ý "<½"2@`l@€L@"Àq@#ÿý "Lý " mý #ý #<½#$@À^@€H@#€e@$ÿý #Lý # lý $ ý $<½$ @˜¥@ðs@$¨@%ÿý $Lý $ jý $ ký %!ý %<½%1@èŠ@ g@%h@&ÿý %Lý % hý % iý &"ý &<½& @@‘@j@&€”@'ÿý &Lý & fý & gý '#ý '<½',@È€@€K@'€‚@(ÿý 'Lý ' eý ($ý (<½($@€@€K@(È@)ÿý (Lý ( dý )%ý )<½)$@Ü’@€r@)|—@*ÿý )Lý ) cý )  ý *&½*$@7À@ì•@*€ôÂ@+ÿý *Lý * aý * bý +'½+,@Ì™@+Ì™@,ÿý + Lý + “ý + ’ý ,(½,*@Z@ÀU@,àg@-ÿý ,Lý , `ý -)½-@+Ð@|¤@-ÀºÒ@.ÿý -Lý - _ý .*½.´@0‰@.5·@/ÿý .Lý . ^ý . ]ý /+ý /›ý /½/8@`@ m@/‡@0ÿý /Lý / \ý 0,ý 0›ý 0½0€2Æ@0€2Æ@1ÿý 0 Lý 0 ”ý 0 •ý 1-½15@a@€X@1@m@2ÿý 1Lý 1 [ý 2.½2 @`@ào@2¬’@3ÿý 2Lý 2 Xý 2 Yý 3/½3 @h’@0z@3ô˜@4ÿý 3Lý 3 Vý 3 Wý 40½4$@L›@w@4ˆ @5ÿý 4Lý 4 Uý 51ý 5:½5@€—@@P@5„˜@6ÿý 5 Lý 5 –ý 62ý 69ý 6½6@ô£@„@6©@7ÿý 6 Lý 6 –ý 73ý 7:½7,@p‡@€[@7àŠ@8ÿý 7 Lý 7 —ý 84ý 8:½8@h•@8h•@9ÿý 8Lý 8 Rý 8 Zý 9¨ý 9:~ 98@~ 9@Z@9@Z@:ÿý :5ý :›½: @`u@:`u@;ÿý : Lý : ˜ý : “ý ;6ý ;;½; @ z@; z@<ÿý ; Lý ; –ý <7ý <;½<@P†@<P†@ÿý < Lý < –×>_0sssssssmees‰essess{W{m>¶@A à@ ÿ? ï7 s ÍÉÀ C  dü©ñÒMbP?_*+‚€%ÿÁƒ„¡"ÿà?à?U>¶@ï7 s ÍÉÀ  D  dü©ñÒMbP?_*+‚€%ÿÁƒ„¡"ÿà?à?U>¶@ï7 þÿà…ŸòùOh«‘+'³Ù0¸@Hd€ ˜ ¤°äBjarni KristjanssonBjarni KristjanssonMicrosoft Excel@Sðü|NÊ@)‰ÉcÊþÿÕÍÕœ.“—+,ù®0ì PXx €ˆ˜   ÉäMaximal Software, Inc.' Sheet1Sheet2Sheet3  Worksheets  !"þÿÿÿ$%&'()*þÿÿÿ,-./012þÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿ ÀFðÊòuÊcÊþÿÿÿWorkbookÿÿÿÿÿÿÿÿÿÿÿÿoDSummaryInformation(ÿÿÿÿ#DocumentSummaryInformation8ÿÿÿÿÿÿÿÿÿÿÿÿ+Cbc-2.8.12/configure0000755000076600007660000416074112377521104012677 0ustar coincoin#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for Cbc 2.8.12. # # Report bugs to . # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # # # Copyright 2006 International Business Machines and others. # All Rights Reserved. # This file is part of the open source package Coin which is distributed # under the Eclipse Public License. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac echo=${ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null 2>&1 && unset CDPATH if test -z "$ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if (echo_test_string=`eval $cmd`) 2>/dev/null && echo_test_string=`eval $cmd` && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi tagnames=${tagnames+${tagnames},}CXX tagnames=${tagnames+${tagnames},}F77 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME='Cbc' PACKAGE_TARNAME='cbc' PACKAGE_VERSION='2.8.12' PACKAGE_STRING='Cbc 2.8.12' PACKAGE_BUGREPORT='cbc@lists.coin-or.org' ac_unique_file="src/CbcTree.hpp" ac_default_prefix=`pwd` # Factoring default headers for most tests. ac_includes_default="\ #include #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os ALWAYS_FALSE_TRUE ALWAYS_FALSE_FALSE have_svnversion CBC_SVN_REV CDEFS ADD_CFLAGS DBG_CFLAGS OPT_CFLAGS sol_cc_compiler CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT COIN_CC_IS_CL_TRUE COIN_CC_IS_CL_FALSE MPICC CXXDEFS ADD_CXXFLAGS DBG_CXXFLAGS OPT_CXXFLAGS CXX CXXFLAGS ac_ct_CXX COIN_CXX_IS_CL_TRUE COIN_CXX_IS_CL_FALSE MPICXX EGREP LN_S INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBTOOLM4 have_autoconf have_automake have_svn BUILDTOOLSDIR AUX_DIR abs_source_dir abs_lib_dir abs_include_dir abs_bin_dir HAVE_EXTERNALS_TRUE HAVE_EXTERNALS_FALSE host host_cpu host_vendor host_os ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL ac_c_preproc_warn_flag ac_cxx_preproc_warn_flag RPATH_FLAGS DEPENDENCY_LINKING_TRUE DEPENDENCY_LINKING_FALSE LT_LDFLAGS PKG_CONFIG ac_ct_PKG_CONFIG COIN_HAS_PKGCONFIG_TRUE COIN_HAS_PKGCONFIG_FALSE COIN_PKG_CONFIG_PATH COIN_PKG_CONFIG_PATH_UNINSTALLED COINDEPEND_LIBS COINDEPEND_CFLAGS COINDEPEND_DATA COINDEPEND_DEPENDENCIES COINDEPEND_LIBS_INSTALLED COINDEPEND_CFLAGS_INSTALLED COINDEPEND_DATA_INSTALLED CBCLIB_CFLAGS CBCLIB_LIBS CBCLIB_PCLIBS CBCLIB_PCREQUIRES CBCLIB_DEPENDENCIES CBCLIB_CFLAGS_INSTALLED CBCLIB_LIBS_INSTALLED CBCGENERIC_CFLAGS CBCGENERIC_LIBS CBCGENERIC_PCLIBS CBCGENERIC_PCREQUIRES CBCGENERIC_DEPENDENCIES CBCGENERIC_CFLAGS_INSTALLED CBCGENERIC_LIBS_INSTALLED COIN_HAS_COINDEPEND_TRUE COIN_HAS_COINDEPEND_FALSE CLP_LIBS CLP_CFLAGS CLP_DATA CLP_DEPENDENCIES CLP_LIBS_INSTALLED CLP_CFLAGS_INSTALLED CLP_DATA_INSTALLED COIN_HAS_CLP_TRUE COIN_HAS_CLP_FALSE OSITESTS_LIBS OSITESTS_CFLAGS OSITESTS_DATA OSITESTS_DEPENDENCIES OSITESTS_LIBS_INSTALLED OSITESTS_CFLAGS_INSTALLED OSITESTS_DATA_INSTALLED COIN_HAS_OSITESTS_TRUE COIN_HAS_OSITESTS_FALSE SAMPLE_LIBS SAMPLE_CFLAGS SAMPLE_DATA SAMPLE_DEPENDENCIES SAMPLE_LIBS_INSTALLED SAMPLE_CFLAGS_INSTALLED SAMPLE_DATA_INSTALLED COIN_HAS_SAMPLE_TRUE COIN_HAS_SAMPLE_FALSE NETLIB_LIBS NETLIB_CFLAGS NETLIB_DATA NETLIB_DEPENDENCIES NETLIB_LIBS_INSTALLED NETLIB_CFLAGS_INSTALLED NETLIB_DATA_INSTALLED COIN_HAS_NETLIB_TRUE COIN_HAS_NETLIB_FALSE MIPLIB3_LIBS MIPLIB3_CFLAGS MIPLIB3_DATA MIPLIB3_DEPENDENCIES MIPLIB3_LIBS_INSTALLED MIPLIB3_CFLAGS_INSTALLED MIPLIB3_DATA_INSTALLED COIN_HAS_MIPLIB3_TRUE COIN_HAS_MIPLIB3_FALSE DYLP_LIBS DYLP_CFLAGS DYLP_DATA DYLP_DEPENDENCIES DYLP_LIBS_INSTALLED DYLP_CFLAGS_INSTALLED DYLP_DATA_INSTALLED COIN_HAS_DYLP_TRUE COIN_HAS_DYLP_FALSE VOL_LIBS VOL_CFLAGS VOL_DATA VOL_DEPENDENCIES VOL_LIBS_INSTALLED VOL_CFLAGS_INSTALLED VOL_DATA_INSTALLED COIN_HAS_VOL_TRUE COIN_HAS_VOL_FALSE CPX_LIBS CPX_CFLAGS CPX_DATA CPX_DEPENDENCIES CPX_LIBS_INSTALLED CPX_CFLAGS_INSTALLED CPX_DATA_INSTALLED COIN_HAS_CPX_TRUE COIN_HAS_CPX_FALSE GLPK_LIBS GLPK_CFLAGS GLPK_DATA GLPK_DEPENDENCIES GLPK_LIBS_INSTALLED GLPK_CFLAGS_INSTALLED GLPK_DATA_INSTALLED COIN_HAS_GLPK_TRUE COIN_HAS_GLPK_FALSE GRB_LIBS GRB_CFLAGS GRB_DATA GRB_DEPENDENCIES GRB_LIBS_INSTALLED GRB_CFLAGS_INSTALLED GRB_DATA_INSTALLED COIN_HAS_GRB_TRUE COIN_HAS_GRB_FALSE MSK_LIBS MSK_CFLAGS MSK_DATA MSK_DEPENDENCIES MSK_LIBS_INSTALLED MSK_CFLAGS_INSTALLED MSK_DATA_INSTALLED COIN_HAS_MSK_TRUE COIN_HAS_MSK_FALSE SPX_LIBS SPX_CFLAGS SPX_DATA SPX_DEPENDENCIES SPX_LIBS_INSTALLED SPX_CFLAGS_INSTALLED SPX_DATA_INSTALLED COIN_HAS_SPX_TRUE COIN_HAS_SPX_FALSE XPR_LIBS XPR_CFLAGS XPR_DATA XPR_DEPENDENCIES XPR_LIBS_INSTALLED XPR_CFLAGS_INSTALLED XPR_DATA_INSTALLED COIN_HAS_XPR_TRUE COIN_HAS_XPR_FALSE ASL_LIBS ASL_CFLAGS ASL_DATA ASL_DEPENDENCIES ASL_LIBS_INSTALLED ASL_CFLAGS_INSTALLED ASL_DATA_INSTALLED COIN_HAS_ASL_TRUE COIN_HAS_ASL_FALSE CBC_BUILD_CBC_GENERIC_TRUE CBC_BUILD_CBC_GENERIC_FALSE OSICBC_DFLT_SOLVER_CLP_TRUE OSICBC_DFLT_SOLVER_CLP_FALSE OSICBC_DFLT_SOLVER_CPX_TRUE OSICBC_DFLT_SOLVER_CPX_FALSE OSICBC_DFLT_SOLVER_DYLP_TRUE OSICBC_DFLT_SOLVER_DYLP_FALSE OSICBC_DFLT_SOLVER_GLPK_TRUE OSICBC_DFLT_SOLVER_GLPK_FALSE OSICBC_DFLT_SOLVER_GRB_TRUE OSICBC_DFLT_SOLVER_GRB_FALSE OSICBC_DFLT_SOLVER_MSK_TRUE OSICBC_DFLT_SOLVER_MSK_FALSE OSICBC_DFLT_SOLVER_SPX_TRUE OSICBC_DFLT_SOLVER_SPX_FALSE OSICBC_DFLT_SOLVER_SYM_TRUE OSICBC_DFLT_SOLVER_SYM_FALSE OSICBC_DFLT_SOLVER_VOL_TRUE OSICBC_DFLT_SOLVER_VOL_FALSE OSICBC_DFLT_SOLVER_XPR_TRUE OSICBC_DFLT_SOLVER_XPR_FALSE coin_have_doxygen coin_doxy_usedot coin_doxy_tagname coin_doxy_logname coin_doxy_tagfiles coin_doxy_excludes LIBEXT VPATH_DISTCLEANFILES ABSBUILDDIR LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CDEFS_set=${CDEFS+set} ac_env_CDEFS_value=$CDEFS ac_cv_env_CDEFS_set=${CDEFS+set} ac_cv_env_CDEFS_value=$CDEFS ac_env_ADD_CFLAGS_set=${ADD_CFLAGS+set} ac_env_ADD_CFLAGS_value=$ADD_CFLAGS ac_cv_env_ADD_CFLAGS_set=${ADD_CFLAGS+set} ac_cv_env_ADD_CFLAGS_value=$ADD_CFLAGS ac_env_DBG_CFLAGS_set=${DBG_CFLAGS+set} ac_env_DBG_CFLAGS_value=$DBG_CFLAGS ac_cv_env_DBG_CFLAGS_set=${DBG_CFLAGS+set} ac_cv_env_DBG_CFLAGS_value=$DBG_CFLAGS ac_env_OPT_CFLAGS_set=${OPT_CFLAGS+set} ac_env_OPT_CFLAGS_value=$OPT_CFLAGS ac_cv_env_OPT_CFLAGS_set=${OPT_CFLAGS+set} ac_cv_env_OPT_CFLAGS_value=$OPT_CFLAGS ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_MPICC_set=${MPICC+set} ac_env_MPICC_value=$MPICC ac_cv_env_MPICC_set=${MPICC+set} ac_cv_env_MPICC_value=$MPICC ac_env_CXXDEFS_set=${CXXDEFS+set} ac_env_CXXDEFS_value=$CXXDEFS ac_cv_env_CXXDEFS_set=${CXXDEFS+set} ac_cv_env_CXXDEFS_value=$CXXDEFS ac_env_ADD_CXXFLAGS_set=${ADD_CXXFLAGS+set} ac_env_ADD_CXXFLAGS_value=$ADD_CXXFLAGS ac_cv_env_ADD_CXXFLAGS_set=${ADD_CXXFLAGS+set} ac_cv_env_ADD_CXXFLAGS_value=$ADD_CXXFLAGS ac_env_DBG_CXXFLAGS_set=${DBG_CXXFLAGS+set} ac_env_DBG_CXXFLAGS_value=$DBG_CXXFLAGS ac_cv_env_DBG_CXXFLAGS_set=${DBG_CXXFLAGS+set} ac_cv_env_DBG_CXXFLAGS_value=$DBG_CXXFLAGS ac_env_OPT_CXXFLAGS_set=${OPT_CXXFLAGS+set} ac_env_OPT_CXXFLAGS_value=$OPT_CXXFLAGS ac_cv_env_OPT_CXXFLAGS_set=${OPT_CXXFLAGS+set} ac_cv_env_OPT_CXXFLAGS_value=$OPT_CXXFLAGS ac_env_CXX_set=${CXX+set} ac_env_CXX_value=$CXX ac_cv_env_CXX_set=${CXX+set} ac_cv_env_CXX_value=$CXX ac_env_CXXFLAGS_set=${CXXFLAGS+set} ac_env_CXXFLAGS_value=$CXXFLAGS ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} ac_cv_env_CXXFLAGS_value=$CXXFLAGS ac_env_MPICXX_set=${MPICXX+set} ac_env_MPICXX_value=$MPICXX ac_cv_env_MPICXX_set=${MPICXX+set} ac_cv_env_MPICXX_value=$MPICXX ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP ac_env_CXXCPP_set=${CXXCPP+set} ac_env_CXXCPP_value=$CXXCPP ac_cv_env_CXXCPP_set=${CXXCPP+set} ac_cv_env_CXXCPP_value=$CXXCPP ac_env_F77_set=${F77+set} ac_env_F77_value=$F77 ac_cv_env_F77_set=${F77+set} ac_cv_env_F77_value=$F77 ac_env_FFLAGS_set=${FFLAGS+set} ac_env_FFLAGS_value=$FFLAGS ac_cv_env_FFLAGS_set=${FFLAGS+set} ac_cv_env_FFLAGS_value=$FFLAGS ac_env_PKG_CONFIG_set=${PKG_CONFIG+set} ac_env_PKG_CONFIG_value=$PKG_CONFIG ac_cv_env_PKG_CONFIG_set=${PKG_CONFIG+set} ac_cv_env_PKG_CONFIG_value=$PKG_CONFIG # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures Cbc 2.8.12 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Cbc 2.8.12:";; esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-debug compile all projects with debug options tests (implies --disable-shared) --enable-debug-cbc compile project Cbc with debug compiler flags --enable-msvc Prefer (i)cl/ifort/link over GNU on MinGW/Cygwin. --enable-static[=PKGS] build static libraries [default=no] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-pkg-config disable use of pkg-config (if available) --disable-interpackage-dependencies disables deduction of Makefile dependencies from package linker flags --enable-gnu-packages compile with GNU packages (disabled by default) --enable-cbc-parallel enables compilation of the SMP version of Cbc Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-cbc-verbosity specify the debug verbosity level for project Cbc --with-cbc-checklevel specify the sanity check level for project Cbc --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-pic try to use only PIC/non-PIC objects [default=use both] --with-tags[=TAGS] include additional configurations [automatic] --with-coin-instdir prefix of installation directory for precompiled COIN packages --with-coindepend-lib linker flags for using package CoinDepend --with-coindepend-incdir directory with header files for using package CoinDepend --with-coindepend-datadir directory with data files for using package CoinDepend --with-clp-lib linker flags for using package Clp --with-clp-incdir directory with header files for using package Clp --with-clp-datadir directory with data files for using package Clp --with-ositests-lib linker flags for using package OsiTests --with-ositests-incdir directory with header files for using package OsiTests --with-ositests-datadir directory with data files for using package OsiTests --with-sample-lib linker flags for using package Sample --with-sample-incdir directory with header files for using package Sample --with-sample-datadir directory with data files for using package Sample --with-netlib-lib linker flags for using package Netlib --with-netlib-incdir directory with header files for using package Netlib --with-netlib-datadir directory with data files for using package Netlib --with-miplib3-lib linker flags for using package Miplib3 --with-miplib3-incdir directory with header files for using package Miplib3 --with-miplib3-datadir directory with data files for using package Miplib3 --with-dylp-lib linker flags for using package DyLP --with-dylp-incdir directory with header files for using package DyLP --with-dylp-datadir directory with data files for using package DyLP --with-vol-lib linker flags for using package Vol --with-vol-incdir directory with header files for using package Vol --with-vol-datadir directory with data files for using package Vol --with-cpx-lib linker flags for using package Cpx --with-cpx-incdir directory with header files for using package Cpx --with-cpx-datadir directory with data files for using package Cpx --with-glpk-lib linker flags for using package Glpk --with-glpk-incdir directory with header files for using package Glpk --with-glpk-datadir directory with data files for using package Glpk --with-grb-lib linker flags for using package Grb --with-grb-incdir directory with header files for using package Grb --with-grb-datadir directory with data files for using package Grb --with-msk-lib linker flags for using package Msk --with-msk-incdir directory with header files for using package Msk --with-msk-datadir directory with data files for using package Msk --with-spx-lib linker flags for using package Spx --with-spx-incdir directory with header files for using package Spx --with-spx-datadir directory with data files for using package Spx --with-xpr-lib linker flags for using package Xpr --with-xpr-incdir directory with header files for using package Xpr --with-xpr-datadir directory with data files for using package Xpr --with-asl-lib linker flags for using package ASL --with-asl-incdir directory with header files for using package ASL --with-asl-datadir directory with data files for using package ASL --with-cbc-generic specify whether to build cbc-generic (default: no) --with-cbc-generic-solver specify default solver for cbc-generic in lower case letters (if not given, clp is assumed) --with-pthreadsw32-lib specify the name of the pthreads win32 library (for cl/icl builds only) --with-pthreadsw32-incdir specify the path of the pthreads win32 header file (for cl/icl builds only) --with-osicbc-default-solver specify underlying solver for OsiCbc (default clp) --with-dot use dot (from graphviz) when creating documentation with doxygen if available; --without-dot to disable Some influential environment variables: CDEFS Additional -D flags to be used when compiling C code. ADD_CFLAGS Additional C compiler options DBG_CFLAGS Debug C compiler options OPT_CFLAGS Optimize C compiler options CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory MPICC C MPI Compiler CXXDEFS Additional -D flags to be used when compiling C++ code. ADD_CXXFLAGS Additional C++ compiler options DBG_CXXFLAGS Debug C++ compiler options OPT_CXXFLAGS Optimize C++ compiler options CXX C++ compiler command CXXFLAGS C++ compiler flags MPICXX C++ MPI Compiler CPP C preprocessor CXXCPP C++ preprocessor F77 Fortran 77 compiler command FFLAGS Fortran 77 compiler flags PKG_CONFIG path to pkg-config utility Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF Cbc configure 2.8.12 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Copyright 2006 International Business Machines and others. All Rights Reserved. This file is part of the open source package Coin which is distributed under the Eclipse Public License. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Cbc $as_me 2.8.12, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # List one file in the package so that the configure script can test # whether the package is actually there # Where should everything be installed by default? Here, we want it # to be installed directly in 'bin', 'lib', 'include' subdirectories # of the directory where configure is run. The default would be # /usr/local. ############################################################################# # Standard build tool stuff # ############################################################################# # Get the system type ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f $ac_dir/shtool; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} { (exit 1); exit 1; }; } fi ac_config_guess="$SHELL $ac_aux_dir/config.guess" ac_config_sub="$SHELL $ac_aux_dir/config.sub" ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # Make sure we can run config.sub. $ac_config_sub sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 echo "$as_me: error: cannot run $ac_config_sub" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking build system type" >&5 echo $ECHO_N "checking build system type... $ECHO_C" >&6 if test "${ac_cv_build+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_build_alias=$build_alias test -z "$ac_cv_build_alias" && ac_cv_build_alias=`$ac_config_guess` test -z "$ac_cv_build_alias" && { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_build" >&5 echo "${ECHO_T}$ac_cv_build" >&6 build=$ac_cv_build build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # If this project depends on external projects, the Externals file in # the source root directory contains definition of where to find those # externals. The following macro ensures that those externals are # retrieved by svn if they are not there yet. # As backup, we make sure we don't loose an FLIBS if it has been set # by the user save_FLIBS="$FLIBS" # A useful makefile conditional that is always false if false; then ALWAYS_FALSE_TRUE= ALWAYS_FALSE_FALSE='#' else ALWAYS_FALSE_TRUE='#' ALWAYS_FALSE_FALSE= fi # We set the following variable so that we know later in AC_COIN_FINALIZE # that we are in a project main directory coin_projectdir=yes # Set the project's version numbers cat >>confdefs.h <<_ACEOF #define CBC_VERSION "$PACKAGE_VERSION" _ACEOF coin_majorver=`echo $PACKAGE_VERSION | sed -n -e 's/^\([0-9]*\).*/\1/gp'` coin_minorver=`echo $PACKAGE_VERSION | sed -n -e 's/^[0-9]*\.\([0-9]*\).*/\1/gp'` coin_releasever=`echo $PACKAGE_VERSION | sed -n -e 's/^[0-9]*\.[0-9]*\.\([0-9]*\).*/\1/gp'` if test "x$coin_majorver" = x ; then coin_majorver=9999 ; fi if test "x$coin_minorver" = x ; then coin_minorver=9999 ; fi if test "x$coin_releasever" = x ; then coin_releasever=9999 ; fi cat >>confdefs.h <<_ACEOF #define CBC_VERSION_MAJOR $coin_majorver _ACEOF cat >>confdefs.h <<_ACEOF #define CBC_VERSION_MINOR $coin_minorver _ACEOF cat >>confdefs.h <<_ACEOF #define CBC_VERSION_RELEASE $coin_releasever _ACEOF # We use the following variable to have a string with the upper case # version of the project name COIN_PRJCT=CBC # Set the project's SVN revision number. The complicated sed expression # (made worse by quadrigraphs) ensures that things like 4123:4168MS end up # as a single number. # Extract the first word of "svnversion", so it can be a program name with args. set dummy svnversion; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_have_svnversion+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$have_svnversion"; then ac_cv_prog_have_svnversion="$have_svnversion" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_svnversion="yes" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_have_svnversion" && ac_cv_prog_have_svnversion="no" fi fi have_svnversion=$ac_cv_prog_have_svnversion if test -n "$have_svnversion"; then echo "$as_me:$LINENO: result: $have_svnversion" >&5 echo "${ECHO_T}$have_svnversion" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test "x$have_svnversion" = xyes; then svn_rev_tmp=`LANG=en_EN svnversion $srcdir 2>/dev/null` if test "x$svn_rev_tmp" != xexported -a "x$svn_rev_tmp" != x -a "x$svn_rev_tmp" != "xUnversioned directory"; then CBC_SVN_REV=`echo $svn_rev_tmp | sed -n -e 's/^[0-9]*://' -e 's/\([0-9]\)[^0-9]*$/\1/p'` cat >>confdefs.h <<_ACEOF #define CBC_SVN_REV $CBC_SVN_REV _ACEOF fi fi # Capture libtool library version, if given. coin_libversion=11:12:8 # Check if user wants to produce debugging code echo "$as_me:$LINENO: checking whether we want to compile in debug mode" >&5 echo $ECHO_N "checking whether we want to compile in debug mode... $ECHO_C" >&6 # Check whether --enable-debug or --disable-debug was given. if test "${enable_debug+set}" = set; then enableval="$enable_debug" case "${enableval}" in yes) coin_debug_compile=true if test "${enable_shared+set}" = set; then :; else enable_shared=no fi ;; no) coin_debug_compile=false ;; *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-debug" >&5 echo "$as_me: error: bad value ${enableval} for --enable-debug" >&2;} { (exit 1); exit 1; }; } ;; esac else coin_debug_compile=false fi; # Check whether --enable-debug-cbc or --disable-debug-cbc was given. if test "${enable_debug_cbc+set}" = set; then enableval="$enable_debug_cbc" case "${enableval}" in yes) coin_debug_compile=true ;; no) coin_debug_compile=false ;; *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-debug-cbc" >&5 echo "$as_me: error: bad value ${enableval} for --enable-debug-cbc" >&2;} { (exit 1); exit 1; }; } ;; esac else : fi; # m4_ifvaln([Cbc], if test $coin_debug_compile = true; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Check whether --with-cbc-verbosity or --without-cbc-verbosity was given. if test "${with_cbc_verbosity+set}" = set; then withval="$with_cbc_verbosity" if test "$withval" = yes; then withval=1 fi coin_cbc_verbosity=$withval else coin_cbc_verbosity=0 fi; cat >>confdefs.h <<_ACEOF #define COIN_CBC_VERBOSITY $coin_cbc_verbosity _ACEOF # Check whether --with-cbc-checklevel or --without-cbc-checklevel was given. if test "${with_cbc_checklevel+set}" = set; then withval="$with_cbc_checklevel" if test "$withval" = yes; then withval=1 fi coin_cbc_checklevel=$withval else coin_cbc_checklevel=0 fi; cat >>confdefs.h <<_ACEOF #define COIN_CBC_CHECKLEVEL $coin_cbc_checklevel _ACEOF # m4_ifvaln([Cbc], # Get the name of the C++ compiler and appropriate compiler options # for backward compatibility # Check whether --enable-doscompile or --disable-doscompile was given. if test "${enable_doscompile+set}" = set; then enableval="$enable_doscompile" enable_doscompile=$enableval else enable_doscompile=no fi; # Check whether --enable-msvc or --disable-msvc was given. if test "${enable_msvc+set}" = set; then enableval="$enable_msvc" enable_msvc=$enableval else enable_msvc=no if test "$enable_doscompile" = msvc ; then enable_msvc=yes elif test "$enable_doscompile" != no ; then { { echo "$as_me:$LINENO: error: --enable-doscompile=$enable_doscompile not supported anymore." >&5 echo "$as_me: error: --enable-doscompile=$enable_doscompile not supported anymore." >&2;} { (exit 1); exit 1; }; } fi fi; if test "$enable_msvc" = MD; then enable_shared=yes enable_msvc=yes fi if test "$enable_msvc" = yes; then case $build in *-cygwin* | *-mingw*) ;; *) { { echo "$as_me:$LINENO: error: --enable-msvc option makes sense only under Cygwin or MinGW" >&5 echo "$as_me: error: --enable-msvc option makes sense only under Cygwin or MinGW" >&2;} { (exit 1); exit 1; }; } ;; esac fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # For consistency, we set the C compiler to the same value of the C++ # compiler, if the C++ is set, but the C compiler isn't (only for CXX=cl) if test x"$CXX" != x; then case "$CXX" in clang* ) ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) if test x"$CC" = x; then CC="$CXX" { echo "$as_me:$LINENO: WARNING: C++ compiler name provided as $CXX, but CC is unset. Setting CC to $CXX" >&5 echo "$as_me: WARNING: C++ compiler name provided as $CXX, but CC is unset. Setting CC to $CXX" >&2;} fi ;; esac fi coin_has_cc=yes save_cflags="$CFLAGS" # For *-*-solaris*, promote Studio/Workshop cc compiler to front of list. # Depending on the user's PATH, when Studio/Workshop cc is not present we may # find /usr/ucb/cc, which is almost certainly not a good choice for the C # compiler. In this case, put cc after gcc. case $build in *-cygwin* | *-mingw*) if test "$enable_msvc" = yes ; then comps="icl cl gcc" else comps="gcc icl cl" fi ;; *-*-solaris*) # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_sol_cc_compiler+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$sol_cc_compiler"; then ac_cv_prog_sol_cc_compiler="$sol_cc_compiler" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_sol_cc_compiler="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_sol_cc_compiler shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set sol_cc_compiler to just the basename; use the full file name. shift ac_cv_prog_sol_cc_compiler="$as_dir/$ac_word${1+' '}$@" fi fi fi fi sol_cc_compiler=$ac_cv_prog_sol_cc_compiler if test -n "$sol_cc_compiler"; then echo "$as_me:$LINENO: result: $sol_cc_compiler" >&5 echo "${ECHO_T}$sol_cc_compiler" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test "$sol_cc_compiler" = "cc" ; then comps="cc xlc gcc pgcc icc" else comps="xlc gcc pgcc icc cc" fi ;; *-*-darwin*) comps="clang gcc" ;; *-linux-gnu*) comps="gcc cc pgcc icc xlc" ;; *-linux-*) comps="xlc gcc cc pgcc icc" ;; *) comps="xlc_r xlc cc gcc pgcc icc" ;; esac # We delete the cached value, since the test might not have been # performed with our choice of compilers earlier $as_unset ac_cv_prog_CC || test "${ac_cv_prog_CC+set}" != set || { ac_cv_prog_CC=; export ac_cv_prog_CC; } # AC_MSG_NOTICE([C compiler candidates: $comps]) ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in $comps do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in $comps do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -z "$CC" ; then { { echo "$as_me:$LINENO: error: Failed to find a C compiler!" >&5 echo "$as_me: error: Failed to find a C compiler!" >&2;} { (exit 1); exit 1; }; } fi # Autoconf incorrectly concludes that cl recognises -g. It doesn't. case "$CC" in clang* ) ;; cl* | */cl* | CL* | */CL* ) if test "$ac_cv_prog_cc_g" = yes ; then ac_cv_prog_cc_g=no { echo "$as_me:$LINENO: Overruling autoconf; cl does not recognise -g." >&5 echo "$as_me: Overruling autoconf; cl does not recognise -g." >&6;} fi ;; * ) if test x"$CYGPATH_W" = x ; then CYGPATH_W=echo fi ;; esac CFLAGS="$save_cflags" # add automake conditional so we can recognize cl compiler in makefile coin_cc_is_cl=false case "$CC" in clang* ) ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) coin_cc_is_cl=true ;; esac if test $coin_cc_is_cl = true; then COIN_CC_IS_CL_TRUE= COIN_CC_IS_CL_FALSE='#' else COIN_CC_IS_CL_TRUE='#' COIN_CC_IS_CL_FALSE= fi # Check if a project specific CFLAGS variable has been set if test x$COIN_PRJCT != x; then eval coin_tmp=\${${COIN_PRJCT}_CFLAGS+set} if test x$coin_tmp = xset; then eval CFLAGS=\${${COIN_PRJCT}_CFLAGS} fi fi if test x"$CFLAGS" = x; then coin_add_cflags= coin_opt_cflags= coin_dbg_cflags= coin_warn_cflags= if test "$GCC" = "yes"; then case "$CC" in icc* | */icc*) ;; *) coin_opt_cflags="-O3" coin_add_cflags="-pipe" coin_dbg_cflags="-g -O0" coin_warn_cflags="-Wimplicit -Wparentheses -Wsequence-point -Wreturn-type -Wcast-qual -Wall -Wno-unknown-pragmas -Wno-long-long" case $build in *-darwin*) ;; *) coin_warn_cflags="-pedantic-errors $coin_warn_cflags" ;; esac esac fi if test -z "$coin_opt_cflags"; then case $build in *-cygwin* | *-mingw*) case "$CC" in clang* ) ;; cl* | */cl* | CL* | */CL*) if test "$coin_disable_shared" = yes || test "$enable_shared" = yes ; then coin_opt_cflags='-MD -O2' coin_dbg_cflags='-MDd' else coin_opt_cflags='-MT -O2' coin_dbg_cflags='-MTd' fi coin_add_cflags='-nologo -wd4996 -D_CRT_SECURE_NO_DEPRECATE' ;; icl* | */icl* | ICL* | */ICL*) if test "$coin_disable_shared" = yes || test "$enable_shared" = yes ; then coin_opt_cflags='-MD -Ox' coin_dbg_cflags='-MDd -debug' else coin_opt_cflags='-MT -Ox' coin_dbg_cflags='-MTd -debug' fi coin_add_cflags='-nologo -D_CRT_SECURE_NO_DEPRECATE' ;; esac ;; *-linux-*) case "$CC" in icc* | */icc*) coin_opt_cflags="-O3 -ip -mp1" coin_add_cflags="" coin_dbg_cflags="-g" # Check if -i_dynamic is necessary (for new glibc library) CFLAGS= cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i=0; i++; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 coin_add_cflags="-i_dynamic $coin_add_cflags" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; pgcc* | */pgcc*) coin_opt_cflags="-fast" coin_add_cflags="-Kieee -pc 64" coin_dbg_cflags="-g" ;; esac ;; *-ibm-*) case "$CC" in xlc* | */xlc* | mpxlc* | */mpxlc*) coin_opt_cflags="-O -qarch=auto -qcache=auto -qtune=auto -qmaxmem=-1" coin_add_cflags="-bmaxdata:0x80000000 -qsuppress=1500-036 -qsuppress=1500-029" coin_dbg_cflags="-g" ;; esac ;; *-hp-*) coin_opt_cflags="-O" coin_add_cflags="-Ae" coin_dbg_cflags="-g" ;; *-*-solaris*) coin_opt_cflags="-xO4" coin_dbg_cflags="-g" ;; *-sgi-*) coin_opt_cflags="-O -OPT:Olimit=0" coin_dbg_cflags="-g" ;; esac fi if test "$ac_cv_prog_cc_g" = yes && test -z "$coin_dbg_cflags" ; then coin_dbg_cflags="-g" fi if test -z "$coin_opt_cflags"; then # Try if -O option works if nothing else is set CFLAGS="-O" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i=0; i++; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then coin_opt_cflags="-O" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi # if PM doesn't want the warning messages, take them out if test x"$coin_skip_warn_cflags" = xyes; then coin_warn_cflags= fi if test x${DBG_CFLAGS+set} != xset; then DBG_CFLAGS="$coin_dbg_cflags $coin_add_cflags $coin_warn_cflags" fi if test x${OPT_CFLAGS+set} != xset; then OPT_CFLAGS="$coin_opt_cflags $coin_add_cflags -DNDEBUG $coin_warn_cflags" fi DBG_CFLAGS="$DBG_CFLAGS $ADD_CFLAGS $CDEFS" OPT_CFLAGS="$OPT_CFLAGS $ADD_CFLAGS $CDEFS" if test "$coin_debug_compile" = "true"; then CFLAGS="$DBG_CFLAGS" else CFLAGS="$OPT_CFLAGS" fi else CFLAGS="$CFLAGS $ADD_CFLAGS $CDEFS" if test x${DBG_CFLAGS+set} != xset; then DBG_CFLAGS="$CFLAGS" fi if test x${OPT_CFLAGS+set} != xset; then OPT_CFLAGS="$CFLAGS" fi fi # add -DPROJECT_BUILD to signal compiler preprocessor which config header file to include if test x$COIN_PRJCT != x; then CFLAGS="$CFLAGS -D${COIN_PRJCT}_BUILD" fi # Try if CFLAGS works save_CFLAGS="$CFLAGS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i=0; i++; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS= fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$CFLAGS"; then { echo "$as_me:$LINENO: WARNING: The value CFLAGS=\"$save_CFLAGS\" do not work. I will now just try '-O', but you might want to set CFLAGS manually." >&5 echo "$as_me: WARNING: The value CFLAGS=\"$save_CFLAGS\" do not work. I will now just try '-O', but you might want to set CFLAGS manually." >&2;} CFLAGS='-O' cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i=0; i++; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS= fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$CFLAGS"; then { echo "$as_me:$LINENO: WARNING: This value for CFLAGS does not work. I will continue with empty CFLAGS, but you might want to set CFLAGS manually." >&5 echo "$as_me: WARNING: This value for CFLAGS does not work. I will continue with empty CFLAGS, but you might want to set CFLAGS manually." >&2;} fi fi { echo "$as_me:$LINENO: C compiler options are: $CFLAGS" >&5 echo "$as_me: C compiler options are: $CFLAGS" >&6;} if test x"$MPICC" = x; then :; else { echo "$as_me:$LINENO: Will use MPI C compiler $MPICC" >&5 echo "$as_me: Will use MPI C compiler $MPICC" >&6;} CC="$MPICC" fi # Correct the LD variable if we are using the MS or Intel-windows compiler case "$CC" in clang* ) ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) LD=link ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #Let's try if that overcomes configuration problem with VC++ 6.0 ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu coin_has_cxx=yes save_cxxflags="$CXXFLAGS" # For *-*-solaris*, promote Studio/Workshop compiler to front of list. case $build in *-cygwin* | *-mingw*) if test "$enable_msvc" = yes ; then comps="icl cl g++" else comps="g++ icl cl" fi ;; *-*-solaris*) comps="CC xlC_r aCC g++ c++ pgCC icpc gpp cxx cc++ cl FCC KCC RCC" ;; *-darwin*) comps="g++ c++ CC" ;; *-linux-gnu*) comps="g++ c++ pgCC icpc gpp cxx cc++ cl FCC KCC RCC xlC_r aCC CC" ;; *) comps="xlC_r aCC CC g++ c++ pgCC icpc gpp cxx cc++ cl FCC KCC RCC" ;; esac # We delete the cached value, since the test might not have been # performed with our choice of compilers earlier $as_unset ac_cv_prog_CXX || test "${ac_cv_prog_CXX+set}" != set || { ac_cv_prog_CXX=; export ac_cv_prog_CXX; } # AC_MSG_NOTICE([C++ compiler candidates: $comps]) ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in $CCC $comps do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then echo "$as_me:$LINENO: result: $CXX" >&5 echo "${ECHO_T}$CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in $CCC $comps do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 echo "${ECHO_T}$ac_ct_CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CXX" && break done test -n "$ac_ct_CXX" || ac_ct_CXX="g++" CXX=$ac_ct_CXX fi # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C++ compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 GXX=`test $ac_compiler_gnu = yes && echo yes` ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS CXXFLAGS="-g" echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cxx_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu #AC_PROG_CXX sets CXX to g++ if it cannot find a working C++ compiler #thus, we test here whether $CXX is actually working ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu echo "$as_me:$LINENO: checking whether C++ compiler $CXX works" >&5 echo $ECHO_N "checking whether C++ compiler $CXX works... $ECHO_C" >&6; cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i=0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: failed to find a C++ compiler or C++ compiler $CXX does not work" >&5 echo "$as_me: error: failed to find a C++ compiler or C++ compiler $CXX does not work" >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu coin_cxx_is_cl=false # It seems that we need to cleanup something here for the Windows case "$CXX" in clang* ) ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) sed -e 's/^void exit (int);//' confdefs.h >> confdefs.hh mv confdefs.hh confdefs.h coin_cxx_is_cl=true ;; esac # add automake conditional so we can recognize cl compiler in makefile if test $coin_cxx_is_cl = true; then COIN_CXX_IS_CL_TRUE= COIN_CXX_IS_CL_FALSE='#' else COIN_CXX_IS_CL_TRUE='#' COIN_CXX_IS_CL_FALSE= fi # Autoconf incorrectly concludes that cl recognises -g. It doesn't. case "$CXX" in clang* ) ;; cl* | */cl* | CL* | */CL* ) if test "$ac_cv_prog_cxx_g" = yes ; then ac_cv_prog_cxx_g=no { echo "$as_me:$LINENO: Overruling autoconf; cl does not recognise -g." >&5 echo "$as_me: Overruling autoconf; cl does not recognise -g." >&6;} fi ;; * ) if test x"$CYGPATH_W" = x ; then CYGPATH_W=echo fi ;; esac CXXFLAGS="$save_cxxflags" # Check if a project specific CXXFLAGS variable has been set if test x$COIN_PRJCT != x; then eval coin_tmp=\${${COIN_PRJCT}_CXXFLAGS+set} if test x$coin_tmp = xset; then eval CXXFLAGS=\${${COIN_PRJCT}_CXXFLAGS} fi fi if test x"$CXXFLAGS" = x; then # ToDo decide whether we want -DNDEBUG for optimization coin_add_cxxflags= coin_opt_cxxflags= coin_dbg_cxxflags= coin_warn_cxxflags= if test "$GXX" = "yes"; then case "$CXX" in icpc* | */icpc*) ;; *) # ToDo decide about unroll-loops coin_opt_cxxflags="-O3" coin_add_cxxflags="-pipe" coin_dbg_cxxflags="-g -O0" coin_warn_cxxflags="-Wparentheses -Wreturn-type -Wcast-qual -Wall -Wpointer-arith -Wwrite-strings -Wconversion -Wno-unknown-pragmas -Wno-long-long" case $build in *-darwin*) ;; *) coin_warn_cxxflags="-pedantic-errors $coin_warn_cxxflags" ;; esac esac fi # Note that we do not need to cover GCC in the following tests. if test -z "$coin_opt_cxxflags"; then case $build in *-cygwin* | *-mingw*) case "$CXX" in clang* ) ;; cl* | */cl* | CL* | */CL*) # The MT and MTd options are mutually exclusive if test "$coin_disable_shared" = yes || test "$enable_shared" = yes ; then coin_opt_cxxflags='-MD -O2' coin_dbg_cxxflags='-MDd' else coin_opt_cxxflags='-MT -O2' coin_dbg_cxxflags='-MTd' fi coin_add_cxxflags='-nologo -EHsc -GR -wd4996 -D_CRT_SECURE_NO_DEPRECATE' ;; icl* | */icl* | ICL* | */ICL*) # The MT and MTd options are mutually exclusive if test "$coin_disable_shared" = yes || test "$enable_shared" = yes ; then coin_opt_cxxflags='-MD -Ox' coin_dbg_cxxflags='-MDd -debug' else coin_opt_cxxflags='-MT -Ox' coin_dbg_cxxflags='-MTd -debug' fi coin_add_cxxflags='-nologo -EHsc -GR -D_CRT_SECURE_NO_DEPRECATE' ;; esac ;; *-linux-*) case "$CXX" in icpc* | */icpc*) coin_opt_cxxflags="-O3 -ip -mp1" coin_add_cxxflags="" coin_dbg_cxxflags="-g" # Check if -i_dynamic is necessary (for new glibc library) CXXFLAGS= cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i=0; i++; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 coin_add_cxxflags="-i_dynamic $coin_add_cxxflags" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; pgCC* | */pgCC*) coin_opt_cxxflags="-fast" coin_add_cxxflags="-Kieee -pc 64" coin_dbg_cxxflags="-g" ;; esac ;; *-ibm-*) case "$CXX" in xlC* | */xlC* | mpxlC* | */mpxlC*) coin_opt_cxxflags="-O -qarch=auto -qcache=auto -qtune=auto -qmaxmem=-1" coin_add_cxxflags="-bmaxdata:0x80000000 -qrtti=dyna -qsuppress=1500-036 -qsuppress=1500-029 -qsourcetype=c++" coin_dbg_cxxflags="-g" ;; esac ;; *-hp-*) case "$CXX" in aCC* | */aCC* ) coin_opt_cxxflags="-O" coin_add_cxxflags="-AA" coin_dbg_cxxflags="-g" ;; esac ;; *-*-solaris*) coin_opt_cxxflags="-O4" coin_dbg_cxxflags="-g" ;; esac fi # Generic flag settings. If these don't work, add a case above. if test "$ac_cv_prog_cxx_g" = yes && test -z "$coin_dbg_cxxflags" ; then coin_dbg_cxxflags="-g" fi if test -z "$coin_opt_cxxflags"; then # Try if -O option works if nothing else is set CXXFLAGS=-O cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i=0; i++; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then coin_opt_cxxflags="-O" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi # if PM doesn't want the warning messages, take them out if test x"$coin_skip_warn_cxxflags" = xyes; then coin_warn_cxxflags= fi # Do final setup of flags based on values determined above. if test x${DBG_CXXFLAGS+set} != xset; then DBG_CXXFLAGS="$coin_dbg_cxxflags $coin_add_cxxflags $coin_warn_cxxflags" fi if test x${OPT_CXXFLAGS+set} != xset; then OPT_CXXFLAGS="$coin_opt_cxxflags $coin_add_cxxflags -DNDEBUG $coin_warn_cxxflags" fi DBG_CXXFLAGS="$DBG_CXXFLAGS $ADD_CXXFLAGS $CXXDEFS" OPT_CXXFLAGS="$OPT_CXXFLAGS $ADD_CXXFLAGS $CXXDEFS" if test "$coin_debug_compile" = "true"; then CXXFLAGS="$DBG_CXXFLAGS" else CXXFLAGS="$OPT_CXXFLAGS" fi # Handle the case where CXXFLAGS was set externally. else CXXFLAGS="$CXXFLAGS $ADD_CXXFLAGS $CXXDEFS" if test x${DBG_CXXFLAGS+set} != xset; then DBG_CXXFLAGS="$CXXFLAGS" fi if test x${OPT_CXXFLAGS+set} != xset; then OPT_CXXFLAGS="$CXXFLAGS" fi fi # add -DPROJECT_BUILD to signal compiler preprocessor which config header file to include if test x$COIN_PRJCT != x; then CXXFLAGS="$CXXFLAGS -D${COIN_PRJCT}_BUILD" fi # Try if CXXFLAGS works save_CXXFLAGS="$CXXFLAGS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i=0; i++; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CXXFLAGS= fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$CXXFLAGS"; then { echo "$as_me:$LINENO: WARNING: The flags CXXFLAGS=\"$save_CXXFLAGS\" do not work. I will now just try '-O', but you might want to set CXXFLAGS manually." >&5 echo "$as_me: WARNING: The flags CXXFLAGS=\"$save_CXXFLAGS\" do not work. I will now just try '-O', but you might want to set CXXFLAGS manually." >&2;} CXXFLAGS='-O' cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i=0; i++; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CXXFLAGS= fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$CXXFLAGS"; then { echo "$as_me:$LINENO: WARNING: This value for CXXFLAGS does not work. I will continue with empty CXXFLAGS, but you might want to set CXXFLAGS manually." >&5 echo "$as_me: WARNING: This value for CXXFLAGS does not work. I will continue with empty CXXFLAGS, but you might want to set CXXFLAGS manually." >&2;} fi fi { echo "$as_me:$LINENO: C++ compiler options are: $CXXFLAGS" >&5 echo "$as_me: C++ compiler options are: $CXXFLAGS" >&6;} if test x"$MPICXX" = x; then :; else { echo "$as_me:$LINENO: Will use MPI C++ compiler $MPICXX" >&5 echo "$as_me: Will use MPI C++ compiler $MPICXX" >&6;} CXX="$MPICXX" fi # correct the LD variable in a build with MS or intel compiler case "$CXX" in clang* ) ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) LD=link ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Initialize automake and libtool { # START coin_disable_shared=no # Test if force_shared has been set if test "x" = xforce_shared; then if test x$enable_shared = xno; then { { echo "$as_me:$LINENO: error: Shared libraries are disabled by user, but this is not feasible with the given options" >&5 echo "$as_me: error: Shared libraries are disabled by user, but this is not feasible with the given options" >&2;} { (exit 1); exit 1; }; } fi enable_shared=yes; else # On Cygwin and AIX, building DLLs doesn't work case $build in *-cygwin* | *-mingw*) coin_disable_shared=yes if test x"$enable_shared" = xyes; then case "$CC" in clang* ) { echo "$as_me:$LINENO: WARNING: DLL building not supported. I'm disabling your choice." >&5 echo "$as_me: WARNING: DLL building not supported. I'm disabling your choice." >&2;} ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) { echo "$as_me:$LINENO: DLL building not supported, but will build with -MD(d) instead of -MT(d)." >&5 echo "$as_me: DLL building not supported, but will build with -MD(d) instead of -MT(d)." >&6;} ;; *gcc*) if test x"$enable_dependency_linking" = xyes; then coin_disable_shared=no else { echo "$as_me:$LINENO: WARNING: To build shared libraries with gcc on CYGWIN or MSys, use --enable-dependency-linking" >&5 echo "$as_me: WARNING: To build shared libraries with gcc on CYGWIN or MSys, use --enable-dependency-linking" >&2;} fi ;; *) { echo "$as_me:$LINENO: WARNING: DLL building not supported. I'm disabling your choice." >&5 echo "$as_me: WARNING: DLL building not supported. I'm disabling your choice." >&2;} ;; esac fi ;; *-aix*) coin_disable_shared=yes platform=AIX if test x"$enable_shared" = xyes; then { echo "$as_me:$LINENO: WARNING: Shared objects are not supported. I'm disabling your choice." >&5 echo "$as_me: WARNING: Shared objects are not supported. I'm disabling your choice." >&2;} fi ;; esac fi if test x"$coin_disable_shared" = xyes; then if test x"$enable_shared" = xyes; then : else # we don't disable shared, because it was not selected anyway coin_disable_shared=no fi enable_shared=no fi # By default, we only want the shared objects to be compiled # Check whether --enable-static or --disable-static was given. if test "${enable_static+set}" = set; then enableval="$enable_static" p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=no fi; # Initialize automake echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking whether ln -s works" >&5 echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no, using $LN_S" >&5 echo "${ECHO_T}no, using $LN_S" >&6 fi am__api_version="1.9" # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL=$ac_install_sh fi fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo "$as_me:$LINENO: checking whether build environment is sane" >&5 echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 test "$program_prefix" != NONE && program_transform_name="s,^,$program_prefix,;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$,$program_suffix,;$program_transform_name" # Double any \ or $. echo might interpret backslashes. # By default was `s,x,x', remove it if useless. cat <<\_ACEOF >conftest.sed s/[\\$]/&&/g;s/;s,x,x,$// _ACEOF program_transform_name=`echo $program_transform_name | sed -f conftest.sed` rm conftest.sed # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$AWK" && break done echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi echo "$as_me:$LINENO: result: $_am_result" >&5 echo "${ECHO_T}$_am_result" >&6 rm -f confinc confmf # Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval="$enable_dependency_tracking" fi; if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi # AC_MSG_NOTICE([Beginning automake initialisation.]) # Stuff for automake # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='cbc' VERSION='2.8.12' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} install_sh=${install_sh-"$am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi STRIP=$ac_ct_STRIP else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' depcc="$CC" am_compiler_list= echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi depcc="$CXX" am_compiler_list= echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5 echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi; echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5 echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6 if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE coin_have_externals=no if test "$enable_maintainer_mode" = yes; then # If maintainer mode is chosen, we make sure that the correct versions # of the tools are used, and that we know where libtool.m4 is (to # recreate acinclude.m4) LIBTOOLM4= # Normally, $HOME AUTOTOOLS_DFLT=$HOME echo "$as_me:$LINENO: checking whether we are using the correct autotools" >&5 echo $ECHO_N "checking whether we are using the correct autotools... $ECHO_C" >&6 if test "${ac_cv_use_correct_autotools+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_use_correct_autotools=check fi echo "$as_me:$LINENO: result: $ac_cv_use_correct_autotools" >&5 echo "${ECHO_T}$ac_cv_use_correct_autotools" >&6 if test $ac_cv_use_correct_autotools = check; then ac_cv_use_correct_autotools=yes # Check if we have autoconf # Extract the first word of "autoconf", so it can be a program name with args. set dummy autoconf; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_have_autoconf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$have_autoconf"; then ac_cv_prog_have_autoconf="$have_autoconf" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_autoconf="yes" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_have_autoconf" && ac_cv_prog_have_autoconf="no" fi fi have_autoconf=$ac_cv_prog_have_autoconf if test -n "$have_autoconf"; then echo "$as_me:$LINENO: result: $have_autoconf" >&5 echo "${ECHO_T}$have_autoconf" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test $have_autoconf = no; then { { echo "$as_me:$LINENO: error: You specified you want to use maintainer mode, but I cannot find autoconf in your path." >&5 echo "$as_me: error: You specified you want to use maintainer mode, but I cannot find autoconf in your path." >&2;} { (exit 1); exit 1; }; } fi # Check whether autoconf is the correct version correct_version='2.59' grep_version=`echo $correct_version | sed -e 's/\\./\\\\\\./g'` echo "$as_me:$LINENO: checking whether we are using the correct version ($correct_version) of autoconf" >&5 echo $ECHO_N "checking whether we are using the correct version ($correct_version) of autoconf... $ECHO_C" >&6 autoconf --version > confauto.out 2>&1 if $EGREP $grep_version confauto.out >/dev/null 2>&1; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else rm -f confauto.out echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: You don't have the correct version of autoconf as the first one in your path." >&5 echo "$as_me: error: You don't have the correct version of autoconf as the first one in your path." >&2;} { (exit 1); exit 1; }; } fi rm -f confauto.out # Check if the executable autoconf is picked up from the correct location echo "$as_me:$LINENO: checking whether autoconf is coming from the correct location" >&5 echo $ECHO_N "checking whether autoconf is coming from the correct location... $ECHO_C" >&6 autoconf_dir=`which autoconf | sed -e 's=/autoconf=='` autoconf_dir=`cd $autoconf_dir; pwd` if test x$AUTOTOOLS_DIR = x; then want_dir=$AUTOTOOLS_DFLT/bin else want_dir=$AUTOTOOLS_DIR/bin fi if test $autoconf_dir = `cd $want_dir; pwd`; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else rm -f confauto.out echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: The autoconf executable should be picked up from \$AUTOTOOLS_DFLT/bin or \$AUTOTOOLS_DIR/bin." >&5 echo "$as_me: error: The autoconf executable should be picked up from \$AUTOTOOLS_DFLT/bin or \$AUTOTOOLS_DIR/bin." >&2;} { (exit 1); exit 1; }; } fi # Check if we have automake # Extract the first word of "automake", so it can be a program name with args. set dummy automake; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_have_automake+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$have_automake"; then ac_cv_prog_have_automake="$have_automake" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_automake="yes" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_have_automake" && ac_cv_prog_have_automake="no" fi fi have_automake=$ac_cv_prog_have_automake if test -n "$have_automake"; then echo "$as_me:$LINENO: result: $have_automake" >&5 echo "${ECHO_T}$have_automake" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test $have_automake = no; then { { echo "$as_me:$LINENO: error: You specified you want to use maintainer mode, but I cannot find automake in your path." >&5 echo "$as_me: error: You specified you want to use maintainer mode, but I cannot find automake in your path." >&2;} { (exit 1); exit 1; }; } fi # Check whether automake is the correct version correct_version='1.9.6' grep_version=`echo $correct_version | sed -e 's/\\./\\\\\\./g'` echo "$as_me:$LINENO: checking whether we are using the correct version ($correct_version) of automake" >&5 echo $ECHO_N "checking whether we are using the correct version ($correct_version) of automake... $ECHO_C" >&6 automake --version > confauto.out 2>&1 if $EGREP $grep_version confauto.out >/dev/null 2>&1; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else rm -f confauto.out echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: You don't have the correct version of automake as the first one in your path." >&5 echo "$as_me: error: You don't have the correct version of automake as the first one in your path." >&2;} { (exit 1); exit 1; }; } fi rm -f confauto.out # Check if the executable automake is picked up from the correct location echo "$as_me:$LINENO: checking whether automake is coming from the correct location" >&5 echo $ECHO_N "checking whether automake is coming from the correct location... $ECHO_C" >&6 automake_dir=`which automake | sed -e 's=/automake=='` automake_dir=`cd $automake_dir; pwd` if test x$AUTOTOOLS_DIR = x; then want_dir=$AUTOTOOLS_DFLT/bin else want_dir=$AUTOTOOLS_DIR/bin fi if test $automake_dir = `cd $want_dir; pwd`; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else rm -f confauto.out echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: The automake executable should be picked up from \$AUTOTOOLS_DFLT/bin or \$AUTOTOOLS_DIR/bin." >&5 echo "$as_me: error: The automake executable should be picked up from \$AUTOTOOLS_DFLT/bin or \$AUTOTOOLS_DIR/bin." >&2;} { (exit 1); exit 1; }; } fi # Check if this is the correct version of libtool (with escaped dots) if test x$AUTOTOOLS_DIR = x; then want_dir=$AUTOTOOLS_DFLT/share else want_dir=$AUTOTOOLS_DIR/share fi correct_version='1.5.22' grep_version=`echo $correct_version | sed -e 's/\\./\\\\\\./g'` if test -r $want_dir/libtool/ltmain.sh; then have_ltmain=yes : else have_ltmain=no : fi echo "$as_me:$LINENO: checking whether we are using the correct version ($correct_version) of libtool." >&5 echo $ECHO_N "checking whether we are using the correct version ($correct_version) of libtool.... $ECHO_C" >&6 if test $have_ltmain = yes; then if $EGREP $grep_version $want_dir/libtool/ltmain.sh >/dev/null 2>&1; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: You don't have the correct version of libtool." >&5 echo "$as_me: error: You don't have the correct version of libtool." >&2;} { (exit 1); exit 1; }; } fi else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: I cannot find the ltmain.sh file." >&5 echo "$as_me: error: I cannot find the ltmain.sh file." >&2;} { (exit 1); exit 1; }; } fi fi # Check if we can find the libtool file if test x$AUTOTOOLS_DIR = x; then want_dir=$AUTOTOOLS_DFLT/share else want_dir=$AUTOTOOLS_DIR/share fi if test -r $want_dir/aclocal/libtool.m4; then LIBTOOLM4="$want_dir/aclocal/libtool.m4" : else { { echo "$as_me:$LINENO: error: I cannot find the libtool.m4 file." >&5 echo "$as_me: error: I cannot find the libtool.m4 file." >&2;} { (exit 1); exit 1; }; } : fi # Check if we have an Dependencies file if test -r $srcdir/Dependencies; then coin_have_externals=yes fi # Check if subversion is installed and understands https # Extract the first word of "svn", so it can be a program name with args. set dummy svn; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_have_svn+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$have_svn"; then ac_cv_prog_have_svn="$have_svn" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_svn="yes" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_have_svn" && ac_cv_prog_have_svn="no" fi fi have_svn=$ac_cv_prog_have_svn if test -n "$have_svn"; then echo "$as_me:$LINENO: result: $have_svn" >&5 echo "${ECHO_T}$have_svn" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test x$have_svn = xyes; then echo "$as_me:$LINENO: checking whether svn understands https" >&5 echo $ECHO_N "checking whether svn understands https... $ECHO_C" >&6 if test "${ac_cv_svn_understands_https+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else svn --version > confauto.out 2>&1 if $EGREP https confauto.out >/dev/null 2>&1; then ac_cv_svn_understands_https=yes else ac_cv_svn_understands_https=no have_svn=no ac_cv_prog_have_svn=no fi rm -f confauto.out fi echo "$as_me:$LINENO: result: $ac_cv_svn_understands_https" >&5 echo "${ECHO_T}$ac_cv_svn_understands_https" >&6 fi # Find the location of the BuildTools directory BUILDTOOLSDIR= if test -r $srcdir/BuildTools/coin.m4; then BUILDTOOLSDIR=$srcdir/BuildTools else if test -r $srcdir/../BuildTools/coin.m4; then BUILDTOOLSDIR=$srcdir/../BuildTools else if test -r $srcdir/../../BuildTools/coin.m4; then BUILDTOOLSDIR=$srcdir/../../BuildTools else { { echo "$as_me:$LINENO: error: Cannot find the BuildTools directory" >&5 echo "$as_me: error: Cannot find the BuildTools directory" >&2;} { (exit better disable maintainer mode.); exit better disable maintainer mode.; }; } fi fi fi # for running automake by make, we need to have Makemain.inc available at the place where it usually can be found during run_autotools if test "$BUILDTOOLSDIR" != "$srcdir/BuildTools" ; then $LN_S `cd $BUILDTOOLSDIR; pwd` "$srcdir/BuildTools" fi # The following variable is set to the name of the directory where # the autotool scripts are located AUX_DIR=$ac_aux_dir fi # helpful variable for the base directory of this package abs_source_dir=`cd $srcdir; pwd` # Stuff for example Makefiles if test x$prefix = xNONE; then full_prefix=$ac_default_prefix else full_prefix=$prefix fi full_prefix=`cd $full_prefix ; pwd` abs_lib_dir=$full_prefix/lib abs_include_dir=$full_prefix/include abs_bin_dir=$full_prefix/bin if test $coin_have_externals = yes && test x$have_svn = xyes; then HAVE_EXTERNALS_TRUE= HAVE_EXTERNALS_FALSE='#' else HAVE_EXTERNALS_TRUE='#' HAVE_EXTERNALS_FALSE= fi # AC_MSG_NOTICE([End automake initialisation.]) LIBTOOL= if test -f ../libtool; then coin_config_dir=.. LIBTOOL='$(SHELL) $(top_builddir)/../libtool' fi if test "x$LIBTOOL" = x; then if test -f ../../libtool; then coin_config_dir=../.. LIBTOOL='$(SHELL) $(top_builddir)/../../libtool' fi fi if test "x$LIBTOOL" = x; then # AC_MSG_NOTICE([Creating libtool script (calling COIN_PROG_LIBTOOL).]) # Stuff for libtool # Check whether --enable-shared or --disable-shared was given. if test "${enable_shared+set}" = set; then enableval="$enable_shared" p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi; # Check whether --enable-fast-install or --disable-fast-install was given. if test "${enable_fast_install+set}" = set; then enableval="$enable_fast_install" p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi; echo "$as_me:$LINENO: checking host system type" >&5 echo $ECHO_N "checking host system type... $ECHO_C" >&6 if test "${ac_cv_host+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_host_alias=$host_alias test -z "$ac_cv_host_alias" && ac_cv_host_alias=$ac_cv_build_alias ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6 host=$ac_cv_host host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6 if test "${lt_cv_path_SED+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done fi SED=$lt_cv_path_SED echo "$as_me:$LINENO: result: $SED" >&5 echo "${ECHO_T}$SED" >&6 # Check whether --with-gnu-ld or --without-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval="$with_gnu_ld" test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi; ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo "$as_me:$LINENO: checking for ld used by $CC" >&5 echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then echo "$as_me:$LINENO: checking for GNU ld" >&5 echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 else echo "$as_me:$LINENO: checking for non-GNU ld" >&5 echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 fi if test "${lt_cv_path_LD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 echo "${ECHO_T}$LD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 if test "${lt_cv_prog_gnu_ld+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 with_gnu_ld=$lt_cv_prog_gnu_ld echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6 if test "${lt_cv_ld_reload_flag+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_ld_reload_flag='-r' fi echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6 reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6 if test "${lt_cv_path_NM+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi fi echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 echo "${ECHO_T}$lt_cv_path_NM" >&6 NM="$lt_cv_path_NM" echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6 if test "${lt_cv_deplibs_check_method+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix4* | aix5*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump'. lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | kfreebsd*-gnu | dragonfly*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix3*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; nto-qnx*) lt_cv_deplibs_check_method=unknown ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac fi echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6 file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check whether --enable-libtool-lock or --disable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval="$enable_libtool_lock" fi; test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 5873 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6 if test "${lt_cv_cc_needs_belf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then lt_cv_cc_needs_belf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_cc_needs_belf=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6 if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) LD="${LD-ld} -64" ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to cbc@lists.coin-or.org ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 if test -z "$CXXCPP"; then if test "${ac_cv_prog_CXXCPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi echo "$as_me:$LINENO: result: $CXXCPP" >&5 echo "${ECHO_T}$CXXCPP" >&6 ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu fi ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$F77"; then ac_cv_prog_F77="$F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_F77="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi F77=$ac_cv_prog_F77 if test -n "$F77"; then echo "$as_me:$LINENO: result: $F77" >&5 echo "${ECHO_T}$F77" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$F77" && break done fi if test -z "$F77"; then ac_ct_F77=$F77 for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_F77"; then ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_F77="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_F77=$ac_cv_prog_ac_ct_F77 if test -n "$ac_ct_F77"; then echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 echo "${ECHO_T}$ac_ct_F77" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_F77" && break done F77=$ac_ct_F77 fi # Provide some information about the compiler. echo "$as_me:7007:" \ "checking for Fortran 77 compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -f a.out # If we don't use `.F' as extension, the preprocessor is not run on the # input file. (Note that this only needs to work for GNU compilers.) ac_save_ext=$ac_ext ac_ext=F echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6 if test "${ac_cv_f77_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF program main #ifndef __GNUC__ choke me #endif end _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_f77_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6 ac_ext=$ac_save_ext ac_test_FFLAGS=${FFLAGS+set} ac_save_FFLAGS=$FFLAGS FFLAGS= echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_f77_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else FFLAGS=-g cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_f77_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_f77_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 echo "${ECHO_T}$ac_cv_prog_f77_g" >&6 if test "$ac_test_FFLAGS" = set; then FFLAGS=$ac_save_FFLAGS elif test $ac_cv_prog_f77_g = yes; then if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-g -O2" else FFLAGS="-g" fi else if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-O2" else FFLAGS= fi fi G77=`test $ac_compiler_gnu = yes && echo yes` ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! # find the maximum length of command line arguments echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6 if test "${lt_cv_sys_max_cmd_len+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ = "XX$teststring") >/dev/null 2>&1 && new_result=`expr "X$teststring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done teststring= # Add a significant safety factor because C++ compilers can tack on massive # amounts of additional arguments before passing them to the linker. # It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6 else echo "$as_me:$LINENO: result: none" >&5 echo "${ECHO_T}none" >&6 fi # Check for command to grab the raw symbol name followed by C symbol from nm. echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6 if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32*) symcode='[ABCDGISTW]' ;; hpux*) # Its linker distinguishes data from code symbols if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; linux*) if test "$host_cpu" = ia64; then symcode='[ABCDGIRSTW]' lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Now try to grab the symbols. nlist=conftest.nm if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if grep ' nm_test_var$' "$nlist" >/dev/null; then if grep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[] = { EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then echo "$as_me:$LINENO: result: failed" >&5 echo "${ECHO_T}failed" >&6 else echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6 fi echo "$as_me:$LINENO: checking for objdir" >&5 echo $ECHO_N "checking for objdir... $ECHO_C" >&6 if test "${lt_cv_objdir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 echo "${ECHO_T}$lt_cv_objdir" >&6 objdir=$lt_cv_objdir case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then echo "$as_me:$LINENO: result: $AR" >&5 echo "${ECHO_T}$AR" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false" fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 echo "${ECHO_T}$ac_ct_AR" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi AR=$ac_ct_AR else AR="$ac_cv_prog_AR" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RANLIB=$ac_ct_RANLIB else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi STRIP=$ac_ct_STRIP else STRIP="$ac_cv_prog_STRIP" fi old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$SED" && SED=sed test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6 if test "${lt_cv_path_MAGIC_CMD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 echo "${ECHO_T}$MAGIC_CMD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then echo "$as_me:$LINENO: checking for file" >&5 echo $ECHO_N "checking for file... $ECHO_C" >&6 if test "${lt_cv_path_MAGIC_CMD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 echo "${ECHO_T}$MAGIC_CMD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi else MAGIC_CMD=: fi fi fi ;; esac enable_dlopen=no enable_win32_dll=no # Check whether --enable-libtool-lock or --disable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval="$enable_libtool_lock" fi; test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Check whether --with-pic or --without-pic was given. if test "${with_pic+set}" = set; then withval="$with_pic" pic_mode="$withval" else pic_mode=default fi; test -z "$pic_mode" && pic_mode=default # Use C for the default configuration in the libtool script tagname= lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}\n' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:8074: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:8078: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; *) lt_prog_compiler_pic='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic='-qnocommon' lt_prog_compiler_wl='-Wl,' ;; esac ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; linux*) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 echo "${ECHO_T}$lt_prog_compiler_pic" >&6 # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6 if test "${lt_prog_compiler_pic_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:8342: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:8346: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6 if test x"$lt_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 if test "${lt_prog_compiler_static_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_static_works=yes fi else lt_prog_compiler_static_works=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 echo "${ECHO_T}$lt_prog_compiler_static_works" >&6 if test x"$lt_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:8446: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:8450: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6 hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6 if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 runpath_var= allow_undefined_flag= enable_shared_with_static_runtimes=no archive_cmds= archive_expsym_cmds= old_archive_From_new_cmds= old_archive_from_expsyms_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported link_all_deplibs=unknown hardcode_automatic=no module_cmds= module_expsym_cmds= always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; interix3*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_libdir_separator=':' link_all_deplibs=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[012]) allow_undefined_flag='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='' link_all_deplibs=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs=no ;; esac fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu | dragonfly*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld='-rpath $libdir' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) hardcode_direct=yes hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z text' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine linker options so we # cannot just pass the convience library names through # without $wl, iff we do not link with $LD. # Luckily, gcc supports the same syntax we need for Sun Studio. # Supported since Solaris 2.6 (maybe 2.5.1?) case $wlarc in '') whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; *) whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi echo "$as_me:$LINENO: result: $ld_shlibs" >&5 echo "${ECHO_T}$ld_shlibs" >&6 test "$ld_shlibs" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc=no else archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 echo "${ECHO_T}$archive_cmds_need_lc" >&6 ;; esac fi ;; esac echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; freebsd*) # from 4.6 on shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix3*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; knetbsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var" || \ test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi echo "$as_me:$LINENO: result: $hardcode_action" >&5 echo "${ECHO_T}$hardcode_action" >&6 if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi ;; *) echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 ;; esac fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); int main () { dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) echo "$as_me:$LINENO: checking for shl_load" >&5 echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 if test "${ac_cv_func_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define shl_load to an innocuous variant, in case declares shl_load. For example, HP-UX 11i declares gettimeofday. */ #define shl_load innocuous_shl_load /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef shl_load /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shl_load (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_shl_load) || defined (__stub___shl_load) choke me #else char (*f) () = shl_load; #endif #ifdef __cplusplus } #endif int main () { return f != shl_load; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 echo "${ECHO_T}$ac_cv_func_shl_load" >&6 if test $ac_cv_func_shl_load = yes; then lt_cv_dlopen="shl_load" else echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shl_load (); int main () { shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 if test $ac_cv_lib_dld_shl_load = yes; then lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else echo "$as_me:$LINENO: checking for dlopen" >&5 echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 if test "${ac_cv_func_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define dlopen to an innocuous variant, in case declares dlopen. For example, HP-UX 11i declares gettimeofday. */ #define dlopen innocuous_dlopen /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef dlopen /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_dlopen) || defined (__stub___dlopen) choke me #else char (*f) () = dlopen; #endif #ifdef __cplusplus } #endif int main () { return f != dlopen; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 echo "${ECHO_T}$ac_cv_func_dlopen" >&6 if test $ac_cv_func_dlopen = yes; then lt_cv_dlopen="dlopen" else echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); int main () { dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 if test $ac_cv_lib_dl_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 if test "${ac_cv_lib_svld_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen (); int main () { dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_svld_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 if test $ac_cv_lib_svld_dlopen = yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 if test "${ac_cv_lib_dld_dld_link+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dld_link (); int main () { dld_link (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_dld_dld_link=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 if test $ac_cv_lib_dld_dld_link = yes; then lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 if test "${lt_cv_dlopen_self+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); exit (status); } EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 echo "${ECHO_T}$lt_cv_dlopen_self" >&6 if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 if test "${lt_cv_dlopen_self_static+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); exit (status); } EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # Report which library types will actually be built echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $can_build_shared" >&5 echo "${ECHO_T}$can_build_shared" >&6 echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4* | aix5*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac echo "$as_me:$LINENO: result: $enable_shared" >&5 echo "${ECHO_T}$enable_shared" >&6 echo "$as_me:$LINENO: checking whether to build static libraries" >&5 echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes echo "$as_me:$LINENO: result: $enable_static" >&5 echo "${ECHO_T}$enable_static" >&6 # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler \ CC \ LD \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_prog_compiler_no_builtin_flag \ export_dynamic_flag_spec \ thread_safe_flag_spec \ whole_archive_flag_spec \ enable_shared_with_static_runtimes \ old_archive_cmds \ old_archive_from_new_cmds \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ archive_cmds \ archive_expsym_cmds \ postinstall_cmds \ postuninstall_cmds \ old_archive_from_expsyms_cmds \ allow_undefined_flag \ no_undefined_flag \ export_symbols_cmds \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ hardcode_automatic \ module_cmds \ module_expsym_cmds \ lt_cv_prog_compiler_c_o \ exclude_expsyms \ include_expsyms; do case $var in old_archive_cmds | \ old_archive_from_new_cmds | \ archive_cmds | \ archive_expsym_cmds | \ module_cmds | \ module_expsym_cmds | \ old_archive_from_expsyms_cmds | \ export_symbols_cmds | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="${ofile}T" trap "$rm \"$cfgfile\"; exit 1" 1 2 15 $rm -f "$cfgfile" { echo "$as_me:$LINENO: creating $ofile" >&5 echo "$as_me: creating $ofile" >&6;} cat <<__EOF__ >> "$cfgfile" #! $SHELL # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e 1s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # The names of the tagged configurations supported by this script. available_tags= # ### BEGIN LIBTOOL CONFIG # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler # Is the compiler the GNU C compiler? with_gcc=$GCC # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # ### END LIBTOOL CONFIG __EOF__ case $host_os in aix3*) cat <<\EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || \ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" # Check whether --with-tags or --without-tags was given. if test "${with_tags+set}" = set; then withval="$with_tags" tagnames="$withval" fi; if test -f "$ltmain" && test -n "$tagnames"; then if test ! -f "${ofile}"; then { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} fi if test -z "$LTCC"; then eval "`$SHELL ${ofile} --config | grep '^LTCC='`" if test -z "$LTCC"; then { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} else { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} fi fi if test -z "$LTCFLAGS"; then eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for tagname in $tagnames; do IFS="$lt_save_ifs" # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in "") ;; *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 echo "$as_me: error: invalid tag name: $tagname" >&2;} { (exit 1); exit 1; }; } ;; esac if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} { (exit 1); exit 1; }; } fi # Update the list of available tags. if test -n "$tagname"; then echo appending configuration tag \"$tagname\" to $ofile case $tagname in CXX) if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_flag_spec_ld_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC compiler_CXX=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld or --without-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval="$with_gnu_ld" test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi; ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo "$as_me:$LINENO: checking for ld used by $CC" >&5 echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then echo "$as_me:$LINENO: checking for GNU ld" >&5 echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 else echo "$as_me:$LINENO: checking for non-GNU ld" >&5 echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 fi if test "${lt_cv_path_LD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 echo "${ECHO_T}$LD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 if test "${lt_cv_prog_gnu_ld+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes if test "$GXX" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_CXX=yes else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_CXX=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' archive_cmds_need_lc_CXX=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[012]) allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported whole_archive_flag_spec_CXX='' link_all_deplibs_CXX=yes if test "$GXX" = yes ; then lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs_CXX=no ;; esac fi ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd[12]*) # C++ shared libraries reported to be fairly broken before switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; gnu*) ;; hpux9*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld_CXX='+b $libdir' ;; *) export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix3*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: ;; linux*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc*) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC*) # Portland Group C++ compiler archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; openbsd2*) # C++ shared libraries are fairly broken ld_shlibs_CXX=no ;; openbsd*) hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='${wl}-E' whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd='echo' ;; osf3*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ $rm $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The C++ compiler is used as linker so we must use $wl # flag to pass the commands to the underlying system # linker. We must also pass each convience library through # to the system linker between allextract/defaultextract. # The C++ compiler will combine linker options so we # cannot just pass the convience library names through # without $wl. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | grep -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='${wl}-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. # So that behaviour is only enabled if SCOABSPATH is set to a # non-empty value in the environment. Most likely only useful for # creating official distributions of packages. # This is a hack until libtool officially supports absolute path # names for shared libraries. no_undefined_flag_CXX='${wl}-z,text' allow_undefined_flag_CXX='${wl}-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 echo "${ECHO_T}$ld_shlibs_CXX" >&6 test "$ld_shlibs_CXX" = no && can_build_shared=no GCC_CXX="$GXX" LD_CXX="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no # The `*' in the case matches for architectures that use `case' in # $output_verbose_cmd can trigger glob expansion during the loop # eval without this substitution. output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` for p in `eval $output_verbose_link_cmd`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" \ || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX="${prev}${p}" else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX="${prev}${p}" else postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$predep_objects_CXX"; then predep_objects_CXX="$p" else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX="$p" else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $rm -f confest.$objext # PORTME: override above test on systems where it is broken case $host_os in interix3*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; solaris*) case $cc_basename in CC*) # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. postdeps_CXX='-lCstd -lCrun' ;; esac ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix4* | aix5*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic_CXX='-qnocommon' lt_prog_compiler_wl_CXX='-Wl,' ;; esac ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; icpc* | ecpc*) # Intel C++ lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC*) # Portland Group C++ compiler. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6 # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6 if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:13235: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:13239: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works_CXX=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6 if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 if test "${lt_prog_compiler_static_works_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_static_works_CXX=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_static_works_CXX=yes fi else lt_prog_compiler_static_works_CXX=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6 if test x"$lt_prog_compiler_static_works_CXX" = xyes; then : else lt_prog_compiler_static_CXX= fi echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o_CXX=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:13339: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:13343: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6 hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6 if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix4* | aix5*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw*) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 echo "${ECHO_T}$ld_shlibs_CXX" >&6 test "$ld_shlibs_CXX" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_CXX=no else archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6 ;; esac fi ;; esac echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; freebsd*) # from 4.6 on shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix3*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; knetbsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || \ test -n "$runpath_var_CXX" || \ test "X$hardcode_automatic_CXX" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_CXX" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && test "$hardcode_minus_L_CXX" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 echo "${ECHO_T}$hardcode_action_CXX" >&6 if test "$hardcode_action_CXX" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_CXX \ CC_CXX \ LD_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_static_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ export_dynamic_flag_spec_CXX \ thread_safe_flag_spec_CXX \ whole_archive_flag_spec_CXX \ enable_shared_with_static_runtimes_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ postinstall_cmds_CXX \ postuninstall_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ export_symbols_cmds_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_flag_spec_ld_CXX \ hardcode_libdir_separator_CXX \ hardcode_automatic_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ lt_cv_prog_compiler_c_o_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX; do case $var in old_archive_cmds_CXX | \ old_archive_from_new_cmds_CXX | \ archive_cmds_CXX | \ archive_expsym_cmds_CXX | \ module_cmds_CXX | \ module_expsym_cmds_CXX | \ old_archive_from_expsyms_cmds_CXX | \ export_symbols_cmds_CXX | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU C compiler? with_gcc=$GCC_CXX # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_CXX # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_CXX old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_CXX # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_CXX # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_CXX # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_CXX # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_CXX" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ldcxx=$with_gnu_ld with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld else tagname="" fi ;; F77) if test -n "$F77" && test "X$F77" != "Xno"; then ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu archive_cmds_need_lc_F77=no allow_undefined_flag_F77= always_export_symbols_F77=no archive_expsym_cmds_F77= export_dynamic_flag_spec_F77= hardcode_direct_F77=no hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_minus_L_F77=no hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= link_all_deplibs_F77=unknown old_archive_cmds_F77=$old_archive_cmds no_undefined_flag_F77= whole_archive_flag_spec_F77= enable_shared_with_static_runtimes_F77=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o objext_F77=$objext # Code to be used in simple compile tests lt_simple_compile_test_code=" subroutine t\n return\n end\n" # Code to be used in simple link tests lt_simple_link_test_code=" program t\n end\n" # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${F77-"f77"} compiler=$CC compiler_F77=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $can_build_shared" >&5 echo "${ECHO_T}$can_build_shared" >&6 echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4* | aix5*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac echo "$as_me:$LINENO: result: $enable_shared" >&5 echo "${ECHO_T}$enable_shared" >&6 echo "$as_me:$LINENO: checking whether to build static libraries" >&5 echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes echo "$as_me:$LINENO: result: $enable_static" >&5 echo "${ECHO_T}$enable_static" >&6 GCC_F77="$G77" LD_F77="$LD" lt_prog_compiler_wl_F77= lt_prog_compiler_pic_F77= lt_prog_compiler_static_F77= echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 if test "$GCC" = yes; then lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_static_F77='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_F77='-fno-common' ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_F77=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_F77=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_F77='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' else lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic_F77='-qnocommon' lt_prog_compiler_wl_F77='-Wl,' ;; esac ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_F77='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_F77='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_F77='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_F77='-non_shared' ;; newsos6) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; linux*) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-fpic' lt_prog_compiler_static_F77='-Bstatic' ;; ccc*) lt_prog_compiler_wl_F77='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_F77='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; solaris*) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl_F77='-Qoption ld ';; *) lt_prog_compiler_wl_F77='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl_F77='-Qoption ld ' lt_prog_compiler_pic_F77='-PIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_F77='-Kconform_pic' lt_prog_compiler_static_F77='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; unicos*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_can_build_shared_F77=no ;; uts4*) lt_prog_compiler_pic_F77='-pic' lt_prog_compiler_static_F77='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_F77=no ;; esac fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6 # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_F77"; then echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6 if test "${lt_prog_compiler_pic_works_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works_F77=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_F77" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:14909: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:14913: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works_F77=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6 if test x"$lt_prog_compiler_pic_works_F77" = xyes; then case $lt_prog_compiler_pic_F77 in "" | " "*) ;; *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; esac else lt_prog_compiler_pic_F77= lt_prog_compiler_can_build_shared_F77=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_F77= ;; *) lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 if test "${lt_prog_compiler_static_works_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_static_works_F77=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_static_works_F77=yes fi else lt_prog_compiler_static_works_F77=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6 if test x"$lt_prog_compiler_static_works_F77" = xyes; then : else lt_prog_compiler_static_F77= fi echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o_F77=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:15013: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:15017: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_F77=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6 hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6 if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 runpath_var= allow_undefined_flag_F77= enable_shared_with_static_runtimes_F77=no archive_cmds_F77= archive_expsym_cmds_F77= old_archive_From_new_cmds_F77= old_archive_from_expsyms_cmds_F77= export_dynamic_flag_spec_F77= whole_archive_flag_spec_F77= thread_safe_flag_spec_F77= hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_direct_F77=no hardcode_minus_L_F77=no hardcode_shlibpath_var_F77=unsupported link_all_deplibs_F77=unknown hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= always_export_symbols_F77=no export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_F77= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs_F77=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_F77='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_F77= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_F77=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs_F77=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_F77=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_F77=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_F77='-L$libdir' allow_undefined_flag_F77=unsupported always_export_symbols_F77=no enable_shared_with_static_runtimes_F77=yes export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_F77=no fi ;; interix3*) hardcode_direct_F77=no hardcode_shlibpath_var_F77=no hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs_F77=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_F77=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs_F77=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac ;; sunos4*) archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac if test "$ld_shlibs_F77" = no; then runpath_var= hardcode_libdir_flag_spec_F77= export_dynamic_flag_spec_F77= whole_archive_flag_spec_F77= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_F77=unsupported always_export_symbols_F77=yes archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_F77=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_F77=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_F77='' hardcode_direct_F77=yes hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_F77=yes else # We have old collect2 hardcode_direct_F77=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_F77=yes hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_libdir_separator_F77= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_F77=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_F77='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_F77="-z nodefs" archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_F77=' ${wl}-bernotok' allow_undefined_flag_F77=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_F77='$convenience' archive_cmds_need_lc_F77=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes # see comment about different semantics on the GNU ld section ld_shlibs_F77=no ;; bsdi[45]*) export_dynamic_flag_spec_F77=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_F77=' ' allow_undefined_flag_F77=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_F77='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path_F77='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_F77=yes ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[012]) allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac archive_cmds_need_lc_F77=no hardcode_direct_F77=no hardcode_automatic_F77=yes hardcode_shlibpath_var_F77=unsupported whole_archive_flag_spec_F77='' link_all_deplibs_F77=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs_F77=no ;; esac fi ;; dgux*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; freebsd1*) ld_shlibs_F77=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu | dragonfly*) archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes export_dynamic_flag_spec_F77='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld_F77='+b $libdir' hardcode_direct_F77=no hardcode_shlibpath_var_F77=no ;; *) hardcode_direct_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: link_all_deplibs_F77=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; newsos6) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_shlibpath_var_F77=no ;; openbsd*) hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-R$libdir' ;; *) archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes allow_undefined_flag_F77=unsupported archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_F77='-rpath $libdir' fi hardcode_libdir_separator_F77=: ;; solaris*) no_undefined_flag_F77=' -z text' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_shlibpath_var_F77=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine linker options so we # cannot just pass the convience library names through # without $wl, iff we do not link with $LD. # Luckily, gcc supports the same syntax we need for Sun Studio. # Supported since Solaris 2.6 (maybe 2.5.1?) case $wlarc in '') whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; *) whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac ;; esac link_all_deplibs_F77=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; sysv4) case $host_vendor in sni) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_F77='$CC -r -o $output$reload_objs' hardcode_direct_F77=no ;; motorola) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_F77=no ;; sysv4.3*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no export_dynamic_flag_spec_F77='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_F77=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) no_undefined_flag_F77='${wl}-z,text' archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_F77='${wl}-z,text' allow_undefined_flag_F77='${wl}-z,nodefs' archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes export_dynamic_flag_spec_F77='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; *) ld_shlibs_F77=no ;; esac fi echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 echo "${ECHO_T}$ld_shlibs_F77" >&6 test "$ld_shlibs_F77" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_F77" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_F77=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_F77 in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_F77 pic_flag=$lt_prog_compiler_pic_F77 compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_F77 allow_undefined_flag_F77= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_F77=no else archive_cmds_need_lc_F77=yes fi allow_undefined_flag_F77=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6 ;; esac fi ;; esac echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; freebsd*) # from 4.6 on shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix3*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; knetbsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action_F77= if test -n "$hardcode_libdir_flag_spec_F77" || \ test -n "$runpath_var_F77" || \ test "X$hardcode_automatic_F77" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_F77" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && test "$hardcode_minus_L_F77" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_F77=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_F77=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_F77=unsupported fi echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 echo "${ECHO_T}$hardcode_action_F77" >&6 if test "$hardcode_action_F77" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_F77 \ CC_F77 \ LD_F77 \ lt_prog_compiler_wl_F77 \ lt_prog_compiler_pic_F77 \ lt_prog_compiler_static_F77 \ lt_prog_compiler_no_builtin_flag_F77 \ export_dynamic_flag_spec_F77 \ thread_safe_flag_spec_F77 \ whole_archive_flag_spec_F77 \ enable_shared_with_static_runtimes_F77 \ old_archive_cmds_F77 \ old_archive_from_new_cmds_F77 \ predep_objects_F77 \ postdep_objects_F77 \ predeps_F77 \ postdeps_F77 \ compiler_lib_search_path_F77 \ archive_cmds_F77 \ archive_expsym_cmds_F77 \ postinstall_cmds_F77 \ postuninstall_cmds_F77 \ old_archive_from_expsyms_cmds_F77 \ allow_undefined_flag_F77 \ no_undefined_flag_F77 \ export_symbols_cmds_F77 \ hardcode_libdir_flag_spec_F77 \ hardcode_libdir_flag_spec_ld_F77 \ hardcode_libdir_separator_F77 \ hardcode_automatic_F77 \ module_cmds_F77 \ module_expsym_cmds_F77 \ lt_cv_prog_compiler_c_o_F77 \ exclude_expsyms_F77 \ include_expsyms_F77; do case $var in old_archive_cmds_F77 | \ old_archive_from_new_cmds_F77 | \ archive_cmds_F77 | \ archive_expsym_cmds_F77 | \ module_cmds_F77 | \ module_expsym_cmds_F77 | \ old_archive_from_expsyms_cmds_F77 | \ export_symbols_cmds_F77 | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_F77 # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_F77 # Is the compiler the GNU C compiler? with_gcc=$GCC_F77 # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_F77 # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_F77 # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_F77 pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_F77 # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_F77 old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_F77 archive_expsym_cmds=$lt_archive_expsym_cmds_F77 postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_F77 module_expsym_cmds=$lt_module_expsym_cmds_F77 # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_F77 # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_F77 # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_F77 # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_F77 # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_F77 # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_F77 # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_F77 # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_F77 # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_F77 # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_F77 # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_F77 # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_F77 # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_F77" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_F77 # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_F77 # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_F77 # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_F77 # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; GCJ) if test -n "$GCJ" && test "X$GCJ" != "Xno"; then # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o objext_GCJ=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}\n" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${GCJ-"gcj"} compiler=$CC compiler_GCJ=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # GCJ did not exist at the time GCC didn't implicitly link libc in. archive_cmds_need_lc_GCJ=no old_archive_cmds_GCJ=$old_archive_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... lt_prog_compiler_no_builtin_flag_GCJ= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:17220: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:17224: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl_GCJ= lt_prog_compiler_pic_GCJ= lt_prog_compiler_static_GCJ= echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 if test "$GCC" = yes; then lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_static_GCJ='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_GCJ='-fno-common' ;; interix3*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_GCJ=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_GCJ=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_GCJ='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' else lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic_GCJ='-qnocommon' lt_prog_compiler_wl_GCJ='-Wl,' ;; esac ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_GCJ='-non_shared' ;; newsos6) lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; linux*) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-fpic' lt_prog_compiler_static_GCJ='-Bstatic' ;; ccc*) lt_prog_compiler_wl_GCJ='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_GCJ='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; solaris*) lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl_GCJ='-Qoption ld ';; *) lt_prog_compiler_wl_GCJ='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl_GCJ='-Qoption ld ' lt_prog_compiler_pic_GCJ='-PIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_GCJ='-Kconform_pic' lt_prog_compiler_static_GCJ='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; unicos*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_can_build_shared_GCJ=no ;; uts4*) lt_prog_compiler_pic_GCJ='-pic' lt_prog_compiler_static_GCJ='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_GCJ=no ;; esac fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6 # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_GCJ"; then echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6 if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_pic_works_GCJ=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_GCJ" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:17488: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:17492: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works_GCJ=yes fi fi $rm conftest* fi echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6 if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then case $lt_prog_compiler_pic_GCJ in "" | " "*) ;; *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; esac else lt_prog_compiler_pic_GCJ= lt_prog_compiler_can_build_shared_GCJ=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_GCJ= ;; *) lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_prog_compiler_static_works_GCJ=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_static_works_GCJ=yes fi else lt_prog_compiler_static_works_GCJ=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6 if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then : else lt_prog_compiler_static_GCJ= fi echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else lt_cv_prog_compiler_c_o_GCJ=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:17592: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:17596: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_GCJ=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6 hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$as_me:$LINENO: result: $hard_links" >&5 echo "${ECHO_T}$hard_links" >&6 if test "$hard_links" = no; then { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 runpath_var= allow_undefined_flag_GCJ= enable_shared_with_static_runtimes_GCJ=no archive_cmds_GCJ= archive_expsym_cmds_GCJ= old_archive_From_new_cmds_GCJ= old_archive_from_expsyms_cmds_GCJ= export_dynamic_flag_spec_GCJ= whole_archive_flag_spec_GCJ= thread_safe_flag_spec_GCJ= hardcode_libdir_flag_spec_GCJ= hardcode_libdir_flag_spec_ld_GCJ= hardcode_libdir_separator_GCJ= hardcode_direct_GCJ=no hardcode_minus_L_GCJ=no hardcode_shlibpath_var_GCJ=unsupported link_all_deplibs_GCJ=unknown hardcode_automatic_GCJ=no module_cmds_GCJ= module_expsym_cmds_GCJ= always_export_symbols_GCJ=no export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_GCJ= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs_GCJ=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_GCJ= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_GCJ=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs_GCJ=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_GCJ=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_GCJ=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_GCJ='-L$libdir' allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=no enable_shared_with_static_runtimes_GCJ=yes export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_GCJ=no fi ;; interix3*) hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' export_dynamic_flag_spec_GCJ='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs_GCJ=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_GCJ=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs_GCJ=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; esac ;; sunos4*) archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; esac if test "$ld_shlibs_GCJ" = no; then runpath_var= hardcode_libdir_flag_spec_GCJ= export_dynamic_flag_spec_GCJ= whole_archive_flag_spec_GCJ= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=yes archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_GCJ=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_GCJ=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_GCJ='' hardcode_direct_GCJ=yes hardcode_libdir_separator_GCJ=':' link_all_deplibs_GCJ=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_GCJ=yes else # We have old collect2 hardcode_direct_GCJ=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_GCJ=yes hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_libdir_separator_GCJ= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_GCJ=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_GCJ='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_GCJ="-z nodefs" archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_GCJ=' ${wl}-bernotok' allow_undefined_flag_GCJ=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_GCJ='$convenience' archive_cmds_need_lc_GCJ=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes # see comment about different semantics on the GNU ld section ld_shlibs_GCJ=no ;; bsdi[45]*) export_dynamic_flag_spec_GCJ=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_GCJ=' ' allow_undefined_flag_GCJ=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_GCJ='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_GCJ=yes ;; darwin* | rhapsody*) case $host_os in rhapsody* | darwin1.[012]) allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' ;; esac fi ;; esac archive_cmds_need_lc_GCJ=no hardcode_direct_GCJ=no hardcode_automatic_GCJ=yes hardcode_shlibpath_var_GCJ=unsupported whole_archive_flag_spec_GCJ='' link_all_deplibs_GCJ=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs_GCJ=no ;; esac fi ;; dgux*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; freebsd1*) ld_shlibs_GCJ=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu | dragonfly*) archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no ;; *) hardcode_direct_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: link_all_deplibs_GCJ=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; newsos6) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_shlibpath_var_GCJ=no ;; openbsd*) hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' export_dynamic_flag_spec_GCJ='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' ;; *) archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes allow_undefined_flag_GCJ=unsupported archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_GCJ='-rpath $libdir' fi hardcode_libdir_separator_GCJ=: ;; solaris*) no_undefined_flag_GCJ=' -z text' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_shlibpath_var_GCJ=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine linker options so we # cannot just pass the convience library names through # without $wl, iff we do not link with $LD. # Luckily, gcc supports the same syntax we need for Sun Studio. # Supported since Solaris 2.6 (maybe 2.5.1?) case $wlarc in '') whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; *) whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac ;; esac link_all_deplibs_GCJ=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; sysv4) case $host_vendor in sni) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_GCJ='$CC -r -o $output$reload_objs' hardcode_direct_GCJ=no ;; motorola) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_GCJ=no ;; sysv4.3*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no export_dynamic_flag_spec_GCJ='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_GCJ=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) no_undefined_flag_GCJ='${wl}-z,text' archive_cmds_need_lc_GCJ=no hardcode_shlibpath_var_GCJ=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_GCJ='${wl}-z,text' allow_undefined_flag_GCJ='${wl}-z,nodefs' archive_cmds_need_lc_GCJ=no hardcode_shlibpath_var_GCJ=no hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator_GCJ=':' link_all_deplibs_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; *) ld_shlibs_GCJ=no ;; esac fi echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 echo "${ECHO_T}$ld_shlibs_GCJ" >&6 test "$ld_shlibs_GCJ" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_GCJ" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_GCJ=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_GCJ in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_GCJ pic_flag=$lt_prog_compiler_pic_GCJ compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ allow_undefined_flag_GCJ= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_GCJ=no else archive_cmds_need_lc_GCJ=yes fi allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6 ;; esac fi ;; esac echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; freebsd*) # from 4.6 on shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix3*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; knetbsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action_GCJ= if test -n "$hardcode_libdir_flag_spec_GCJ" || \ test -n "$runpath_var_GCJ" || \ test "X$hardcode_automatic_GCJ" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_GCJ" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && test "$hardcode_minus_L_GCJ" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_GCJ=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_GCJ=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_GCJ=unsupported fi echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 echo "${ECHO_T}$hardcode_action_GCJ" >&6 if test "$hardcode_action_GCJ" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_GCJ \ CC_GCJ \ LD_GCJ \ lt_prog_compiler_wl_GCJ \ lt_prog_compiler_pic_GCJ \ lt_prog_compiler_static_GCJ \ lt_prog_compiler_no_builtin_flag_GCJ \ export_dynamic_flag_spec_GCJ \ thread_safe_flag_spec_GCJ \ whole_archive_flag_spec_GCJ \ enable_shared_with_static_runtimes_GCJ \ old_archive_cmds_GCJ \ old_archive_from_new_cmds_GCJ \ predep_objects_GCJ \ postdep_objects_GCJ \ predeps_GCJ \ postdeps_GCJ \ compiler_lib_search_path_GCJ \ archive_cmds_GCJ \ archive_expsym_cmds_GCJ \ postinstall_cmds_GCJ \ postuninstall_cmds_GCJ \ old_archive_from_expsyms_cmds_GCJ \ allow_undefined_flag_GCJ \ no_undefined_flag_GCJ \ export_symbols_cmds_GCJ \ hardcode_libdir_flag_spec_GCJ \ hardcode_libdir_flag_spec_ld_GCJ \ hardcode_libdir_separator_GCJ \ hardcode_automatic_GCJ \ module_cmds_GCJ \ module_expsym_cmds_GCJ \ lt_cv_prog_compiler_c_o_GCJ \ exclude_expsyms_GCJ \ include_expsyms_GCJ; do case $var in old_archive_cmds_GCJ | \ old_archive_from_new_cmds_GCJ | \ archive_cmds_GCJ | \ archive_expsym_cmds_GCJ | \ module_cmds_GCJ | \ module_expsym_cmds_GCJ | \ old_archive_from_expsyms_cmds_GCJ | \ export_symbols_cmds_GCJ | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_GCJ # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_GCJ # Is the compiler the GNU C compiler? with_gcc=$GCC_GCJ # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_GCJ # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_GCJ # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_GCJ pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_GCJ # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_GCJ old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_GCJ archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_GCJ module_expsym_cmds=$lt_module_expsym_cmds_GCJ # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_GCJ # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_GCJ # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_GCJ # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_GCJ # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_GCJ # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_GCJ # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_GCJ # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_GCJ # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_GCJ # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_GCJ # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_GCJ # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_GCJ" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_GCJ # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_GCJ # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_GCJ # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_GCJ # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; RC) # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o objext_RC=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext printf "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${RC-"windres"} compiler=$CC compiler_RC=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` lt_cv_prog_compiler_c_o_RC=yes # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_RC \ CC_RC \ LD_RC \ lt_prog_compiler_wl_RC \ lt_prog_compiler_pic_RC \ lt_prog_compiler_static_RC \ lt_prog_compiler_no_builtin_flag_RC \ export_dynamic_flag_spec_RC \ thread_safe_flag_spec_RC \ whole_archive_flag_spec_RC \ enable_shared_with_static_runtimes_RC \ old_archive_cmds_RC \ old_archive_from_new_cmds_RC \ predep_objects_RC \ postdep_objects_RC \ predeps_RC \ postdeps_RC \ compiler_lib_search_path_RC \ archive_cmds_RC \ archive_expsym_cmds_RC \ postinstall_cmds_RC \ postuninstall_cmds_RC \ old_archive_from_expsyms_cmds_RC \ allow_undefined_flag_RC \ no_undefined_flag_RC \ export_symbols_cmds_RC \ hardcode_libdir_flag_spec_RC \ hardcode_libdir_flag_spec_ld_RC \ hardcode_libdir_separator_RC \ hardcode_automatic_RC \ module_cmds_RC \ module_expsym_cmds_RC \ lt_cv_prog_compiler_c_o_RC \ exclude_expsyms_RC \ include_expsyms_RC; do case $var in old_archive_cmds_RC | \ old_archive_from_new_cmds_RC | \ archive_cmds_RC | \ archive_expsym_cmds_RC | \ module_cmds_RC | \ module_expsym_cmds_RC | \ old_archive_from_expsyms_cmds_RC | \ export_symbols_cmds_RC | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_RC # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_RC # Is the compiler the GNU C compiler? with_gcc=$GCC_RC # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_RC # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_RC # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_RC pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_RC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_RC old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_RC archive_expsym_cmds=$lt_archive_expsym_cmds_RC postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_RC module_expsym_cmds=$lt_module_expsym_cmds_RC # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_RC # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_RC # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_RC # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_RC # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_RC # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_RC # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_RC # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_RC # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_RC # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_RC # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_RC # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_RC # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_RC # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_RC" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_RC # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_RC # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_RC # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_RC # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ;; *) { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 echo "$as_me: error: Unsupported tag name: $tagname" >&2;} { (exit 1); exit 1; }; } ;; esac # Append the new tag name to the list of available tags. if test -n "$tagname" ; then available_tags="$available_tags $tagname" fi fi done IFS="$lt_save_ifs" # Now substitute the updated list of available tags. if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then mv "${ofile}T" "$ofile" chmod +x "$ofile" else rm -f "${ofile}T" { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 echo "$as_me: error: unable to update list of available tagged configurations." >&2;} { (exit 1); exit 1; }; } fi fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' # Prevent multiple expansion # No longer needed now that CPPFLAGS is correctly set -- lh, 061214 -- # AC_REQUIRE([AC_COIN_DLFCN_H]) # NEW: If libtool exists in the directory higher up, we use that one # instead of creating a new one # It turns out that the code for AC_PROG_LIBTOOL is somehow AC_REQUIRED # out in front of this macro body. You'll notice that LIBTOOL is already # defined here. We'll have to count on this macro not being called if libtool # already exists, or at least move the libtool fixes outside the conditional. # AC_MSG_NOTICE([Entering coin_prog_libtool, LIBTOOL = "$LIBTOOL".]) # This test is therefore removed. -- lh, 061214 -- # if test "x$LIBTOOL" = x; then # AC_MSG_NOTICE([Calling PROG_LIBTOOL.]) # AC_MSG_NOTICE([Finished PROG_LIBTOOL.]) { echo "$as_me:$LINENO: Build is \"$build\"." >&5 echo "$as_me: Build is \"$build\"." >&6;} mydos2unix='| dos2unix' case $build in *-mingw*) CYGPATH_W=echo mydos2unix= ;; esac case $build in # Here we need to check if -m32 is specified. If so, we need to correct # sys_lib_search_path_spec *-cygwin* | *-mingw*) case "$CXX" in clang* ) # we assume that libtool patches for CLANG are the same as for GNU compiler - correct??? { echo "$as_me:$LINENO: Applying patches to libtool for CLANG compiler" >&5 echo "$as_me: Applying patches to libtool for CLANG compiler" >&6;} sed -e 's|fix_srcfile_path=\"`cygpath -w \"\$srcfile\"`\"|fix_srcfile_path=\"\\\`'"$CYGPATH_W"' \\\"\\$srcfile\\\"\\\`\"|' \ -e 's|"lib /OUT:\\$oldlib\\$oldobjs\\$old_deplibs"|"\\$AR \\$AR_FLAGS \\$oldlib\\$oldobjs\\$old_deplibs~\\$RANLIB \\$oldlib"|' \ -e 's|libext="lib"|libext="a"|' \ libtool > conftest.bla ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) { echo "$as_me:$LINENO: Applying patches to libtool for cl compiler" >&5 echo "$as_me: Applying patches to libtool for cl compiler" >&6;} sed -e 's|fix_srcfile_path=\"`cygpath -w \"\$srcfile\"`\"|fix_srcfile_path=\"\\\`'"$CYGPATH_W"' \\\"\\$srcfile\\\"\\\`\"|' \ -e 's|fix_srcfile_path=\"\"|fix_srcfile_path=\"\\\`'"$CYGPATH_W"' \\\"\\$srcfile\\\"\\\`\"|' \ -e 's%compile_deplibs=\"\$dir/\$old_library \$compile_deplibs\"%compile_deplibs="'\`"$CYGPATH_W"' \$dir/\$old_library | sed -e '"'"'sY\\\\\\\\Y/Yg'"'"\`' \$compile_deplibs\"'% \ -e 's%compile_deplibs=\"\$dir/\$linklib \$compile_deplibs\"%compile_deplibs="'\`"$CYGPATH_W"' \$dir/\$linklib | sed -e '"'"'sY\\\\\\\\Y/Yg'"'"\`' \$compile_deplibs\"'% \ -e 's%lib /OUT:%lib -OUT:%' \ -e "s%cygpath -w%$CYGPATH_W%" \ -e 's%$AR x \\$f_ex_an_ar_oldlib%bla=\\$(lib -nologo -list \\$('"$CYGPATH_W \$1"') '"$mydos2unix"' | xargs echo); echo \\$bla; for i in \\$bla; do lib -nologo -extract:\\$i \\$('"$CYGPATH_W \$1"'); done%' \ -e 's%$AR t "$f_ex_an_ar_oldlib"%lib -nologo -list \$('"$CYGPATH_W \$1"') '"$mydos2unix"'%' \ -e 's%f_ex_an_ar_oldlib="\($?*1*\)"%f_ex_an_ar_oldlib='\`"$CYGPATH_W"' \1`%' \ -e 's%^archive_cmds=.*%archive_cmds="\\$CC -o \\$lib \\$libobjs \\$compiler_flags \\\\\\`echo \\\\\\"\\$deplibs\\\\\\" | \\$SED -e '"\'"'s/ -lc\\$//'"\'"'\\\\\\` -link -dll~linknames="%' \ -e 's%old_archive_cmds="lib -OUT:\\$oldlib\\$oldobjs\\$old_deplibs"%old_archive_cmds="if test -r \\$oldlib; then bla=\\"\\$oldlib\\"; else bla=; fi; lib -OUT:\\$oldlib \\\\\\$bla\\$oldobjs\\$old_deplibs"%' \ libtool > conftest.bla ;; *) { echo "$as_me:$LINENO: Applying patches to libtool for GNU compiler" >&5 echo "$as_me: Applying patches to libtool for GNU compiler" >&6;} sed -e 's|fix_srcfile_path=\"`cygpath -w \"\$srcfile\"`\"|fix_srcfile_path=\"\\\`'"$CYGPATH_W"' \\\"\\$srcfile\\\"\\\`\"|' \ -e 's|"lib /OUT:\\$oldlib\\$oldobjs\\$old_deplibs"|"\\$AR \\$AR_FLAGS \\$oldlib\\$oldobjs\\$old_deplibs~\\$RANLIB \\$oldlib"|' \ -e 's|libext="lib"|libext="a"|' \ libtool > conftest.bla ;; esac mv conftest.bla libtool chmod 755 libtool ;; *x86_64-*) if test "$GCC" = yes && (echo $CXXFLAGS $CFLAGS $FFLAGS | $EGREP 'm32' >& /dev/null); then { echo "$as_me:$LINENO: Applying patches to libtool for 32bit compilation" >&5 echo "$as_me: Applying patches to libtool for 32bit compilation" >&6;} sed -e 's|sys_lib_search_path_spec=".*"|sys_lib_search_path_spec="/lib /usr/lib"|' libtool > conftest.bla mv conftest.bla libtool chmod 755 libtool fi ;; *-solaris*) if test "$GCC" = yes && \ (echo $CXXFLAGS $CFLAGS $FFLAGS | $EGREP 'm64' >/dev/null 2>&1) ; then hdwisa=`isainfo | sed -e 's/\([^ ]*\) .*$/\1/'` if `$EGREP 'sys_lib_search_path_spec=' libtool | $EGREP -v $hdwisa >/dev/null 2>&1` ; then { echo "$as_me:$LINENO: Applying patches to libtool for 64-bit GCC compilation" >&5 echo "$as_me: Applying patches to libtool for 64-bit GCC compilation" >&6;} fixlibtmp=`$CC -m64 -print-search-dirs | $EGREP '^libraries:'` fixlibtmp=`echo $fixlibtmp | sed -e 's/libraries: =//' -e 's/:/ /g'` if `echo "$fixlibtmp" | $EGREP -v $hdwisa >/dev/null 2>&1` ; then # AC_MSG_NOTICE(Compensating for broken gcc) for lib in $fixlibtmp ; do if test -d "${lib}${hdwisa}" ; then syslibpath64="$syslibpath64 ${lib}${hdwisa}/" fi done syslibpath64="${syslibpath64} ${fixlibtmp}" else syslibpath64="$fixlibtmp" fi sed -e 's|sys_lib_search_path_spec=".*"|sys_lib_search_path_spec="'"$syslibpath64"'"|' libtool > conftest.bla mv conftest.bla libtool chmod 755 libtool fi # AC_MSG_NOTICE(Result is ) # $EGREP 'sys_lib_search_path_spec=' libtool fi ;; # Cygwin. Ah, cygwin. Too big and ugly to inline; see the macro. *-darwin*) { echo "$as_me:$LINENO: Applying patches to libtool for Darwin" >&5 echo "$as_me: Applying patches to libtool for Darwin" >&6;} sed -e 's/verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"/verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"/' \ -e 's/ -dynamiclib / -dynamiclib -single_module /g' \ libtool > conftest.bla mv conftest.bla libtool chmod 755 libtool ;; esac # This fi matches the commented `if test "x$LIBTOOL" = x;' up at the head of # the macro. -- lh, 061214 -- # fi # AC_MSG_NOTICE([End libtool initialisation.]) # AC_MSG_NOTICE([Finished COIN_PROG_LIBTOOL.]) # set RPATH_FLAGS to the compiler link flags required to hardcode location # of the shared objects RPATH_FLAGS= if test $enable_shared = yes; then case $build in *-linux-*) if test "$GXX" = "yes"; then RPATH_FLAGS= for dir in $abs_lib_dir; do RPATH_FLAGS="$RPATH_FLAGS -Wl,--rpath -Wl,$dir" done fi ;; *-darwin*) RPATH_FLAGS=nothing ;; *-ibm-*) case "$CXX" in xlC* | */xlC* | mpxlC* | */mpxlC*) RPATH_FLAGS=nothing ;; esac ;; *-hp-*) RPATH_FLAGS=nothing ;; *-mingw32) RPATH_FLAGS=nothing ;; *-*-solaris*) RPATH_FLAGS= for dir in $abs_lib_dir; do RPATH_FLAGS="$RPATH_FLAGS -R$dir" done esac if test "$RPATH_FLAGS" = ""; then { echo "$as_me:$LINENO: WARNING: Could not automatically determine how to tell the linker about automatic inclusion of the path for shared libraries. The test examples might not work if you link against shared objects. You will need to set the LD_LIBRARY_PATH, DYLP_LIBRARY_PATH, or LIBDIR variable manually." >&5 echo "$as_me: WARNING: Could not automatically determine how to tell the linker about automatic inclusion of the path for shared libraries. The test examples might not work if you link against shared objects. You will need to set the LD_LIBRARY_PATH, DYLP_LIBRARY_PATH, or LIBDIR variable manually." >&2;} fi if test "$RPATH_FLAGS" = "nothing"; then RPATH_FLAGS= fi fi else { echo "$as_me:$LINENO: Using libtool script in directory $coin_config_dir" >&5 echo "$as_me: Using libtool script in directory $coin_config_dir" >&6;} # get all missing information from the config.log file # output variables and defines as_save_IFS=$IFS IFS=' ' for oneline in `cat $coin_config_dir/config.status`; do case "$oneline" in # First some automake conditionals s,@am__fastdep* | s,@AR@* | s,@CPP@* | s,@CPPFLAGS@* | s,@CXXCPP@* | \ s,@RANLIB@* | s,@STRIP@* | s,@ac_ct_AR@* | s,@ac_ct_RANLIB@* | \ s,@ac_ct_STRIP@* | s,@host* | s,@LN_S@* | s,@RPATH_FLAGS@* | \ s,@ac_c_preproc_warn_flag@* | s,@ac_cxx_preproc_warn_flag@* ) command=`echo $oneline | sed -e 's/^s,@//' -e 's/@,/="/' -e 's/,;t t/"/'` # echo "$command" eval "$command" ;; s,@DEFS@* ) command=`echo $oneline | sed -e 's/^s,@DEFS@,/defsline="/' -e 's/,;t t/"/'` # echo "$command" eval "$command" ;; esac done IFS=$as_save_IFS # And some defines (assuming here that the packages base dir # doesn't have a config.h file for word in $defsline; do # echo word $word case $word in -DHAVE_[A-Z_]*_H=1 | -DSTDC_HEADERS=1 ) i=`echo $word | sed -e 's/-D/#define /' -e 's/=/ /'` # echo dd $i echo $i >>confdefs.h ;; esac done fi # AC_MSG_NOTICE([End of INIT_AUTO_TOOLS.]) # Check whether --enable-dependency-linking or --disable-dependency-linking was given. if test "${enable_dependency_linking+set}" = set; then enableval="$enable_dependency_linking" dependency_linking="$enableval" else dependency_linking=no fi; # ToDo # For now, don't use the -no-undefined flag, since the Makefiles are # not yet set up that way. But we need to fix this, when we want # to comile DLLs under Windows. if test "$dependency_linking" = yes ; then LT_LDFLAGS="-no-undefined" else LT_LDFLAGS= fi if test "$dependency_linking" = yes; then DEPENDENCY_LINKING_TRUE= DEPENDENCY_LINKING_FALSE='#' else DEPENDENCY_LINKING_TRUE='#' DEPENDENCY_LINKING_FALSE= fi # Check if we want to set the library version echo "$as_me:$LINENO: checking if library version is set" >&5 echo $ECHO_N "checking if library version is set... $ECHO_C" >&6 if test x"$coin_libversion" != x; then LT_LDFLAGS="$LT_LDFLAGS -version-info $coin_libversion" echo "$as_me:$LINENO: result: $coin_libversion" >&5 echo "${ECHO_T}$coin_libversion" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi #END } ############################################################################# # COIN-OR components # ############################################################################# # Check whether --enable-pkg-config or --disable-pkg-config was given. if test "${enable_pkg_config+set}" = set; then enableval="$enable_pkg_config" use_pkgconfig="$enableval" else if test x$coin_cc_is_cl = xtrue; then use_pkgconfig=no else use_pkgconfig=yes fi fi; if test $use_pkgconfig = yes ; then if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_PKG_CONFIG+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$PKG_CONFIG"; then ac_cv_prog_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PKG_CONFIG="${ac_tool_prefix}pkg-config" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi PKG_CONFIG=$ac_cv_prog_PKG_CONFIG if test -n "$PKG_CONFIG"; then echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 echo "${ECHO_T}$PKG_CONFIG" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_PKG_CONFIG"; then ac_ct_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_PKG_CONFIG+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_PKG_CONFIG"; then ac_cv_prog_ac_ct_PKG_CONFIG="$ac_ct_PKG_CONFIG" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_PKG_CONFIG="pkg-config" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_PKG_CONFIG=$ac_cv_prog_ac_ct_PKG_CONFIG if test -n "$ac_ct_PKG_CONFIG"; then echo "$as_me:$LINENO: result: $ac_ct_PKG_CONFIG" >&5 echo "${ECHO_T}$ac_ct_PKG_CONFIG" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi PKG_CONFIG=$ac_ct_PKG_CONFIG else PKG_CONFIG="$ac_cv_prog_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.16.0 echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5 echo $ECHO_N "checking pkg-config is at least version $_pkg_min_version... $ECHO_C" >&6 if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 PKG_CONFIG="" fi fi # check if pkg-config supports the short-errors flag if test -n "$PKG_CONFIG" && \ $PKG_CONFIG --atleast-pkgconfig-version 0.20; then pkg_short_errors=" --short-errors " else pkg_short_errors="" fi fi if test -n "$PKG_CONFIG"; then COIN_HAS_PKGCONFIG_TRUE= COIN_HAS_PKGCONFIG_FALSE='#' else COIN_HAS_PKGCONFIG_TRUE='#' COIN_HAS_PKGCONFIG_FALSE= fi # assemble pkg-config search path for installed projects COIN_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" # let's assume that when installing into $prefix, then the user may have installed some other coin projects there before, so it's worth to have a look into there # best would actually to use ${libdir}, since .pc files get installed into ${libdir}/pkgconfig, # unfortunately, ${libdir} expands to ${exec_prefix}/lib and ${exec_prefix} to ${prefix}... if test "x${prefix}" = xNONE ; then COIN_PKG_CONFIG_PATH="${ac_default_prefix}/lib64/pkgconfig:${ac_default_prefix}/lib/pkgconfig:${ac_default_prefix}/share/pkgconfig:${COIN_PKG_CONFIG_PATH}" else COIN_PKG_CONFIG_PATH="${prefix}/lib64/pkgconfig:${prefix}/lib/pkgconfig:${prefix}/share/pkgconfig:${COIN_PKG_CONFIG_PATH}" fi # Check whether --with-coin-instdir or --without-coin-instdir was given. if test "${with_coin_instdir+set}" = set; then withval="$with_coin_instdir" if test -d "$withval"; then : ; else { { echo "$as_me:$LINENO: error: argument for --with-coin-instdir not a directory" >&5 echo "$as_me: error: argument for --with-coin-instdir not a directory" >&2;} { (exit 1); exit 1; }; } fi COIN_PKG_CONFIG_PATH="$withval/lib/pkgconfig:$withval/share/pkgconfig:${COIN_PKG_CONFIG_PATH}" fi; # assemble additional pkg-config search paths for uninstalled projects if test x$coin_projectdir = xyes ; then # if we are in a project setup, then in a classic setup, we want to find uninstalled projects # their (relative) location is written to coin_subdirs.txt by the configure in the project base directory # unfortunately, if the user set prefix, then we do not know where the project base directory is located # but it is likely to be either .. (if we are a usual coin project) or ../.. (if we are a unusual coin project like ThirdParty or Data) COIN_PKG_CONFIG_PATH_UNINSTALLED= if test -f ../coin_subdirs.txt ; then for i in `cat ../coin_subdirs.txt` ; do if test -d ../$i ; then COIN_PKG_CONFIG_PATH_UNINSTALLED="`cd ../$i; pwd`:${COIN_PKG_CONFIG_PATH_UNINSTALLED}" fi if test -d ../$i/pkgconfig ; then COIN_PKG_CONFIG_PATH_UNINSTALLED="`cd ../$i/pkgconfig; pwd`:${COIN_PKG_CONFIG_PATH_UNINSTALLED}" fi done fi if test -f ../../coin_subdirs.txt ; then for i in `cat ../../coin_subdirs.txt` ; do if test -d ../../$i ; then COIN_PKG_CONFIG_PATH_UNINSTALLED="`cd ../../$i; pwd`:${COIN_PKG_CONFIG_PATH_UNINSTALLED}" fi if test -d ../../$i/pkgconfig ; then COIN_PKG_CONFIG_PATH_UNINSTALLED="`cd ../../$i/pkgconfig; pwd`:${COIN_PKG_CONFIG_PATH_UNINSTALLED}" fi done fi fi if test -n "$PKG_CONFIG" && test x$coin_cc_is_cl = xtrue; then { echo "$as_me:$LINENO: WARNING: Using pkg-config together with MS or Intel Compiler on Windows is not support by example Makefiles. Consider using --disable-pkg-config." >&5 echo "$as_me: WARNING: Using pkg-config together with MS or Intel Compiler on Windows is not support by example Makefiles. Consider using --disable-pkg-config." >&2;} fi echo "$as_me:$LINENO: checking for COIN-OR package CoinDepend" >&5 echo $ECHO_N "checking for COIN-OR package CoinDepend... $ECHO_C" >&6 coin_has_coindepend=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "CoinDepend"; then coin_has_coindepend=skipping fi done fi if test "$coin_has_coindepend" != skipping; then # Check whether --with-m4_tolower(CoinDepend) or --without-m4_tolower(CoinDepend) was given. if test "${with_coindepend+set}" = set; then withval="$with_coindepend" if test "$withval" = no ; then coin_has_coindepend=skipping fi fi; fi COINDEPEND_LIBS= COINDEPEND_CFLAGS= COINDEPEND_DATA= COINDEPEND_DEPENDENCIES= COINDEPEND_PCLIBS= COINDEPEND_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_coindepend != skipping; then # Check whether --with-m4_tolower(CoinDepend)-lib or --without-m4_tolower(CoinDepend)-lib was given. if test "${with_coindepend_lib+set}" = set; then withval="$with_coindepend_lib" if test "$withval" = no ; then coin_has_coindepend=skipping else coin_has_coindepend=yes COINDEPEND_LIBS="$withval" COINDEPEND_PCLIBS="$withval" CBCLIB_PCLIBS="$withval $CBCLIB_PCLIBS" CBCLIB_LIBS="$withval $CBCLIB_LIBS" CBCGENERIC_PCLIBS="$withval $CBCGENERIC_PCLIBS" CBCGENERIC_LIBS="$withval $CBCGENERIC_LIBS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then COINDEPEND_LIBS_INSTALLED="$withval" CBCLIB_LIBS_INSTALLED="$withval $CBCLIB_LIBS_INSTALLED"CBCGENERIC_LIBS_INSTALLED="$withval $CBCGENERIC_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_coindepend != skipping; then # Check whether --with-m4_tolower(CoinDepend)-incdir or --without-m4_tolower(CoinDepend)-incdir was given. if test "${with_coindepend_incdir+set}" = set; then withval="$with_coindepend_incdir" if test "$withval" = no ; then coin_has_coindepend=skipping else coin_has_coindepend=yes COINDEPEND_CFLAGS="-I`${CYGPATH_W} $withval`" CBCLIB_CFLAGS="-I`${CYGPATH_W} $withval` $CBCLIB_CFLAGS"CBCGENERIC_CFLAGS="-I`${CYGPATH_W} $withval` $CBCGENERIC_CFLAGS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then COINDEPEND_CFLAGS_INSTALLED="$COINDEPEND_CFLAGS" CBCLIB_CFLAGS_INSTALLED="$COINDEPEND_CFLAGS $CBCLIB_CFLAGS_INSTALLED"CBCGENERIC_CFLAGS_INSTALLED="$COINDEPEND_CFLAGS $CBCGENERIC_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_coindepend != skipping; then # Check whether --with-m4_tolower(CoinDepend)-datadir or --without-m4_tolower(CoinDepend)-datadir was given. if test "${with_coindepend_datadir+set}" = set; then withval="$with_coindepend_datadir" if test "$withval" = no ; then coin_has_coindepend=skipping else coin_has_coindepend=yes COINDEPEND_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then COINDEPEND_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_coindepend = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "cgl osi coinutils"; then COINDEPEND_VERSIONS=`$PKG_CONFIG --modversion "cgl osi coinutils" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "cgl osi coinutils" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi COINDEPEND_CFLAGS="$cflags" COINDEPEND_LIBS=`$PKG_CONFIG --libs "cgl osi coinutils" 2>/dev/null` COINDEPEND_DATA=`$PKG_CONFIG --variable=datadir "cgl osi coinutils" 2>/dev/null` coin_has_coindepend=yes echo "$as_me:$LINENO: result: yes: $COINDEPEND_VERSIONS" >&5 echo "${ECHO_T}yes: $COINDEPEND_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then COINDEPEND_LIBS=`echo " $COINDEPEND_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi COINDEPEND_PCREQUIRES="cgl osi coinutils" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in CbcLib CbcGeneric CBCLIB_PCREQUIRES="cgl osi coinutils $CBCLIB_PCREQUIRES" CBCLIB_CFLAGS="$COINDEPEND_CFLAGS $CBCLIB_CFLAGS" CBCLIB_LIBS="$COINDEPEND_LIBS $CBCLIB_LIBS" CBCGENERIC_PCREQUIRES="cgl osi coinutils $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$COINDEPEND_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$COINDEPEND_LIBS $CBCGENERIC_LIBS" else COINDEPEND_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "cgl osi coinutils"` coin_has_coindepend=notGiven echo "$as_me:$LINENO: result: not given: $COINDEPEND_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $COINDEPEND_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module CoinDepend without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module CoinDepend without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package CoinDepend (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package CoinDepend (fallback)... $ECHO_C" >&6 coin_has_coindepend=notGiven COINDEPEND_LIBS= COINDEPEND_LIBS_INSTALLED= COINDEPEND_CFLAGS= COINDEPEND_CFLAGS_INSTALLED= COINDEPEND_DATA= COINDEPEND_DATA_INSTALLED= COINDEPEND_PCLIBS= COINDEPEND_PCREQUIRES= # initial list of dependencies is "cgl osi coinutils", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="cgl osi coinutils" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$COINDEPEND_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` COINDEPEND_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$COINDEPEND_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi COINDEPEND_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi COINDEPEND_CFLAGS="$projcflags $COINDEPEND_CFLAGS" # set LIBS variable COINDEPEND_LIBS="$projlibs $COINDEPEND_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi COINDEPEND_CFLAGS_INSTALLED="$projcflags $COINDEPEND_CFLAGS_INSTALLED" # set LIBS variable COINDEPEND_LIBS_INSTALLED="$projlibs $COINDEPEND_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_coindepend=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_COINDEPEND 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then COINDEPEND_LIBS=`echo " $COINDEPEND_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` COINDEPEND_LIBS_INSTALLED=`echo " $COINDEPEND_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi COINDEPEND_PCREQUIRES="cgl osi coinutils" CBCLIB_PCREQUIRES="cgl osi coinutils $CBCLIB_PCREQUIRES" CBCLIB_CFLAGS="$COINDEPEND_CFLAGS $CBCLIB_CFLAGS" CBCLIB_LIBS="$COINDEPEND_LIBS $CBCLIB_LIBS" CBCLIB_CFLAGS_INSTALLED="$COINDEPEND_CFLAGS_INSTALLED $CBCLIB_CFLAGS_INSTALLED" CBCLIB_LIBS_INSTALLED="$COINDEPEND_LIBS_INSTALLED $CBCLIB_LIBS_INSTALLED" CBCGENERIC_PCREQUIRES="cgl osi coinutils $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$COINDEPEND_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$COINDEPEND_LIBS $CBCGENERIC_LIBS" CBCGENERIC_CFLAGS_INSTALLED="$COINDEPEND_CFLAGS_INSTALLED $CBCGENERIC_CFLAGS_INSTALLED" CBCGENERIC_LIBS_INSTALLED="$COINDEPEND_LIBS_INSTALLED $CBCGENERIC_LIBS_INSTALLED" fi if test $coin_has_coindepend != notGiven && test $coin_has_coindepend != skipping; then COIN_HAS_COINDEPEND_TRUE= COIN_HAS_COINDEPEND_FALSE='#' else COIN_HAS_COINDEPEND_TRUE='#' COIN_HAS_COINDEPEND_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_coindepend" >&5 echo "${ECHO_T}$coin_has_coindepend" >&6 fi if test $coin_has_coindepend != skipping && test $coin_has_coindepend != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_COINDEPEND 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) COINDEPEND_DEPENDENCIES=`echo " $COINDEPEND_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCLIB_DEPENDENCIES=`echo " $CBCLIB_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCGENERIC_DEPENDENCIES=`echo " $CBCGENERIC_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$COINDEPEND_CFLAGS" ; then { echo "$as_me:$LINENO: CoinDepend CFLAGS are $COINDEPEND_CFLAGS" >&5 echo "$as_me: CoinDepend CFLAGS are $COINDEPEND_CFLAGS" >&6;} fi if test -n "$COINDEPEND_LIBS" ; then { echo "$as_me:$LINENO: CoinDepend LIBS are $COINDEPEND_LIBS" >&5 echo "$as_me: CoinDepend LIBS are $COINDEPEND_LIBS" >&6;} fi if test -n "$COINDEPEND_DEPENDENCIES" ; then { echo "$as_me:$LINENO: CoinDepend DEPENDENCIES are $COINDEPEND_DEPENDENCIES" >&5 echo "$as_me: CoinDepend DEPENDENCIES are $COINDEPEND_DEPENDENCIES" >&6;} fi if test -n "$COINDEPEND_DATA" ; then { echo "$as_me:$LINENO: CoinDepend DATA is $COINDEPEND_DATA" >&5 echo "$as_me: CoinDepend DATA is $COINDEPEND_DATA" >&6;} fi if test -n "$COINDEPEND_PCLIBS" ; then { echo "$as_me:$LINENO: CoinDepend PCLIBS are $COINDEPEND_PCLIBS" >&5 echo "$as_me: CoinDepend PCLIBS are $COINDEPEND_PCLIBS" >&6;} fi if test -n "$COINDEPEND_PCREQUIRES" ; then { echo "$as_me:$LINENO: CoinDepend PCREQUIRES are $COINDEPEND_PCREQUIRES" >&5 echo "$as_me: CoinDepend PCREQUIRES are $COINDEPEND_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: CbcLib CFLAGS are $CBCLIB_CFLAGS" >&5 echo "$as_me: CbcLib CFLAGS are $CBCLIB_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcLib LIBS are $CBCLIB_LIBS" >&5 echo "$as_me: CbcLib LIBS are $CBCLIB_LIBS" >&6;} { echo "$as_me:$LINENO: CbcLib DEPENDENCIES are $CBCLIB_DEPENDENCIES" >&5 echo "$as_me: CbcLib DEPENDENCIES are $CBCLIB_DEPENDENCIES" >&6;} { echo "$as_me:$LINENO: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&5 echo "$as_me: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&5 echo "$as_me: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&6;} { echo "$as_me:$LINENO: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&5 echo "$as_me: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_coindepend != notGiven && test $coin_has_coindepend != skipping; then COIN_HAS_COINDEPEND_TRUE= COIN_HAS_COINDEPEND_FALSE='#' else COIN_HAS_COINDEPEND_TRUE='#' COIN_HAS_COINDEPEND_FALSE= fi if test $coin_has_coindepend != yes ; then { { echo "$as_me:$LINENO: error: One or more required packages CoinUtils, Osi, and Cgl are not available." >&5 echo "$as_me: error: One or more required packages CoinUtils, Osi, and Cgl are not available." >&2;} { (exit 1); exit 1; }; } fi # Clp and OsiClp are inseparable here. echo "$as_me:$LINENO: checking for COIN-OR package Clp" >&5 echo $ECHO_N "checking for COIN-OR package Clp... $ECHO_C" >&6 coin_has_clp=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Clp"; then coin_has_clp=skipping fi done fi if test "$coin_has_clp" != skipping; then # Check whether --with-m4_tolower(Clp) or --without-m4_tolower(Clp) was given. if test "${with_clp+set}" = set; then withval="$with_clp" if test "$withval" = no ; then coin_has_clp=skipping fi fi; fi CLP_LIBS= CLP_CFLAGS= CLP_DATA= CLP_DEPENDENCIES= CLP_PCLIBS= CLP_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_clp != skipping; then # Check whether --with-m4_tolower(Clp)-lib or --without-m4_tolower(Clp)-lib was given. if test "${with_clp_lib+set}" = set; then withval="$with_clp_lib" if test "$withval" = no ; then coin_has_clp=skipping else coin_has_clp=yes CLP_LIBS="$withval" CLP_PCLIBS="$withval" CBCLIB_PCLIBS="$withval $CBCLIB_PCLIBS" CBCLIB_LIBS="$withval $CBCLIB_LIBS" CBCGENERIC_PCLIBS="$withval $CBCGENERIC_PCLIBS" CBCGENERIC_LIBS="$withval $CBCGENERIC_LIBS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then CLP_LIBS_INSTALLED="$withval" CBCLIB_LIBS_INSTALLED="$withval $CBCLIB_LIBS_INSTALLED"CBCGENERIC_LIBS_INSTALLED="$withval $CBCGENERIC_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_clp != skipping; then # Check whether --with-m4_tolower(Clp)-incdir or --without-m4_tolower(Clp)-incdir was given. if test "${with_clp_incdir+set}" = set; then withval="$with_clp_incdir" if test "$withval" = no ; then coin_has_clp=skipping else coin_has_clp=yes CLP_CFLAGS="-I`${CYGPATH_W} $withval`" CBCLIB_CFLAGS="-I`${CYGPATH_W} $withval` $CBCLIB_CFLAGS"CBCGENERIC_CFLAGS="-I`${CYGPATH_W} $withval` $CBCGENERIC_CFLAGS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then CLP_CFLAGS_INSTALLED="$CLP_CFLAGS" CBCLIB_CFLAGS_INSTALLED="$CLP_CFLAGS $CBCLIB_CFLAGS_INSTALLED"CBCGENERIC_CFLAGS_INSTALLED="$CLP_CFLAGS $CBCGENERIC_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_clp != skipping; then # Check whether --with-m4_tolower(Clp)-datadir or --without-m4_tolower(Clp)-datadir was given. if test "${with_clp_datadir+set}" = set; then withval="$with_clp_datadir" if test "$withval" = no ; then coin_has_clp=skipping else coin_has_clp=yes CLP_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then CLP_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_clp = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-clp"; then CLP_VERSIONS=`$PKG_CONFIG --modversion "osi-clp" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-clp" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi CLP_CFLAGS="$cflags" CLP_LIBS=`$PKG_CONFIG --libs "osi-clp" 2>/dev/null` CLP_DATA=`$PKG_CONFIG --variable=datadir "osi-clp" 2>/dev/null` coin_has_clp=yes echo "$as_me:$LINENO: result: yes: $CLP_VERSIONS" >&5 echo "${ECHO_T}yes: $CLP_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then CLP_LIBS=`echo " $CLP_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi CLP_PCREQUIRES="osi-clp" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in CbcLib CbcGeneric CBCLIB_PCREQUIRES="osi-clp $CBCLIB_PCREQUIRES" CBCLIB_CFLAGS="$CLP_CFLAGS $CBCLIB_CFLAGS" CBCLIB_LIBS="$CLP_LIBS $CBCLIB_LIBS" CBCGENERIC_PCREQUIRES="osi-clp $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$CLP_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$CLP_LIBS $CBCGENERIC_LIBS" else CLP_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-clp"` coin_has_clp=notGiven echo "$as_me:$LINENO: result: not given: $CLP_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $CLP_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Clp without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Clp without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Clp (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Clp (fallback)... $ECHO_C" >&6 coin_has_clp=notGiven CLP_LIBS= CLP_LIBS_INSTALLED= CLP_CFLAGS= CLP_CFLAGS_INSTALLED= CLP_DATA= CLP_DATA_INSTALLED= CLP_PCLIBS= CLP_PCREQUIRES= # initial list of dependencies is "osi-clp", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-clp" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$CLP_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` CLP_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$CLP_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi CLP_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi CLP_CFLAGS="$projcflags $CLP_CFLAGS" # set LIBS variable CLP_LIBS="$projlibs $CLP_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi CLP_CFLAGS_INSTALLED="$projcflags $CLP_CFLAGS_INSTALLED" # set LIBS variable CLP_LIBS_INSTALLED="$projlibs $CLP_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_clp=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_CLP 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then CLP_LIBS=`echo " $CLP_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` CLP_LIBS_INSTALLED=`echo " $CLP_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi CLP_PCREQUIRES="osi-clp" CBCLIB_PCREQUIRES="osi-clp $CBCLIB_PCREQUIRES" CBCLIB_CFLAGS="$CLP_CFLAGS $CBCLIB_CFLAGS" CBCLIB_LIBS="$CLP_LIBS $CBCLIB_LIBS" CBCLIB_CFLAGS_INSTALLED="$CLP_CFLAGS_INSTALLED $CBCLIB_CFLAGS_INSTALLED" CBCLIB_LIBS_INSTALLED="$CLP_LIBS_INSTALLED $CBCLIB_LIBS_INSTALLED" CBCGENERIC_PCREQUIRES="osi-clp $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$CLP_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$CLP_LIBS $CBCGENERIC_LIBS" CBCGENERIC_CFLAGS_INSTALLED="$CLP_CFLAGS_INSTALLED $CBCGENERIC_CFLAGS_INSTALLED" CBCGENERIC_LIBS_INSTALLED="$CLP_LIBS_INSTALLED $CBCGENERIC_LIBS_INSTALLED" fi if test $coin_has_clp != notGiven && test $coin_has_clp != skipping; then COIN_HAS_CLP_TRUE= COIN_HAS_CLP_FALSE='#' else COIN_HAS_CLP_TRUE='#' COIN_HAS_CLP_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_clp" >&5 echo "${ECHO_T}$coin_has_clp" >&6 fi if test $coin_has_clp != skipping && test $coin_has_clp != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_CLP 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) CLP_DEPENDENCIES=`echo " $CLP_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCLIB_DEPENDENCIES=`echo " $CBCLIB_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCGENERIC_DEPENDENCIES=`echo " $CBCGENERIC_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$CLP_CFLAGS" ; then { echo "$as_me:$LINENO: Clp CFLAGS are $CLP_CFLAGS" >&5 echo "$as_me: Clp CFLAGS are $CLP_CFLAGS" >&6;} fi if test -n "$CLP_LIBS" ; then { echo "$as_me:$LINENO: Clp LIBS are $CLP_LIBS" >&5 echo "$as_me: Clp LIBS are $CLP_LIBS" >&6;} fi if test -n "$CLP_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Clp DEPENDENCIES are $CLP_DEPENDENCIES" >&5 echo "$as_me: Clp DEPENDENCIES are $CLP_DEPENDENCIES" >&6;} fi if test -n "$CLP_DATA" ; then { echo "$as_me:$LINENO: Clp DATA is $CLP_DATA" >&5 echo "$as_me: Clp DATA is $CLP_DATA" >&6;} fi if test -n "$CLP_PCLIBS" ; then { echo "$as_me:$LINENO: Clp PCLIBS are $CLP_PCLIBS" >&5 echo "$as_me: Clp PCLIBS are $CLP_PCLIBS" >&6;} fi if test -n "$CLP_PCREQUIRES" ; then { echo "$as_me:$LINENO: Clp PCREQUIRES are $CLP_PCREQUIRES" >&5 echo "$as_me: Clp PCREQUIRES are $CLP_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: CbcLib CFLAGS are $CBCLIB_CFLAGS" >&5 echo "$as_me: CbcLib CFLAGS are $CBCLIB_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcLib LIBS are $CBCLIB_LIBS" >&5 echo "$as_me: CbcLib LIBS are $CBCLIB_LIBS" >&6;} { echo "$as_me:$LINENO: CbcLib DEPENDENCIES are $CBCLIB_DEPENDENCIES" >&5 echo "$as_me: CbcLib DEPENDENCIES are $CBCLIB_DEPENDENCIES" >&6;} { echo "$as_me:$LINENO: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&5 echo "$as_me: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&5 echo "$as_me: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&6;} { echo "$as_me:$LINENO: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&5 echo "$as_me: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_clp != notGiven && test $coin_has_clp != skipping; then COIN_HAS_CLP_TRUE= COIN_HAS_CLP_FALSE='#' else COIN_HAS_CLP_TRUE='#' COIN_HAS_CLP_FALSE= fi if test $coin_has_clp != yes ; then { { echo "$as_me:$LINENO: error: \"Required package Clp unavailable.\"" >&5 echo "$as_me: error: \"Required package Clp unavailable.\"" >&2;} { (exit 1); exit 1; }; } fi # The rest are not required for linking against Cbc echo "$as_me:$LINENO: checking for COIN-OR package OsiTests" >&5 echo $ECHO_N "checking for COIN-OR package OsiTests... $ECHO_C" >&6 coin_has_ositests=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "OsiTests"; then coin_has_ositests=skipping fi done fi if test "$coin_has_ositests" != skipping; then # Check whether --with-m4_tolower(OsiTests) or --without-m4_tolower(OsiTests) was given. if test "${with_ositests+set}" = set; then withval="$with_ositests" if test "$withval" = no ; then coin_has_ositests=skipping fi fi; fi OSITESTS_LIBS= OSITESTS_CFLAGS= OSITESTS_DATA= OSITESTS_DEPENDENCIES= OSITESTS_PCLIBS= OSITESTS_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_ositests != skipping; then # Check whether --with-m4_tolower(OsiTests)-lib or --without-m4_tolower(OsiTests)-lib was given. if test "${with_ositests_lib+set}" = set; then withval="$with_ositests_lib" if test "$withval" = no ; then coin_has_ositests=skipping else coin_has_ositests=yes OSITESTS_LIBS="$withval" OSITESTS_PCLIBS="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then OSITESTS_LIBS_INSTALLED="$withval" fi fi fi; fi if test $coin_has_ositests != skipping; then # Check whether --with-m4_tolower(OsiTests)-incdir or --without-m4_tolower(OsiTests)-incdir was given. if test "${with_ositests_incdir+set}" = set; then withval="$with_ositests_incdir" if test "$withval" = no ; then coin_has_ositests=skipping else coin_has_ositests=yes OSITESTS_CFLAGS="-I`${CYGPATH_W} $withval`" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then OSITESTS_CFLAGS_INSTALLED="$OSITESTS_CFLAGS" fi fi fi; fi if test $coin_has_ositests != skipping; then # Check whether --with-m4_tolower(OsiTests)-datadir or --without-m4_tolower(OsiTests)-datadir was given. if test "${with_ositests_datadir+set}" = set; then withval="$with_ositests_datadir" if test "$withval" = no ; then coin_has_ositests=skipping else coin_has_ositests=yes OSITESTS_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then OSITESTS_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_ositests = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-unittests"; then OSITESTS_VERSIONS=`$PKG_CONFIG --modversion "osi-unittests" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-unittests" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi OSITESTS_CFLAGS="$cflags" OSITESTS_LIBS=`$PKG_CONFIG --libs "osi-unittests" 2>/dev/null` OSITESTS_DATA=`$PKG_CONFIG --variable=datadir "osi-unittests" 2>/dev/null` coin_has_ositests=yes echo "$as_me:$LINENO: result: yes: $OSITESTS_VERSIONS" >&5 echo "${ECHO_T}yes: $OSITESTS_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then OSITESTS_LIBS=`echo " $OSITESTS_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi OSITESTS_PCREQUIRES="osi-unittests" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in else OSITESTS_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-unittests"` coin_has_ositests=notGiven echo "$as_me:$LINENO: result: not given: $OSITESTS_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $OSITESTS_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module OsiTests without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module OsiTests without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package OsiTests (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package OsiTests (fallback)... $ECHO_C" >&6 coin_has_ositests=notGiven OSITESTS_LIBS= OSITESTS_LIBS_INSTALLED= OSITESTS_CFLAGS= OSITESTS_CFLAGS_INSTALLED= OSITESTS_DATA= OSITESTS_DATA_INSTALLED= OSITESTS_PCLIBS= OSITESTS_PCREQUIRES= # initial list of dependencies is "osi-unittests", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-unittests" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$OSITESTS_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` OSITESTS_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$OSITESTS_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi OSITESTS_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi OSITESTS_CFLAGS="$projcflags $OSITESTS_CFLAGS" # set LIBS variable OSITESTS_LIBS="$projlibs $OSITESTS_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi OSITESTS_CFLAGS_INSTALLED="$projcflags $OSITESTS_CFLAGS_INSTALLED" # set LIBS variable OSITESTS_LIBS_INSTALLED="$projlibs $OSITESTS_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_ositests=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_OSITESTS 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then OSITESTS_LIBS=`echo " $OSITESTS_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` OSITESTS_LIBS_INSTALLED=`echo " $OSITESTS_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi OSITESTS_PCREQUIRES="osi-unittests" fi if test $coin_has_ositests != notGiven && test $coin_has_ositests != skipping; then COIN_HAS_OSITESTS_TRUE= COIN_HAS_OSITESTS_FALSE='#' else COIN_HAS_OSITESTS_TRUE='#' COIN_HAS_OSITESTS_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_ositests" >&5 echo "${ECHO_T}$coin_has_ositests" >&6 fi if test $coin_has_ositests != skipping && test $coin_has_ositests != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_OSITESTS 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) OSITESTS_DEPENDENCIES=`echo " $OSITESTS_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$OSITESTS_CFLAGS" ; then { echo "$as_me:$LINENO: OsiTests CFLAGS are $OSITESTS_CFLAGS" >&5 echo "$as_me: OsiTests CFLAGS are $OSITESTS_CFLAGS" >&6;} fi if test -n "$OSITESTS_LIBS" ; then { echo "$as_me:$LINENO: OsiTests LIBS are $OSITESTS_LIBS" >&5 echo "$as_me: OsiTests LIBS are $OSITESTS_LIBS" >&6;} fi if test -n "$OSITESTS_DEPENDENCIES" ; then { echo "$as_me:$LINENO: OsiTests DEPENDENCIES are $OSITESTS_DEPENDENCIES" >&5 echo "$as_me: OsiTests DEPENDENCIES are $OSITESTS_DEPENDENCIES" >&6;} fi if test -n "$OSITESTS_DATA" ; then { echo "$as_me:$LINENO: OsiTests DATA is $OSITESTS_DATA" >&5 echo "$as_me: OsiTests DATA is $OSITESTS_DATA" >&6;} fi if test -n "$OSITESTS_PCLIBS" ; then { echo "$as_me:$LINENO: OsiTests PCLIBS are $OSITESTS_PCLIBS" >&5 echo "$as_me: OsiTests PCLIBS are $OSITESTS_PCLIBS" >&6;} fi if test -n "$OSITESTS_PCREQUIRES" ; then { echo "$as_me:$LINENO: OsiTests PCREQUIRES are $OSITESTS_PCREQUIRES" >&5 echo "$as_me: OsiTests PCREQUIRES are $OSITESTS_PCREQUIRES" >&6;} fi fi fi # Define the Makefile conditional if test $coin_has_ositests != notGiven && test $coin_has_ositests != skipping; then COIN_HAS_OSITESTS_TRUE= COIN_HAS_OSITESTS_FALSE='#' else COIN_HAS_OSITESTS_TRUE='#' COIN_HAS_OSITESTS_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Sample" >&5 echo $ECHO_N "checking for COIN-OR package Sample... $ECHO_C" >&6 coin_has_sample=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Sample"; then coin_has_sample=skipping fi done fi if test "$coin_has_sample" != skipping; then # Check whether --with-m4_tolower(Sample) or --without-m4_tolower(Sample) was given. if test "${with_sample+set}" = set; then withval="$with_sample" if test "$withval" = no ; then coin_has_sample=skipping fi fi; fi SAMPLE_LIBS= SAMPLE_CFLAGS= SAMPLE_DATA= SAMPLE_DEPENDENCIES= SAMPLE_PCLIBS= SAMPLE_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_sample != skipping; then # Check whether --with-m4_tolower(Sample)-lib or --without-m4_tolower(Sample)-lib was given. if test "${with_sample_lib+set}" = set; then withval="$with_sample_lib" if test "$withval" = no ; then coin_has_sample=skipping else coin_has_sample=yes SAMPLE_LIBS="$withval" SAMPLE_PCLIBS="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then SAMPLE_LIBS_INSTALLED="$withval" fi fi fi; fi if test $coin_has_sample != skipping; then # Check whether --with-m4_tolower(Sample)-incdir or --without-m4_tolower(Sample)-incdir was given. if test "${with_sample_incdir+set}" = set; then withval="$with_sample_incdir" if test "$withval" = no ; then coin_has_sample=skipping else coin_has_sample=yes SAMPLE_CFLAGS="-I`${CYGPATH_W} $withval`" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then SAMPLE_CFLAGS_INSTALLED="$SAMPLE_CFLAGS" fi fi fi; fi if test $coin_has_sample != skipping; then # Check whether --with-m4_tolower(Sample)-datadir or --without-m4_tolower(Sample)-datadir was given. if test "${with_sample_datadir+set}" = set; then withval="$with_sample_datadir" if test "$withval" = no ; then coin_has_sample=skipping else coin_has_sample=yes SAMPLE_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then SAMPLE_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_sample = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "coindatasample"; then SAMPLE_VERSIONS=`$PKG_CONFIG --modversion "coindatasample" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "coindatasample" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi SAMPLE_CFLAGS="$cflags" SAMPLE_LIBS=`$PKG_CONFIG --libs "coindatasample" 2>/dev/null` SAMPLE_DATA=`$PKG_CONFIG --variable=datadir "coindatasample" 2>/dev/null` coin_has_sample=yes echo "$as_me:$LINENO: result: yes: $SAMPLE_VERSIONS" >&5 echo "${ECHO_T}yes: $SAMPLE_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then SAMPLE_LIBS=`echo " $SAMPLE_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi SAMPLE_PCREQUIRES="coindatasample" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in else SAMPLE_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "coindatasample"` coin_has_sample=notGiven echo "$as_me:$LINENO: result: not given: $SAMPLE_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $SAMPLE_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Sample without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Sample without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Sample (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Sample (fallback)... $ECHO_C" >&6 coin_has_sample=notGiven SAMPLE_LIBS= SAMPLE_LIBS_INSTALLED= SAMPLE_CFLAGS= SAMPLE_CFLAGS_INSTALLED= SAMPLE_DATA= SAMPLE_DATA_INSTALLED= SAMPLE_PCLIBS= SAMPLE_PCREQUIRES= # initial list of dependencies is "coindatasample", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="coindatasample" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$SAMPLE_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` SAMPLE_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$SAMPLE_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi SAMPLE_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi SAMPLE_CFLAGS="$projcflags $SAMPLE_CFLAGS" # set LIBS variable SAMPLE_LIBS="$projlibs $SAMPLE_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi SAMPLE_CFLAGS_INSTALLED="$projcflags $SAMPLE_CFLAGS_INSTALLED" # set LIBS variable SAMPLE_LIBS_INSTALLED="$projlibs $SAMPLE_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_sample=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_SAMPLE 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then SAMPLE_LIBS=`echo " $SAMPLE_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` SAMPLE_LIBS_INSTALLED=`echo " $SAMPLE_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi SAMPLE_PCREQUIRES="coindatasample" fi if test $coin_has_sample != notGiven && test $coin_has_sample != skipping; then COIN_HAS_SAMPLE_TRUE= COIN_HAS_SAMPLE_FALSE='#' else COIN_HAS_SAMPLE_TRUE='#' COIN_HAS_SAMPLE_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_sample" >&5 echo "${ECHO_T}$coin_has_sample" >&6 fi if test $coin_has_sample != skipping && test $coin_has_sample != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_SAMPLE 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) SAMPLE_DEPENDENCIES=`echo " $SAMPLE_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$SAMPLE_CFLAGS" ; then { echo "$as_me:$LINENO: Sample CFLAGS are $SAMPLE_CFLAGS" >&5 echo "$as_me: Sample CFLAGS are $SAMPLE_CFLAGS" >&6;} fi if test -n "$SAMPLE_LIBS" ; then { echo "$as_me:$LINENO: Sample LIBS are $SAMPLE_LIBS" >&5 echo "$as_me: Sample LIBS are $SAMPLE_LIBS" >&6;} fi if test -n "$SAMPLE_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Sample DEPENDENCIES are $SAMPLE_DEPENDENCIES" >&5 echo "$as_me: Sample DEPENDENCIES are $SAMPLE_DEPENDENCIES" >&6;} fi if test -n "$SAMPLE_DATA" ; then { echo "$as_me:$LINENO: Sample DATA is $SAMPLE_DATA" >&5 echo "$as_me: Sample DATA is $SAMPLE_DATA" >&6;} fi if test -n "$SAMPLE_PCLIBS" ; then { echo "$as_me:$LINENO: Sample PCLIBS are $SAMPLE_PCLIBS" >&5 echo "$as_me: Sample PCLIBS are $SAMPLE_PCLIBS" >&6;} fi if test -n "$SAMPLE_PCREQUIRES" ; then { echo "$as_me:$LINENO: Sample PCREQUIRES are $SAMPLE_PCREQUIRES" >&5 echo "$as_me: Sample PCREQUIRES are $SAMPLE_PCREQUIRES" >&6;} fi fi fi # Define the Makefile conditional if test $coin_has_sample != notGiven && test $coin_has_sample != skipping; then COIN_HAS_SAMPLE_TRUE= COIN_HAS_SAMPLE_FALSE='#' else COIN_HAS_SAMPLE_TRUE='#' COIN_HAS_SAMPLE_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Netlib" >&5 echo $ECHO_N "checking for COIN-OR package Netlib... $ECHO_C" >&6 coin_has_netlib=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Netlib"; then coin_has_netlib=skipping fi done fi if test "$coin_has_netlib" != skipping; then # Check whether --with-m4_tolower(Netlib) or --without-m4_tolower(Netlib) was given. if test "${with_netlib+set}" = set; then withval="$with_netlib" if test "$withval" = no ; then coin_has_netlib=skipping fi fi; fi NETLIB_LIBS= NETLIB_CFLAGS= NETLIB_DATA= NETLIB_DEPENDENCIES= NETLIB_PCLIBS= NETLIB_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_netlib != skipping; then # Check whether --with-m4_tolower(Netlib)-lib or --without-m4_tolower(Netlib)-lib was given. if test "${with_netlib_lib+set}" = set; then withval="$with_netlib_lib" if test "$withval" = no ; then coin_has_netlib=skipping else coin_has_netlib=yes NETLIB_LIBS="$withval" NETLIB_PCLIBS="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then NETLIB_LIBS_INSTALLED="$withval" fi fi fi; fi if test $coin_has_netlib != skipping; then # Check whether --with-m4_tolower(Netlib)-incdir or --without-m4_tolower(Netlib)-incdir was given. if test "${with_netlib_incdir+set}" = set; then withval="$with_netlib_incdir" if test "$withval" = no ; then coin_has_netlib=skipping else coin_has_netlib=yes NETLIB_CFLAGS="-I`${CYGPATH_W} $withval`" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then NETLIB_CFLAGS_INSTALLED="$NETLIB_CFLAGS" fi fi fi; fi if test $coin_has_netlib != skipping; then # Check whether --with-m4_tolower(Netlib)-datadir or --without-m4_tolower(Netlib)-datadir was given. if test "${with_netlib_datadir+set}" = set; then withval="$with_netlib_datadir" if test "$withval" = no ; then coin_has_netlib=skipping else coin_has_netlib=yes NETLIB_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then NETLIB_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_netlib = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "coindatanetlib"; then NETLIB_VERSIONS=`$PKG_CONFIG --modversion "coindatanetlib" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "coindatanetlib" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi NETLIB_CFLAGS="$cflags" NETLIB_LIBS=`$PKG_CONFIG --libs "coindatanetlib" 2>/dev/null` NETLIB_DATA=`$PKG_CONFIG --variable=datadir "coindatanetlib" 2>/dev/null` coin_has_netlib=yes echo "$as_me:$LINENO: result: yes: $NETLIB_VERSIONS" >&5 echo "${ECHO_T}yes: $NETLIB_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then NETLIB_LIBS=`echo " $NETLIB_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi NETLIB_PCREQUIRES="coindatanetlib" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in else NETLIB_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "coindatanetlib"` coin_has_netlib=notGiven echo "$as_me:$LINENO: result: not given: $NETLIB_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $NETLIB_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Netlib without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Netlib without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Netlib (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Netlib (fallback)... $ECHO_C" >&6 coin_has_netlib=notGiven NETLIB_LIBS= NETLIB_LIBS_INSTALLED= NETLIB_CFLAGS= NETLIB_CFLAGS_INSTALLED= NETLIB_DATA= NETLIB_DATA_INSTALLED= NETLIB_PCLIBS= NETLIB_PCREQUIRES= # initial list of dependencies is "coindatanetlib", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="coindatanetlib" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$NETLIB_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` NETLIB_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$NETLIB_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi NETLIB_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi NETLIB_CFLAGS="$projcflags $NETLIB_CFLAGS" # set LIBS variable NETLIB_LIBS="$projlibs $NETLIB_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi NETLIB_CFLAGS_INSTALLED="$projcflags $NETLIB_CFLAGS_INSTALLED" # set LIBS variable NETLIB_LIBS_INSTALLED="$projlibs $NETLIB_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_netlib=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_NETLIB 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then NETLIB_LIBS=`echo " $NETLIB_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` NETLIB_LIBS_INSTALLED=`echo " $NETLIB_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi NETLIB_PCREQUIRES="coindatanetlib" fi if test $coin_has_netlib != notGiven && test $coin_has_netlib != skipping; then COIN_HAS_NETLIB_TRUE= COIN_HAS_NETLIB_FALSE='#' else COIN_HAS_NETLIB_TRUE='#' COIN_HAS_NETLIB_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_netlib" >&5 echo "${ECHO_T}$coin_has_netlib" >&6 fi if test $coin_has_netlib != skipping && test $coin_has_netlib != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_NETLIB 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) NETLIB_DEPENDENCIES=`echo " $NETLIB_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$NETLIB_CFLAGS" ; then { echo "$as_me:$LINENO: Netlib CFLAGS are $NETLIB_CFLAGS" >&5 echo "$as_me: Netlib CFLAGS are $NETLIB_CFLAGS" >&6;} fi if test -n "$NETLIB_LIBS" ; then { echo "$as_me:$LINENO: Netlib LIBS are $NETLIB_LIBS" >&5 echo "$as_me: Netlib LIBS are $NETLIB_LIBS" >&6;} fi if test -n "$NETLIB_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Netlib DEPENDENCIES are $NETLIB_DEPENDENCIES" >&5 echo "$as_me: Netlib DEPENDENCIES are $NETLIB_DEPENDENCIES" >&6;} fi if test -n "$NETLIB_DATA" ; then { echo "$as_me:$LINENO: Netlib DATA is $NETLIB_DATA" >&5 echo "$as_me: Netlib DATA is $NETLIB_DATA" >&6;} fi if test -n "$NETLIB_PCLIBS" ; then { echo "$as_me:$LINENO: Netlib PCLIBS are $NETLIB_PCLIBS" >&5 echo "$as_me: Netlib PCLIBS are $NETLIB_PCLIBS" >&6;} fi if test -n "$NETLIB_PCREQUIRES" ; then { echo "$as_me:$LINENO: Netlib PCREQUIRES are $NETLIB_PCREQUIRES" >&5 echo "$as_me: Netlib PCREQUIRES are $NETLIB_PCREQUIRES" >&6;} fi fi fi # Define the Makefile conditional if test $coin_has_netlib != notGiven && test $coin_has_netlib != skipping; then COIN_HAS_NETLIB_TRUE= COIN_HAS_NETLIB_FALSE='#' else COIN_HAS_NETLIB_TRUE='#' COIN_HAS_NETLIB_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Miplib3" >&5 echo $ECHO_N "checking for COIN-OR package Miplib3... $ECHO_C" >&6 coin_has_miplib3=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Miplib3"; then coin_has_miplib3=skipping fi done fi if test "$coin_has_miplib3" != skipping; then # Check whether --with-m4_tolower(Miplib3) or --without-m4_tolower(Miplib3) was given. if test "${with_miplib3+set}" = set; then withval="$with_miplib3" if test "$withval" = no ; then coin_has_miplib3=skipping fi fi; fi MIPLIB3_LIBS= MIPLIB3_CFLAGS= MIPLIB3_DATA= MIPLIB3_DEPENDENCIES= MIPLIB3_PCLIBS= MIPLIB3_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_miplib3 != skipping; then # Check whether --with-m4_tolower(Miplib3)-lib or --without-m4_tolower(Miplib3)-lib was given. if test "${with_miplib3_lib+set}" = set; then withval="$with_miplib3_lib" if test "$withval" = no ; then coin_has_miplib3=skipping else coin_has_miplib3=yes MIPLIB3_LIBS="$withval" MIPLIB3_PCLIBS="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then MIPLIB3_LIBS_INSTALLED="$withval" fi fi fi; fi if test $coin_has_miplib3 != skipping; then # Check whether --with-m4_tolower(Miplib3)-incdir or --without-m4_tolower(Miplib3)-incdir was given. if test "${with_miplib3_incdir+set}" = set; then withval="$with_miplib3_incdir" if test "$withval" = no ; then coin_has_miplib3=skipping else coin_has_miplib3=yes MIPLIB3_CFLAGS="-I`${CYGPATH_W} $withval`" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then MIPLIB3_CFLAGS_INSTALLED="$MIPLIB3_CFLAGS" fi fi fi; fi if test $coin_has_miplib3 != skipping; then # Check whether --with-m4_tolower(Miplib3)-datadir or --without-m4_tolower(Miplib3)-datadir was given. if test "${with_miplib3_datadir+set}" = set; then withval="$with_miplib3_datadir" if test "$withval" = no ; then coin_has_miplib3=skipping else coin_has_miplib3=yes MIPLIB3_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then MIPLIB3_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_miplib3 = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "coindatamiplib3"; then MIPLIB3_VERSIONS=`$PKG_CONFIG --modversion "coindatamiplib3" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "coindatamiplib3" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi MIPLIB3_CFLAGS="$cflags" MIPLIB3_LIBS=`$PKG_CONFIG --libs "coindatamiplib3" 2>/dev/null` MIPLIB3_DATA=`$PKG_CONFIG --variable=datadir "coindatamiplib3" 2>/dev/null` coin_has_miplib3=yes echo "$as_me:$LINENO: result: yes: $MIPLIB3_VERSIONS" >&5 echo "${ECHO_T}yes: $MIPLIB3_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then MIPLIB3_LIBS=`echo " $MIPLIB3_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi MIPLIB3_PCREQUIRES="coindatamiplib3" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in else MIPLIB3_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "coindatamiplib3"` coin_has_miplib3=notGiven echo "$as_me:$LINENO: result: not given: $MIPLIB3_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $MIPLIB3_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Miplib3 without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Miplib3 without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Miplib3 (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Miplib3 (fallback)... $ECHO_C" >&6 coin_has_miplib3=notGiven MIPLIB3_LIBS= MIPLIB3_LIBS_INSTALLED= MIPLIB3_CFLAGS= MIPLIB3_CFLAGS_INSTALLED= MIPLIB3_DATA= MIPLIB3_DATA_INSTALLED= MIPLIB3_PCLIBS= MIPLIB3_PCREQUIRES= # initial list of dependencies is "coindatamiplib3", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="coindatamiplib3" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$MIPLIB3_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` MIPLIB3_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$MIPLIB3_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi MIPLIB3_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi MIPLIB3_CFLAGS="$projcflags $MIPLIB3_CFLAGS" # set LIBS variable MIPLIB3_LIBS="$projlibs $MIPLIB3_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi MIPLIB3_CFLAGS_INSTALLED="$projcflags $MIPLIB3_CFLAGS_INSTALLED" # set LIBS variable MIPLIB3_LIBS_INSTALLED="$projlibs $MIPLIB3_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_miplib3=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_MIPLIB3 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then MIPLIB3_LIBS=`echo " $MIPLIB3_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` MIPLIB3_LIBS_INSTALLED=`echo " $MIPLIB3_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi MIPLIB3_PCREQUIRES="coindatamiplib3" fi if test $coin_has_miplib3 != notGiven && test $coin_has_miplib3 != skipping; then COIN_HAS_MIPLIB3_TRUE= COIN_HAS_MIPLIB3_FALSE='#' else COIN_HAS_MIPLIB3_TRUE='#' COIN_HAS_MIPLIB3_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_miplib3" >&5 echo "${ECHO_T}$coin_has_miplib3" >&6 fi if test $coin_has_miplib3 != skipping && test $coin_has_miplib3 != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_MIPLIB3 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) MIPLIB3_DEPENDENCIES=`echo " $MIPLIB3_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$MIPLIB3_CFLAGS" ; then { echo "$as_me:$LINENO: Miplib3 CFLAGS are $MIPLIB3_CFLAGS" >&5 echo "$as_me: Miplib3 CFLAGS are $MIPLIB3_CFLAGS" >&6;} fi if test -n "$MIPLIB3_LIBS" ; then { echo "$as_me:$LINENO: Miplib3 LIBS are $MIPLIB3_LIBS" >&5 echo "$as_me: Miplib3 LIBS are $MIPLIB3_LIBS" >&6;} fi if test -n "$MIPLIB3_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Miplib3 DEPENDENCIES are $MIPLIB3_DEPENDENCIES" >&5 echo "$as_me: Miplib3 DEPENDENCIES are $MIPLIB3_DEPENDENCIES" >&6;} fi if test -n "$MIPLIB3_DATA" ; then { echo "$as_me:$LINENO: Miplib3 DATA is $MIPLIB3_DATA" >&5 echo "$as_me: Miplib3 DATA is $MIPLIB3_DATA" >&6;} fi if test -n "$MIPLIB3_PCLIBS" ; then { echo "$as_me:$LINENO: Miplib3 PCLIBS are $MIPLIB3_PCLIBS" >&5 echo "$as_me: Miplib3 PCLIBS are $MIPLIB3_PCLIBS" >&6;} fi if test -n "$MIPLIB3_PCREQUIRES" ; then { echo "$as_me:$LINENO: Miplib3 PCREQUIRES are $MIPLIB3_PCREQUIRES" >&5 echo "$as_me: Miplib3 PCREQUIRES are $MIPLIB3_PCREQUIRES" >&6;} fi fi fi # Define the Makefile conditional if test $coin_has_miplib3 != notGiven && test $coin_has_miplib3 != skipping; then COIN_HAS_MIPLIB3_TRUE= COIN_HAS_MIPLIB3_FALSE='#' else COIN_HAS_MIPLIB3_TRUE='#' COIN_HAS_MIPLIB3_FALSE= fi # Cbc really should make these tests; right now it assumes far too much about # its environment. Needed for cbc-generic. ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu #if test x"" = x; then # hdr="#include " #else # hdr="" #fi #AC_CHECK_HEADERS([cmath],[],[],[$hdr]) for ac_header in cmath do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to cbc@lists.coin-or.org ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_cmath" != "yes"; then #if test x"" = x; then # hdr="#include " #else # hdr="" #fi #AC_CHECK_HEADERS([math.h],[],[],[$hdr]) for ac_header in math.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to cbc@lists.coin-or.org ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu #if test x"" = x; then # hdr="#include " #else # hdr="" #fi #AC_CHECK_HEADERS([cfloat],[],[],[$hdr]) for ac_header in cfloat do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to cbc@lists.coin-or.org ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_cfloat" != "yes"; then #if test x"" = x; then # hdr="#include " #else # hdr="" #fi #AC_CHECK_HEADERS([float.h],[],[],[$hdr]) for ac_header in float.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to cbc@lists.coin-or.org ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu #if test x"" = x; then # hdr="#include " #else # hdr="" #fi #AC_CHECK_HEADERS([cieeefp],[],[],[$hdr]) for ac_header in cieeefp do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to cbc@lists.coin-or.org ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_cieeefp" != "yes"; then #if test x"" = x; then # hdr="#include " #else # hdr="" #fi #AC_CHECK_HEADERS([ieeefp.h],[],[],[$hdr]) for ac_header in ieeefp.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_cxx_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------ ## ## Report this to cbc@lists.coin-or.org ## ## ------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Check whether --enable-gnu-packages or --disable-gnu-packages was given. if test "${enable_gnu_packages+set}" = set; then enableval="$enable_gnu_packages" coin_enable_gnu=$enableval else coin_enable_gnu=no fi; coin_has_readline=no if test $coin_enable_gnu = yes; then #if test x"#include " = x; then # hdr="#include " #else # hdr="#include " #fi #AC_CHECK_HEADERS([readline/readline.h],[coin_has_readline=yes],[],[$hdr]) for ac_header in readline/readline.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF coin_has_readline=yes fi done coin_save_LIBS="$LIBS" LIBS= # First we check if tputs and friends are available if test $coin_has_readline = yes; then echo "$as_me:$LINENO: checking for library containing tputs" >&5 echo $ECHO_N "checking for library containing tputs... $ECHO_C" >&6 if test "${ac_cv_search_tputs+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_tputs=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char tputs (); int main () { tputs (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_tputs="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_tputs" = no; then for ac_lib in ncurses termcap curses; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char tputs (); int main () { tputs (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_tputs="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_tputs" >&5 echo "${ECHO_T}$ac_cv_search_tputs" >&6 if test "$ac_cv_search_tputs" != no; then test "$ac_cv_search_tputs" = "none required" || LIBS="$ac_cv_search_tputs $LIBS" else coin_has_readline=no fi fi # Now we check for readline if test $coin_has_readline = yes; then echo "$as_me:$LINENO: checking for readline in -lreadline" >&5 echo $ECHO_N "checking for readline in -lreadline... $ECHO_C" >&6 if test "${ac_cv_lib_readline_readline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char readline (); int main () { readline (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_readline_readline=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_readline_readline=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_readline_readline" >&5 echo "${ECHO_T}$ac_cv_lib_readline_readline" >&6 if test $ac_cv_lib_readline_readline = yes; then : else coin_has_readline=no fi fi if test $coin_has_readline = yes; then CBCLIB_LIBS="-lreadline $LIBS $CBCLIB_LIBS" CBCLIB_PCLIBS="-lreadline $LIBS $CBCLIB_PCLIBS" CBCLIB_LIBS_INSTALLED="-lreadline $LIBS $CBCLIB_LIBS_INSTALLED" CBCGENERIC_LIBS="-lreadline $LIBS $CBCGENERIC_LIBS" CBCGENERIC_PCLIBS="-lreadline $LIBS $CBCGENERIC_PCLIBS" CBCGENERIC_LIBS_INSTALLED="-lreadline $LIBS $CBCGENERIC_LIBS_INSTALLED" cat >>confdefs.h <<\_ACEOF #define COIN_HAS_READLINE 1 _ACEOF fi LIBS="$coin_save_LIBS" fi ############################################################################# # LP solvers other than CLP # ############################################################################# # Check which other LP solvers are available, some of them become a dependency of CbcGeneric echo "$as_me:$LINENO: checking for COIN-OR package DyLP" >&5 echo $ECHO_N "checking for COIN-OR package DyLP... $ECHO_C" >&6 coin_has_dylp=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "DyLP"; then coin_has_dylp=skipping fi done fi if test "$coin_has_dylp" != skipping; then # Check whether --with-m4_tolower(DyLP) or --without-m4_tolower(DyLP) was given. if test "${with_dylp+set}" = set; then withval="$with_dylp" if test "$withval" = no ; then coin_has_dylp=skipping fi fi; fi DYLP_LIBS= DYLP_CFLAGS= DYLP_DATA= DYLP_DEPENDENCIES= DYLP_PCLIBS= DYLP_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_dylp != skipping; then # Check whether --with-m4_tolower(DyLP)-lib or --without-m4_tolower(DyLP)-lib was given. if test "${with_dylp_lib+set}" = set; then withval="$with_dylp_lib" if test "$withval" = no ; then coin_has_dylp=skipping else coin_has_dylp=yes DYLP_LIBS="$withval" DYLP_PCLIBS="$withval" CBCGENERIC_PCLIBS="$withval $CBCGENERIC_PCLIBS" CBCGENERIC_LIBS="$withval $CBCGENERIC_LIBS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then DYLP_LIBS_INSTALLED="$withval" CBCGENERIC_LIBS_INSTALLED="$withval $CBCGENERIC_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_dylp != skipping; then # Check whether --with-m4_tolower(DyLP)-incdir or --without-m4_tolower(DyLP)-incdir was given. if test "${with_dylp_incdir+set}" = set; then withval="$with_dylp_incdir" if test "$withval" = no ; then coin_has_dylp=skipping else coin_has_dylp=yes DYLP_CFLAGS="-I`${CYGPATH_W} $withval`" CBCGENERIC_CFLAGS="-I`${CYGPATH_W} $withval` $CBCGENERIC_CFLAGS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then DYLP_CFLAGS_INSTALLED="$DYLP_CFLAGS" CBCGENERIC_CFLAGS_INSTALLED="$DYLP_CFLAGS $CBCGENERIC_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_dylp != skipping; then # Check whether --with-m4_tolower(DyLP)-datadir or --without-m4_tolower(DyLP)-datadir was given. if test "${with_dylp_datadir+set}" = set; then withval="$with_dylp_datadir" if test "$withval" = no ; then coin_has_dylp=skipping else coin_has_dylp=yes DYLP_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then DYLP_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_dylp = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-dylp"; then DYLP_VERSIONS=`$PKG_CONFIG --modversion "osi-dylp" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-dylp" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi DYLP_CFLAGS="$cflags" DYLP_LIBS=`$PKG_CONFIG --libs "osi-dylp" 2>/dev/null` DYLP_DATA=`$PKG_CONFIG --variable=datadir "osi-dylp" 2>/dev/null` coin_has_dylp=yes echo "$as_me:$LINENO: result: yes: $DYLP_VERSIONS" >&5 echo "${ECHO_T}yes: $DYLP_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then DYLP_LIBS=`echo " $DYLP_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi DYLP_PCREQUIRES="osi-dylp" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in CbcGeneric CBCGENERIC_PCREQUIRES="osi-dylp $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$DYLP_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$DYLP_LIBS $CBCGENERIC_LIBS" else DYLP_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-dylp"` coin_has_dylp=notGiven echo "$as_me:$LINENO: result: not given: $DYLP_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $DYLP_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module DyLP without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module DyLP without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package DyLP (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package DyLP (fallback)... $ECHO_C" >&6 coin_has_dylp=notGiven DYLP_LIBS= DYLP_LIBS_INSTALLED= DYLP_CFLAGS= DYLP_CFLAGS_INSTALLED= DYLP_DATA= DYLP_DATA_INSTALLED= DYLP_PCLIBS= DYLP_PCREQUIRES= # initial list of dependencies is "osi-dylp", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-dylp" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$DYLP_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` DYLP_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$DYLP_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi DYLP_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi DYLP_CFLAGS="$projcflags $DYLP_CFLAGS" # set LIBS variable DYLP_LIBS="$projlibs $DYLP_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi DYLP_CFLAGS_INSTALLED="$projcflags $DYLP_CFLAGS_INSTALLED" # set LIBS variable DYLP_LIBS_INSTALLED="$projlibs $DYLP_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_dylp=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_DYLP 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then DYLP_LIBS=`echo " $DYLP_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` DYLP_LIBS_INSTALLED=`echo " $DYLP_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi DYLP_PCREQUIRES="osi-dylp" CBCGENERIC_PCREQUIRES="osi-dylp $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$DYLP_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$DYLP_LIBS $CBCGENERIC_LIBS" CBCGENERIC_CFLAGS_INSTALLED="$DYLP_CFLAGS_INSTALLED $CBCGENERIC_CFLAGS_INSTALLED" CBCGENERIC_LIBS_INSTALLED="$DYLP_LIBS_INSTALLED $CBCGENERIC_LIBS_INSTALLED" fi if test $coin_has_dylp != notGiven && test $coin_has_dylp != skipping; then COIN_HAS_DYLP_TRUE= COIN_HAS_DYLP_FALSE='#' else COIN_HAS_DYLP_TRUE='#' COIN_HAS_DYLP_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_dylp" >&5 echo "${ECHO_T}$coin_has_dylp" >&6 fi if test $coin_has_dylp != skipping && test $coin_has_dylp != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_DYLP 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) DYLP_DEPENDENCIES=`echo " $DYLP_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCGENERIC_DEPENDENCIES=`echo " $CBCGENERIC_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$DYLP_CFLAGS" ; then { echo "$as_me:$LINENO: DyLP CFLAGS are $DYLP_CFLAGS" >&5 echo "$as_me: DyLP CFLAGS are $DYLP_CFLAGS" >&6;} fi if test -n "$DYLP_LIBS" ; then { echo "$as_me:$LINENO: DyLP LIBS are $DYLP_LIBS" >&5 echo "$as_me: DyLP LIBS are $DYLP_LIBS" >&6;} fi if test -n "$DYLP_DEPENDENCIES" ; then { echo "$as_me:$LINENO: DyLP DEPENDENCIES are $DYLP_DEPENDENCIES" >&5 echo "$as_me: DyLP DEPENDENCIES are $DYLP_DEPENDENCIES" >&6;} fi if test -n "$DYLP_DATA" ; then { echo "$as_me:$LINENO: DyLP DATA is $DYLP_DATA" >&5 echo "$as_me: DyLP DATA is $DYLP_DATA" >&6;} fi if test -n "$DYLP_PCLIBS" ; then { echo "$as_me:$LINENO: DyLP PCLIBS are $DYLP_PCLIBS" >&5 echo "$as_me: DyLP PCLIBS are $DYLP_PCLIBS" >&6;} fi if test -n "$DYLP_PCREQUIRES" ; then { echo "$as_me:$LINENO: DyLP PCREQUIRES are $DYLP_PCREQUIRES" >&5 echo "$as_me: DyLP PCREQUIRES are $DYLP_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&5 echo "$as_me: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&5 echo "$as_me: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&6;} { echo "$as_me:$LINENO: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&5 echo "$as_me: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_dylp != notGiven && test $coin_has_dylp != skipping; then COIN_HAS_DYLP_TRUE= COIN_HAS_DYLP_FALSE='#' else COIN_HAS_DYLP_TRUE='#' COIN_HAS_DYLP_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Vol" >&5 echo $ECHO_N "checking for COIN-OR package Vol... $ECHO_C" >&6 coin_has_vol=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Vol"; then coin_has_vol=skipping fi done fi if test "$coin_has_vol" != skipping; then # Check whether --with-m4_tolower(Vol) or --without-m4_tolower(Vol) was given. if test "${with_vol+set}" = set; then withval="$with_vol" if test "$withval" = no ; then coin_has_vol=skipping fi fi; fi VOL_LIBS= VOL_CFLAGS= VOL_DATA= VOL_DEPENDENCIES= VOL_PCLIBS= VOL_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_vol != skipping; then # Check whether --with-m4_tolower(Vol)-lib or --without-m4_tolower(Vol)-lib was given. if test "${with_vol_lib+set}" = set; then withval="$with_vol_lib" if test "$withval" = no ; then coin_has_vol=skipping else coin_has_vol=yes VOL_LIBS="$withval" VOL_PCLIBS="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then VOL_LIBS_INSTALLED="$withval" fi fi fi; fi if test $coin_has_vol != skipping; then # Check whether --with-m4_tolower(Vol)-incdir or --without-m4_tolower(Vol)-incdir was given. if test "${with_vol_incdir+set}" = set; then withval="$with_vol_incdir" if test "$withval" = no ; then coin_has_vol=skipping else coin_has_vol=yes VOL_CFLAGS="-I`${CYGPATH_W} $withval`" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then VOL_CFLAGS_INSTALLED="$VOL_CFLAGS" fi fi fi; fi if test $coin_has_vol != skipping; then # Check whether --with-m4_tolower(Vol)-datadir or --without-m4_tolower(Vol)-datadir was given. if test "${with_vol_datadir+set}" = set; then withval="$with_vol_datadir" if test "$withval" = no ; then coin_has_vol=skipping else coin_has_vol=yes VOL_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then VOL_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_vol = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-vol"; then VOL_VERSIONS=`$PKG_CONFIG --modversion "osi-vol" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-vol" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi VOL_CFLAGS="$cflags" VOL_LIBS=`$PKG_CONFIG --libs "osi-vol" 2>/dev/null` VOL_DATA=`$PKG_CONFIG --variable=datadir "osi-vol" 2>/dev/null` coin_has_vol=yes echo "$as_me:$LINENO: result: yes: $VOL_VERSIONS" >&5 echo "${ECHO_T}yes: $VOL_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then VOL_LIBS=`echo " $VOL_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi VOL_PCREQUIRES="osi-vol" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in else VOL_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-vol"` coin_has_vol=notGiven echo "$as_me:$LINENO: result: not given: $VOL_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $VOL_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Vol without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Vol without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Vol (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Vol (fallback)... $ECHO_C" >&6 coin_has_vol=notGiven VOL_LIBS= VOL_LIBS_INSTALLED= VOL_CFLAGS= VOL_CFLAGS_INSTALLED= VOL_DATA= VOL_DATA_INSTALLED= VOL_PCLIBS= VOL_PCREQUIRES= # initial list of dependencies is "osi-vol", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-vol" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$VOL_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` VOL_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$VOL_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi VOL_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi VOL_CFLAGS="$projcflags $VOL_CFLAGS" # set LIBS variable VOL_LIBS="$projlibs $VOL_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi VOL_CFLAGS_INSTALLED="$projcflags $VOL_CFLAGS_INSTALLED" # set LIBS variable VOL_LIBS_INSTALLED="$projlibs $VOL_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_vol=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_VOL 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then VOL_LIBS=`echo " $VOL_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` VOL_LIBS_INSTALLED=`echo " $VOL_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi VOL_PCREQUIRES="osi-vol" fi if test $coin_has_vol != notGiven && test $coin_has_vol != skipping; then COIN_HAS_VOL_TRUE= COIN_HAS_VOL_FALSE='#' else COIN_HAS_VOL_TRUE='#' COIN_HAS_VOL_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_vol" >&5 echo "${ECHO_T}$coin_has_vol" >&6 fi if test $coin_has_vol != skipping && test $coin_has_vol != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_VOL 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) VOL_DEPENDENCIES=`echo " $VOL_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$VOL_CFLAGS" ; then { echo "$as_me:$LINENO: Vol CFLAGS are $VOL_CFLAGS" >&5 echo "$as_me: Vol CFLAGS are $VOL_CFLAGS" >&6;} fi if test -n "$VOL_LIBS" ; then { echo "$as_me:$LINENO: Vol LIBS are $VOL_LIBS" >&5 echo "$as_me: Vol LIBS are $VOL_LIBS" >&6;} fi if test -n "$VOL_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Vol DEPENDENCIES are $VOL_DEPENDENCIES" >&5 echo "$as_me: Vol DEPENDENCIES are $VOL_DEPENDENCIES" >&6;} fi if test -n "$VOL_DATA" ; then { echo "$as_me:$LINENO: Vol DATA is $VOL_DATA" >&5 echo "$as_me: Vol DATA is $VOL_DATA" >&6;} fi if test -n "$VOL_PCLIBS" ; then { echo "$as_me:$LINENO: Vol PCLIBS are $VOL_PCLIBS" >&5 echo "$as_me: Vol PCLIBS are $VOL_PCLIBS" >&6;} fi if test -n "$VOL_PCREQUIRES" ; then { echo "$as_me:$LINENO: Vol PCREQUIRES are $VOL_PCREQUIRES" >&5 echo "$as_me: Vol PCREQUIRES are $VOL_PCREQUIRES" >&6;} fi fi fi # Define the Makefile conditional if test $coin_has_vol != notGiven && test $coin_has_vol != skipping; then COIN_HAS_VOL_TRUE= COIN_HAS_VOL_FALSE='#' else COIN_HAS_VOL_TRUE='#' COIN_HAS_VOL_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Cpx" >&5 echo $ECHO_N "checking for COIN-OR package Cpx... $ECHO_C" >&6 coin_has_cpx=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Cpx"; then coin_has_cpx=skipping fi done fi if test "$coin_has_cpx" != skipping; then # Check whether --with-m4_tolower(Cpx) or --without-m4_tolower(Cpx) was given. if test "${with_cpx+set}" = set; then withval="$with_cpx" if test "$withval" = no ; then coin_has_cpx=skipping fi fi; fi CPX_LIBS= CPX_CFLAGS= CPX_DATA= CPX_DEPENDENCIES= CPX_PCLIBS= CPX_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_cpx != skipping; then # Check whether --with-m4_tolower(Cpx)-lib or --without-m4_tolower(Cpx)-lib was given. if test "${with_cpx_lib+set}" = set; then withval="$with_cpx_lib" if test "$withval" = no ; then coin_has_cpx=skipping else coin_has_cpx=yes CPX_LIBS="$withval" CPX_PCLIBS="$withval" CBCLIB_PCLIBS="$withval $CBCLIB_PCLIBS" CBCLIB_LIBS="$withval $CBCLIB_LIBS" CBCGENERIC_PCLIBS="$withval $CBCGENERIC_PCLIBS" CBCGENERIC_LIBS="$withval $CBCGENERIC_LIBS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then CPX_LIBS_INSTALLED="$withval" CBCLIB_LIBS_INSTALLED="$withval $CBCLIB_LIBS_INSTALLED"CBCGENERIC_LIBS_INSTALLED="$withval $CBCGENERIC_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_cpx != skipping; then # Check whether --with-m4_tolower(Cpx)-incdir or --without-m4_tolower(Cpx)-incdir was given. if test "${with_cpx_incdir+set}" = set; then withval="$with_cpx_incdir" if test "$withval" = no ; then coin_has_cpx=skipping else coin_has_cpx=yes CPX_CFLAGS="-I`${CYGPATH_W} $withval`" CBCLIB_CFLAGS="-I`${CYGPATH_W} $withval` $CBCLIB_CFLAGS"CBCGENERIC_CFLAGS="-I`${CYGPATH_W} $withval` $CBCGENERIC_CFLAGS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then CPX_CFLAGS_INSTALLED="$CPX_CFLAGS" CBCLIB_CFLAGS_INSTALLED="$CPX_CFLAGS $CBCLIB_CFLAGS_INSTALLED"CBCGENERIC_CFLAGS_INSTALLED="$CPX_CFLAGS $CBCGENERIC_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_cpx != skipping; then # Check whether --with-m4_tolower(Cpx)-datadir or --without-m4_tolower(Cpx)-datadir was given. if test "${with_cpx_datadir+set}" = set; then withval="$with_cpx_datadir" if test "$withval" = no ; then coin_has_cpx=skipping else coin_has_cpx=yes CPX_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then CPX_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_cpx = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-cplex"; then CPX_VERSIONS=`$PKG_CONFIG --modversion "osi-cplex" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-cplex" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi CPX_CFLAGS="$cflags" CPX_LIBS=`$PKG_CONFIG --libs "osi-cplex" 2>/dev/null` CPX_DATA=`$PKG_CONFIG --variable=datadir "osi-cplex" 2>/dev/null` coin_has_cpx=yes echo "$as_me:$LINENO: result: yes: $CPX_VERSIONS" >&5 echo "${ECHO_T}yes: $CPX_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then CPX_LIBS=`echo " $CPX_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi CPX_PCREQUIRES="osi-cplex" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in CbcLib CbcGeneric CBCLIB_PCREQUIRES="osi-cplex $CBCLIB_PCREQUIRES" CBCLIB_CFLAGS="$CPX_CFLAGS $CBCLIB_CFLAGS" CBCLIB_LIBS="$CPX_LIBS $CBCLIB_LIBS" CBCGENERIC_PCREQUIRES="osi-cplex $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$CPX_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$CPX_LIBS $CBCGENERIC_LIBS" else CPX_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-cplex"` coin_has_cpx=notGiven echo "$as_me:$LINENO: result: not given: $CPX_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $CPX_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Cpx without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Cpx without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Cpx (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Cpx (fallback)... $ECHO_C" >&6 coin_has_cpx=notGiven CPX_LIBS= CPX_LIBS_INSTALLED= CPX_CFLAGS= CPX_CFLAGS_INSTALLED= CPX_DATA= CPX_DATA_INSTALLED= CPX_PCLIBS= CPX_PCREQUIRES= # initial list of dependencies is "osi-cplex", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-cplex" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$CPX_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` CPX_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$CPX_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi CPX_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi CPX_CFLAGS="$projcflags $CPX_CFLAGS" # set LIBS variable CPX_LIBS="$projlibs $CPX_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi CPX_CFLAGS_INSTALLED="$projcflags $CPX_CFLAGS_INSTALLED" # set LIBS variable CPX_LIBS_INSTALLED="$projlibs $CPX_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_cpx=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_CPX 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then CPX_LIBS=`echo " $CPX_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` CPX_LIBS_INSTALLED=`echo " $CPX_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi CPX_PCREQUIRES="osi-cplex" CBCLIB_PCREQUIRES="osi-cplex $CBCLIB_PCREQUIRES" CBCLIB_CFLAGS="$CPX_CFLAGS $CBCLIB_CFLAGS" CBCLIB_LIBS="$CPX_LIBS $CBCLIB_LIBS" CBCLIB_CFLAGS_INSTALLED="$CPX_CFLAGS_INSTALLED $CBCLIB_CFLAGS_INSTALLED" CBCLIB_LIBS_INSTALLED="$CPX_LIBS_INSTALLED $CBCLIB_LIBS_INSTALLED" CBCGENERIC_PCREQUIRES="osi-cplex $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$CPX_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$CPX_LIBS $CBCGENERIC_LIBS" CBCGENERIC_CFLAGS_INSTALLED="$CPX_CFLAGS_INSTALLED $CBCGENERIC_CFLAGS_INSTALLED" CBCGENERIC_LIBS_INSTALLED="$CPX_LIBS_INSTALLED $CBCGENERIC_LIBS_INSTALLED" fi if test $coin_has_cpx != notGiven && test $coin_has_cpx != skipping; then COIN_HAS_CPX_TRUE= COIN_HAS_CPX_FALSE='#' else COIN_HAS_CPX_TRUE='#' COIN_HAS_CPX_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_cpx" >&5 echo "${ECHO_T}$coin_has_cpx" >&6 fi if test $coin_has_cpx != skipping && test $coin_has_cpx != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_CPX 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) CPX_DEPENDENCIES=`echo " $CPX_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCLIB_DEPENDENCIES=`echo " $CBCLIB_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCGENERIC_DEPENDENCIES=`echo " $CBCGENERIC_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$CPX_CFLAGS" ; then { echo "$as_me:$LINENO: Cpx CFLAGS are $CPX_CFLAGS" >&5 echo "$as_me: Cpx CFLAGS are $CPX_CFLAGS" >&6;} fi if test -n "$CPX_LIBS" ; then { echo "$as_me:$LINENO: Cpx LIBS are $CPX_LIBS" >&5 echo "$as_me: Cpx LIBS are $CPX_LIBS" >&6;} fi if test -n "$CPX_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Cpx DEPENDENCIES are $CPX_DEPENDENCIES" >&5 echo "$as_me: Cpx DEPENDENCIES are $CPX_DEPENDENCIES" >&6;} fi if test -n "$CPX_DATA" ; then { echo "$as_me:$LINENO: Cpx DATA is $CPX_DATA" >&5 echo "$as_me: Cpx DATA is $CPX_DATA" >&6;} fi if test -n "$CPX_PCLIBS" ; then { echo "$as_me:$LINENO: Cpx PCLIBS are $CPX_PCLIBS" >&5 echo "$as_me: Cpx PCLIBS are $CPX_PCLIBS" >&6;} fi if test -n "$CPX_PCREQUIRES" ; then { echo "$as_me:$LINENO: Cpx PCREQUIRES are $CPX_PCREQUIRES" >&5 echo "$as_me: Cpx PCREQUIRES are $CPX_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: CbcLib CFLAGS are $CBCLIB_CFLAGS" >&5 echo "$as_me: CbcLib CFLAGS are $CBCLIB_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcLib LIBS are $CBCLIB_LIBS" >&5 echo "$as_me: CbcLib LIBS are $CBCLIB_LIBS" >&6;} { echo "$as_me:$LINENO: CbcLib DEPENDENCIES are $CBCLIB_DEPENDENCIES" >&5 echo "$as_me: CbcLib DEPENDENCIES are $CBCLIB_DEPENDENCIES" >&6;} { echo "$as_me:$LINENO: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&5 echo "$as_me: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&5 echo "$as_me: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&6;} { echo "$as_me:$LINENO: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&5 echo "$as_me: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_cpx != notGiven && test $coin_has_cpx != skipping; then COIN_HAS_CPX_TRUE= COIN_HAS_CPX_FALSE='#' else COIN_HAS_CPX_TRUE='#' COIN_HAS_CPX_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Glpk" >&5 echo $ECHO_N "checking for COIN-OR package Glpk... $ECHO_C" >&6 coin_has_glpk=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Glpk"; then coin_has_glpk=skipping fi done fi if test "$coin_has_glpk" != skipping; then # Check whether --with-m4_tolower(Glpk) or --without-m4_tolower(Glpk) was given. if test "${with_glpk+set}" = set; then withval="$with_glpk" if test "$withval" = no ; then coin_has_glpk=skipping fi fi; fi GLPK_LIBS= GLPK_CFLAGS= GLPK_DATA= GLPK_DEPENDENCIES= GLPK_PCLIBS= GLPK_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_glpk != skipping; then # Check whether --with-m4_tolower(Glpk)-lib or --without-m4_tolower(Glpk)-lib was given. if test "${with_glpk_lib+set}" = set; then withval="$with_glpk_lib" if test "$withval" = no ; then coin_has_glpk=skipping else coin_has_glpk=yes GLPK_LIBS="$withval" GLPK_PCLIBS="$withval" CBCGENERIC_PCLIBS="$withval $CBCGENERIC_PCLIBS" CBCGENERIC_LIBS="$withval $CBCGENERIC_LIBS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then GLPK_LIBS_INSTALLED="$withval" CBCGENERIC_LIBS_INSTALLED="$withval $CBCGENERIC_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_glpk != skipping; then # Check whether --with-m4_tolower(Glpk)-incdir or --without-m4_tolower(Glpk)-incdir was given. if test "${with_glpk_incdir+set}" = set; then withval="$with_glpk_incdir" if test "$withval" = no ; then coin_has_glpk=skipping else coin_has_glpk=yes GLPK_CFLAGS="-I`${CYGPATH_W} $withval`" CBCGENERIC_CFLAGS="-I`${CYGPATH_W} $withval` $CBCGENERIC_CFLAGS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then GLPK_CFLAGS_INSTALLED="$GLPK_CFLAGS" CBCGENERIC_CFLAGS_INSTALLED="$GLPK_CFLAGS $CBCGENERIC_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_glpk != skipping; then # Check whether --with-m4_tolower(Glpk)-datadir or --without-m4_tolower(Glpk)-datadir was given. if test "${with_glpk_datadir+set}" = set; then withval="$with_glpk_datadir" if test "$withval" = no ; then coin_has_glpk=skipping else coin_has_glpk=yes GLPK_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then GLPK_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_glpk = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-glpk"; then GLPK_VERSIONS=`$PKG_CONFIG --modversion "osi-glpk" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-glpk" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi GLPK_CFLAGS="$cflags" GLPK_LIBS=`$PKG_CONFIG --libs "osi-glpk" 2>/dev/null` GLPK_DATA=`$PKG_CONFIG --variable=datadir "osi-glpk" 2>/dev/null` coin_has_glpk=yes echo "$as_me:$LINENO: result: yes: $GLPK_VERSIONS" >&5 echo "${ECHO_T}yes: $GLPK_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then GLPK_LIBS=`echo " $GLPK_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi GLPK_PCREQUIRES="osi-glpk" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in CbcGeneric CBCGENERIC_PCREQUIRES="osi-glpk $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$GLPK_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$GLPK_LIBS $CBCGENERIC_LIBS" else GLPK_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-glpk"` coin_has_glpk=notGiven echo "$as_me:$LINENO: result: not given: $GLPK_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $GLPK_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Glpk without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Glpk without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Glpk (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Glpk (fallback)... $ECHO_C" >&6 coin_has_glpk=notGiven GLPK_LIBS= GLPK_LIBS_INSTALLED= GLPK_CFLAGS= GLPK_CFLAGS_INSTALLED= GLPK_DATA= GLPK_DATA_INSTALLED= GLPK_PCLIBS= GLPK_PCREQUIRES= # initial list of dependencies is "osi-glpk", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-glpk" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$GLPK_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` GLPK_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$GLPK_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi GLPK_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi GLPK_CFLAGS="$projcflags $GLPK_CFLAGS" # set LIBS variable GLPK_LIBS="$projlibs $GLPK_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi GLPK_CFLAGS_INSTALLED="$projcflags $GLPK_CFLAGS_INSTALLED" # set LIBS variable GLPK_LIBS_INSTALLED="$projlibs $GLPK_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_glpk=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_GLPK 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then GLPK_LIBS=`echo " $GLPK_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` GLPK_LIBS_INSTALLED=`echo " $GLPK_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi GLPK_PCREQUIRES="osi-glpk" CBCGENERIC_PCREQUIRES="osi-glpk $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$GLPK_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$GLPK_LIBS $CBCGENERIC_LIBS" CBCGENERIC_CFLAGS_INSTALLED="$GLPK_CFLAGS_INSTALLED $CBCGENERIC_CFLAGS_INSTALLED" CBCGENERIC_LIBS_INSTALLED="$GLPK_LIBS_INSTALLED $CBCGENERIC_LIBS_INSTALLED" fi if test $coin_has_glpk != notGiven && test $coin_has_glpk != skipping; then COIN_HAS_GLPK_TRUE= COIN_HAS_GLPK_FALSE='#' else COIN_HAS_GLPK_TRUE='#' COIN_HAS_GLPK_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_glpk" >&5 echo "${ECHO_T}$coin_has_glpk" >&6 fi if test $coin_has_glpk != skipping && test $coin_has_glpk != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_GLPK 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) GLPK_DEPENDENCIES=`echo " $GLPK_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCGENERIC_DEPENDENCIES=`echo " $CBCGENERIC_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$GLPK_CFLAGS" ; then { echo "$as_me:$LINENO: Glpk CFLAGS are $GLPK_CFLAGS" >&5 echo "$as_me: Glpk CFLAGS are $GLPK_CFLAGS" >&6;} fi if test -n "$GLPK_LIBS" ; then { echo "$as_me:$LINENO: Glpk LIBS are $GLPK_LIBS" >&5 echo "$as_me: Glpk LIBS are $GLPK_LIBS" >&6;} fi if test -n "$GLPK_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Glpk DEPENDENCIES are $GLPK_DEPENDENCIES" >&5 echo "$as_me: Glpk DEPENDENCIES are $GLPK_DEPENDENCIES" >&6;} fi if test -n "$GLPK_DATA" ; then { echo "$as_me:$LINENO: Glpk DATA is $GLPK_DATA" >&5 echo "$as_me: Glpk DATA is $GLPK_DATA" >&6;} fi if test -n "$GLPK_PCLIBS" ; then { echo "$as_me:$LINENO: Glpk PCLIBS are $GLPK_PCLIBS" >&5 echo "$as_me: Glpk PCLIBS are $GLPK_PCLIBS" >&6;} fi if test -n "$GLPK_PCREQUIRES" ; then { echo "$as_me:$LINENO: Glpk PCREQUIRES are $GLPK_PCREQUIRES" >&5 echo "$as_me: Glpk PCREQUIRES are $GLPK_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&5 echo "$as_me: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&5 echo "$as_me: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&6;} { echo "$as_me:$LINENO: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&5 echo "$as_me: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_glpk != notGiven && test $coin_has_glpk != skipping; then COIN_HAS_GLPK_TRUE= COIN_HAS_GLPK_FALSE='#' else COIN_HAS_GLPK_TRUE='#' COIN_HAS_GLPK_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Grb" >&5 echo $ECHO_N "checking for COIN-OR package Grb... $ECHO_C" >&6 coin_has_grb=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Grb"; then coin_has_grb=skipping fi done fi if test "$coin_has_grb" != skipping; then # Check whether --with-m4_tolower(Grb) or --without-m4_tolower(Grb) was given. if test "${with_grb+set}" = set; then withval="$with_grb" if test "$withval" = no ; then coin_has_grb=skipping fi fi; fi GRB_LIBS= GRB_CFLAGS= GRB_DATA= GRB_DEPENDENCIES= GRB_PCLIBS= GRB_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_grb != skipping; then # Check whether --with-m4_tolower(Grb)-lib or --without-m4_tolower(Grb)-lib was given. if test "${with_grb_lib+set}" = set; then withval="$with_grb_lib" if test "$withval" = no ; then coin_has_grb=skipping else coin_has_grb=yes GRB_LIBS="$withval" GRB_PCLIBS="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then GRB_LIBS_INSTALLED="$withval" fi fi fi; fi if test $coin_has_grb != skipping; then # Check whether --with-m4_tolower(Grb)-incdir or --without-m4_tolower(Grb)-incdir was given. if test "${with_grb_incdir+set}" = set; then withval="$with_grb_incdir" if test "$withval" = no ; then coin_has_grb=skipping else coin_has_grb=yes GRB_CFLAGS="-I`${CYGPATH_W} $withval`" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then GRB_CFLAGS_INSTALLED="$GRB_CFLAGS" fi fi fi; fi if test $coin_has_grb != skipping; then # Check whether --with-m4_tolower(Grb)-datadir or --without-m4_tolower(Grb)-datadir was given. if test "${with_grb_datadir+set}" = set; then withval="$with_grb_datadir" if test "$withval" = no ; then coin_has_grb=skipping else coin_has_grb=yes GRB_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then GRB_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_grb = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-gurobi"; then GRB_VERSIONS=`$PKG_CONFIG --modversion "osi-gurobi" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-gurobi" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi GRB_CFLAGS="$cflags" GRB_LIBS=`$PKG_CONFIG --libs "osi-gurobi" 2>/dev/null` GRB_DATA=`$PKG_CONFIG --variable=datadir "osi-gurobi" 2>/dev/null` coin_has_grb=yes echo "$as_me:$LINENO: result: yes: $GRB_VERSIONS" >&5 echo "${ECHO_T}yes: $GRB_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then GRB_LIBS=`echo " $GRB_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi GRB_PCREQUIRES="osi-gurobi" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in else GRB_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-gurobi"` coin_has_grb=notGiven echo "$as_me:$LINENO: result: not given: $GRB_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $GRB_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Grb without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Grb without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Grb (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Grb (fallback)... $ECHO_C" >&6 coin_has_grb=notGiven GRB_LIBS= GRB_LIBS_INSTALLED= GRB_CFLAGS= GRB_CFLAGS_INSTALLED= GRB_DATA= GRB_DATA_INSTALLED= GRB_PCLIBS= GRB_PCREQUIRES= # initial list of dependencies is "osi-gurobi", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-gurobi" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$GRB_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` GRB_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$GRB_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi GRB_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi GRB_CFLAGS="$projcflags $GRB_CFLAGS" # set LIBS variable GRB_LIBS="$projlibs $GRB_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi GRB_CFLAGS_INSTALLED="$projcflags $GRB_CFLAGS_INSTALLED" # set LIBS variable GRB_LIBS_INSTALLED="$projlibs $GRB_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_grb=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_GRB 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then GRB_LIBS=`echo " $GRB_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` GRB_LIBS_INSTALLED=`echo " $GRB_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi GRB_PCREQUIRES="osi-gurobi" fi if test $coin_has_grb != notGiven && test $coin_has_grb != skipping; then COIN_HAS_GRB_TRUE= COIN_HAS_GRB_FALSE='#' else COIN_HAS_GRB_TRUE='#' COIN_HAS_GRB_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_grb" >&5 echo "${ECHO_T}$coin_has_grb" >&6 fi if test $coin_has_grb != skipping && test $coin_has_grb != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_GRB 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) GRB_DEPENDENCIES=`echo " $GRB_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$GRB_CFLAGS" ; then { echo "$as_me:$LINENO: Grb CFLAGS are $GRB_CFLAGS" >&5 echo "$as_me: Grb CFLAGS are $GRB_CFLAGS" >&6;} fi if test -n "$GRB_LIBS" ; then { echo "$as_me:$LINENO: Grb LIBS are $GRB_LIBS" >&5 echo "$as_me: Grb LIBS are $GRB_LIBS" >&6;} fi if test -n "$GRB_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Grb DEPENDENCIES are $GRB_DEPENDENCIES" >&5 echo "$as_me: Grb DEPENDENCIES are $GRB_DEPENDENCIES" >&6;} fi if test -n "$GRB_DATA" ; then { echo "$as_me:$LINENO: Grb DATA is $GRB_DATA" >&5 echo "$as_me: Grb DATA is $GRB_DATA" >&6;} fi if test -n "$GRB_PCLIBS" ; then { echo "$as_me:$LINENO: Grb PCLIBS are $GRB_PCLIBS" >&5 echo "$as_me: Grb PCLIBS are $GRB_PCLIBS" >&6;} fi if test -n "$GRB_PCREQUIRES" ; then { echo "$as_me:$LINENO: Grb PCREQUIRES are $GRB_PCREQUIRES" >&5 echo "$as_me: Grb PCREQUIRES are $GRB_PCREQUIRES" >&6;} fi fi fi # Define the Makefile conditional if test $coin_has_grb != notGiven && test $coin_has_grb != skipping; then COIN_HAS_GRB_TRUE= COIN_HAS_GRB_FALSE='#' else COIN_HAS_GRB_TRUE='#' COIN_HAS_GRB_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Msk" >&5 echo $ECHO_N "checking for COIN-OR package Msk... $ECHO_C" >&6 coin_has_msk=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Msk"; then coin_has_msk=skipping fi done fi if test "$coin_has_msk" != skipping; then # Check whether --with-m4_tolower(Msk) or --without-m4_tolower(Msk) was given. if test "${with_msk+set}" = set; then withval="$with_msk" if test "$withval" = no ; then coin_has_msk=skipping fi fi; fi MSK_LIBS= MSK_CFLAGS= MSK_DATA= MSK_DEPENDENCIES= MSK_PCLIBS= MSK_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_msk != skipping; then # Check whether --with-m4_tolower(Msk)-lib or --without-m4_tolower(Msk)-lib was given. if test "${with_msk_lib+set}" = set; then withval="$with_msk_lib" if test "$withval" = no ; then coin_has_msk=skipping else coin_has_msk=yes MSK_LIBS="$withval" MSK_PCLIBS="$withval" CBCGENERIC_PCLIBS="$withval $CBCGENERIC_PCLIBS" CBCGENERIC_LIBS="$withval $CBCGENERIC_LIBS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then MSK_LIBS_INSTALLED="$withval" CBCGENERIC_LIBS_INSTALLED="$withval $CBCGENERIC_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_msk != skipping; then # Check whether --with-m4_tolower(Msk)-incdir or --without-m4_tolower(Msk)-incdir was given. if test "${with_msk_incdir+set}" = set; then withval="$with_msk_incdir" if test "$withval" = no ; then coin_has_msk=skipping else coin_has_msk=yes MSK_CFLAGS="-I`${CYGPATH_W} $withval`" CBCGENERIC_CFLAGS="-I`${CYGPATH_W} $withval` $CBCGENERIC_CFLAGS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then MSK_CFLAGS_INSTALLED="$MSK_CFLAGS" CBCGENERIC_CFLAGS_INSTALLED="$MSK_CFLAGS $CBCGENERIC_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_msk != skipping; then # Check whether --with-m4_tolower(Msk)-datadir or --without-m4_tolower(Msk)-datadir was given. if test "${with_msk_datadir+set}" = set; then withval="$with_msk_datadir" if test "$withval" = no ; then coin_has_msk=skipping else coin_has_msk=yes MSK_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then MSK_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_msk = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-mosek"; then MSK_VERSIONS=`$PKG_CONFIG --modversion "osi-mosek" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-mosek" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi MSK_CFLAGS="$cflags" MSK_LIBS=`$PKG_CONFIG --libs "osi-mosek" 2>/dev/null` MSK_DATA=`$PKG_CONFIG --variable=datadir "osi-mosek" 2>/dev/null` coin_has_msk=yes echo "$as_me:$LINENO: result: yes: $MSK_VERSIONS" >&5 echo "${ECHO_T}yes: $MSK_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then MSK_LIBS=`echo " $MSK_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi MSK_PCREQUIRES="osi-mosek" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in CbcGeneric CBCGENERIC_PCREQUIRES="osi-mosek $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$MSK_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$MSK_LIBS $CBCGENERIC_LIBS" else MSK_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-mosek"` coin_has_msk=notGiven echo "$as_me:$LINENO: result: not given: $MSK_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $MSK_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Msk without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Msk without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Msk (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Msk (fallback)... $ECHO_C" >&6 coin_has_msk=notGiven MSK_LIBS= MSK_LIBS_INSTALLED= MSK_CFLAGS= MSK_CFLAGS_INSTALLED= MSK_DATA= MSK_DATA_INSTALLED= MSK_PCLIBS= MSK_PCREQUIRES= # initial list of dependencies is "osi-mosek", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-mosek" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$MSK_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` MSK_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$MSK_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi MSK_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi MSK_CFLAGS="$projcflags $MSK_CFLAGS" # set LIBS variable MSK_LIBS="$projlibs $MSK_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi MSK_CFLAGS_INSTALLED="$projcflags $MSK_CFLAGS_INSTALLED" # set LIBS variable MSK_LIBS_INSTALLED="$projlibs $MSK_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_msk=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_MSK 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then MSK_LIBS=`echo " $MSK_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` MSK_LIBS_INSTALLED=`echo " $MSK_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi MSK_PCREQUIRES="osi-mosek" CBCGENERIC_PCREQUIRES="osi-mosek $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$MSK_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$MSK_LIBS $CBCGENERIC_LIBS" CBCGENERIC_CFLAGS_INSTALLED="$MSK_CFLAGS_INSTALLED $CBCGENERIC_CFLAGS_INSTALLED" CBCGENERIC_LIBS_INSTALLED="$MSK_LIBS_INSTALLED $CBCGENERIC_LIBS_INSTALLED" fi if test $coin_has_msk != notGiven && test $coin_has_msk != skipping; then COIN_HAS_MSK_TRUE= COIN_HAS_MSK_FALSE='#' else COIN_HAS_MSK_TRUE='#' COIN_HAS_MSK_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_msk" >&5 echo "${ECHO_T}$coin_has_msk" >&6 fi if test $coin_has_msk != skipping && test $coin_has_msk != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_MSK 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) MSK_DEPENDENCIES=`echo " $MSK_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCGENERIC_DEPENDENCIES=`echo " $CBCGENERIC_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$MSK_CFLAGS" ; then { echo "$as_me:$LINENO: Msk CFLAGS are $MSK_CFLAGS" >&5 echo "$as_me: Msk CFLAGS are $MSK_CFLAGS" >&6;} fi if test -n "$MSK_LIBS" ; then { echo "$as_me:$LINENO: Msk LIBS are $MSK_LIBS" >&5 echo "$as_me: Msk LIBS are $MSK_LIBS" >&6;} fi if test -n "$MSK_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Msk DEPENDENCIES are $MSK_DEPENDENCIES" >&5 echo "$as_me: Msk DEPENDENCIES are $MSK_DEPENDENCIES" >&6;} fi if test -n "$MSK_DATA" ; then { echo "$as_me:$LINENO: Msk DATA is $MSK_DATA" >&5 echo "$as_me: Msk DATA is $MSK_DATA" >&6;} fi if test -n "$MSK_PCLIBS" ; then { echo "$as_me:$LINENO: Msk PCLIBS are $MSK_PCLIBS" >&5 echo "$as_me: Msk PCLIBS are $MSK_PCLIBS" >&6;} fi if test -n "$MSK_PCREQUIRES" ; then { echo "$as_me:$LINENO: Msk PCREQUIRES are $MSK_PCREQUIRES" >&5 echo "$as_me: Msk PCREQUIRES are $MSK_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&5 echo "$as_me: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&5 echo "$as_me: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&6;} { echo "$as_me:$LINENO: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&5 echo "$as_me: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_msk != notGiven && test $coin_has_msk != skipping; then COIN_HAS_MSK_TRUE= COIN_HAS_MSK_FALSE='#' else COIN_HAS_MSK_TRUE='#' COIN_HAS_MSK_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Spx" >&5 echo $ECHO_N "checking for COIN-OR package Spx... $ECHO_C" >&6 coin_has_spx=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Spx"; then coin_has_spx=skipping fi done fi if test "$coin_has_spx" != skipping; then # Check whether --with-m4_tolower(Spx) or --without-m4_tolower(Spx) was given. if test "${with_spx+set}" = set; then withval="$with_spx" if test "$withval" = no ; then coin_has_spx=skipping fi fi; fi SPX_LIBS= SPX_CFLAGS= SPX_DATA= SPX_DEPENDENCIES= SPX_PCLIBS= SPX_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_spx != skipping; then # Check whether --with-m4_tolower(Spx)-lib or --without-m4_tolower(Spx)-lib was given. if test "${with_spx_lib+set}" = set; then withval="$with_spx_lib" if test "$withval" = no ; then coin_has_spx=skipping else coin_has_spx=yes SPX_LIBS="$withval" SPX_PCLIBS="$withval" CBCGENERIC_PCLIBS="$withval $CBCGENERIC_PCLIBS" CBCGENERIC_LIBS="$withval $CBCGENERIC_LIBS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then SPX_LIBS_INSTALLED="$withval" CBCGENERIC_LIBS_INSTALLED="$withval $CBCGENERIC_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_spx != skipping; then # Check whether --with-m4_tolower(Spx)-incdir or --without-m4_tolower(Spx)-incdir was given. if test "${with_spx_incdir+set}" = set; then withval="$with_spx_incdir" if test "$withval" = no ; then coin_has_spx=skipping else coin_has_spx=yes SPX_CFLAGS="-I`${CYGPATH_W} $withval`" CBCGENERIC_CFLAGS="-I`${CYGPATH_W} $withval` $CBCGENERIC_CFLAGS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then SPX_CFLAGS_INSTALLED="$SPX_CFLAGS" CBCGENERIC_CFLAGS_INSTALLED="$SPX_CFLAGS $CBCGENERIC_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_spx != skipping; then # Check whether --with-m4_tolower(Spx)-datadir or --without-m4_tolower(Spx)-datadir was given. if test "${with_spx_datadir+set}" = set; then withval="$with_spx_datadir" if test "$withval" = no ; then coin_has_spx=skipping else coin_has_spx=yes SPX_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then SPX_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_spx = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-soplex"; then SPX_VERSIONS=`$PKG_CONFIG --modversion "osi-soplex" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-soplex" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi SPX_CFLAGS="$cflags" SPX_LIBS=`$PKG_CONFIG --libs "osi-soplex" 2>/dev/null` SPX_DATA=`$PKG_CONFIG --variable=datadir "osi-soplex" 2>/dev/null` coin_has_spx=yes echo "$as_me:$LINENO: result: yes: $SPX_VERSIONS" >&5 echo "${ECHO_T}yes: $SPX_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then SPX_LIBS=`echo " $SPX_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi SPX_PCREQUIRES="osi-soplex" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in CbcGeneric CBCGENERIC_PCREQUIRES="osi-soplex $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$SPX_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$SPX_LIBS $CBCGENERIC_LIBS" else SPX_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-soplex"` coin_has_spx=notGiven echo "$as_me:$LINENO: result: not given: $SPX_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $SPX_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Spx without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Spx without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Spx (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Spx (fallback)... $ECHO_C" >&6 coin_has_spx=notGiven SPX_LIBS= SPX_LIBS_INSTALLED= SPX_CFLAGS= SPX_CFLAGS_INSTALLED= SPX_DATA= SPX_DATA_INSTALLED= SPX_PCLIBS= SPX_PCREQUIRES= # initial list of dependencies is "osi-soplex", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-soplex" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$SPX_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` SPX_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$SPX_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi SPX_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi SPX_CFLAGS="$projcflags $SPX_CFLAGS" # set LIBS variable SPX_LIBS="$projlibs $SPX_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi SPX_CFLAGS_INSTALLED="$projcflags $SPX_CFLAGS_INSTALLED" # set LIBS variable SPX_LIBS_INSTALLED="$projlibs $SPX_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_spx=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_SPX 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then SPX_LIBS=`echo " $SPX_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` SPX_LIBS_INSTALLED=`echo " $SPX_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi SPX_PCREQUIRES="osi-soplex" CBCGENERIC_PCREQUIRES="osi-soplex $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$SPX_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$SPX_LIBS $CBCGENERIC_LIBS" CBCGENERIC_CFLAGS_INSTALLED="$SPX_CFLAGS_INSTALLED $CBCGENERIC_CFLAGS_INSTALLED" CBCGENERIC_LIBS_INSTALLED="$SPX_LIBS_INSTALLED $CBCGENERIC_LIBS_INSTALLED" fi if test $coin_has_spx != notGiven && test $coin_has_spx != skipping; then COIN_HAS_SPX_TRUE= COIN_HAS_SPX_FALSE='#' else COIN_HAS_SPX_TRUE='#' COIN_HAS_SPX_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_spx" >&5 echo "${ECHO_T}$coin_has_spx" >&6 fi if test $coin_has_spx != skipping && test $coin_has_spx != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_SPX 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) SPX_DEPENDENCIES=`echo " $SPX_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCGENERIC_DEPENDENCIES=`echo " $CBCGENERIC_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$SPX_CFLAGS" ; then { echo "$as_me:$LINENO: Spx CFLAGS are $SPX_CFLAGS" >&5 echo "$as_me: Spx CFLAGS are $SPX_CFLAGS" >&6;} fi if test -n "$SPX_LIBS" ; then { echo "$as_me:$LINENO: Spx LIBS are $SPX_LIBS" >&5 echo "$as_me: Spx LIBS are $SPX_LIBS" >&6;} fi if test -n "$SPX_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Spx DEPENDENCIES are $SPX_DEPENDENCIES" >&5 echo "$as_me: Spx DEPENDENCIES are $SPX_DEPENDENCIES" >&6;} fi if test -n "$SPX_DATA" ; then { echo "$as_me:$LINENO: Spx DATA is $SPX_DATA" >&5 echo "$as_me: Spx DATA is $SPX_DATA" >&6;} fi if test -n "$SPX_PCLIBS" ; then { echo "$as_me:$LINENO: Spx PCLIBS are $SPX_PCLIBS" >&5 echo "$as_me: Spx PCLIBS are $SPX_PCLIBS" >&6;} fi if test -n "$SPX_PCREQUIRES" ; then { echo "$as_me:$LINENO: Spx PCREQUIRES are $SPX_PCREQUIRES" >&5 echo "$as_me: Spx PCREQUIRES are $SPX_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&5 echo "$as_me: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&5 echo "$as_me: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&6;} { echo "$as_me:$LINENO: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&5 echo "$as_me: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_spx != notGiven && test $coin_has_spx != skipping; then COIN_HAS_SPX_TRUE= COIN_HAS_SPX_FALSE='#' else COIN_HAS_SPX_TRUE='#' COIN_HAS_SPX_FALSE= fi echo "$as_me:$LINENO: checking for COIN-OR package Xpr" >&5 echo $ECHO_N "checking for COIN-OR package Xpr... $ECHO_C" >&6 coin_has_xpr=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "Xpr"; then coin_has_xpr=skipping fi done fi if test "$coin_has_xpr" != skipping; then # Check whether --with-m4_tolower(Xpr) or --without-m4_tolower(Xpr) was given. if test "${with_xpr+set}" = set; then withval="$with_xpr" if test "$withval" = no ; then coin_has_xpr=skipping fi fi; fi XPR_LIBS= XPR_CFLAGS= XPR_DATA= XPR_DEPENDENCIES= XPR_PCLIBS= XPR_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_xpr != skipping; then # Check whether --with-m4_tolower(Xpr)-lib or --without-m4_tolower(Xpr)-lib was given. if test "${with_xpr_lib+set}" = set; then withval="$with_xpr_lib" if test "$withval" = no ; then coin_has_xpr=skipping else coin_has_xpr=yes XPR_LIBS="$withval" XPR_PCLIBS="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then XPR_LIBS_INSTALLED="$withval" fi fi fi; fi if test $coin_has_xpr != skipping; then # Check whether --with-m4_tolower(Xpr)-incdir or --without-m4_tolower(Xpr)-incdir was given. if test "${with_xpr_incdir+set}" = set; then withval="$with_xpr_incdir" if test "$withval" = no ; then coin_has_xpr=skipping else coin_has_xpr=yes XPR_CFLAGS="-I`${CYGPATH_W} $withval`" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then XPR_CFLAGS_INSTALLED="$XPR_CFLAGS" fi fi fi; fi if test $coin_has_xpr != skipping; then # Check whether --with-m4_tolower(Xpr)-datadir or --without-m4_tolower(Xpr)-datadir was given. if test "${with_xpr_datadir+set}" = set; then withval="$with_xpr_datadir" if test "$withval" = no ; then coin_has_xpr=skipping else coin_has_xpr=yes XPR_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then XPR_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_xpr = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "osi-xpress"; then XPR_VERSIONS=`$PKG_CONFIG --modversion "osi-xpress" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi-xpress" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi XPR_CFLAGS="$cflags" XPR_LIBS=`$PKG_CONFIG --libs "osi-xpress" 2>/dev/null` XPR_DATA=`$PKG_CONFIG --variable=datadir "osi-xpress" 2>/dev/null` coin_has_xpr=yes echo "$as_me:$LINENO: result: yes: $XPR_VERSIONS" >&5 echo "${ECHO_T}yes: $XPR_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then XPR_LIBS=`echo " $XPR_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi XPR_PCREQUIRES="osi-xpress" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in else XPR_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi-xpress"` coin_has_xpr=notGiven echo "$as_me:$LINENO: result: not given: $XPR_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $XPR_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Xpr without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Xpr without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package Xpr (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Xpr (fallback)... $ECHO_C" >&6 coin_has_xpr=notGiven XPR_LIBS= XPR_LIBS_INSTALLED= XPR_CFLAGS= XPR_CFLAGS_INSTALLED= XPR_DATA= XPR_DATA_INSTALLED= XPR_PCLIBS= XPR_PCREQUIRES= # initial list of dependencies is "osi-xpress", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi-xpress" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$XPR_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` XPR_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$XPR_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi XPR_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi XPR_CFLAGS="$projcflags $XPR_CFLAGS" # set LIBS variable XPR_LIBS="$projlibs $XPR_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi XPR_CFLAGS_INSTALLED="$projcflags $XPR_CFLAGS_INSTALLED" # set LIBS variable XPR_LIBS_INSTALLED="$projlibs $XPR_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_xpr=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_XPR 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then XPR_LIBS=`echo " $XPR_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` XPR_LIBS_INSTALLED=`echo " $XPR_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi XPR_PCREQUIRES="osi-xpress" fi if test $coin_has_xpr != notGiven && test $coin_has_xpr != skipping; then COIN_HAS_XPR_TRUE= COIN_HAS_XPR_FALSE='#' else COIN_HAS_XPR_TRUE='#' COIN_HAS_XPR_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_xpr" >&5 echo "${ECHO_T}$coin_has_xpr" >&6 fi if test $coin_has_xpr != skipping && test $coin_has_xpr != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_XPR 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) XPR_DEPENDENCIES=`echo " $XPR_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$XPR_CFLAGS" ; then { echo "$as_me:$LINENO: Xpr CFLAGS are $XPR_CFLAGS" >&5 echo "$as_me: Xpr CFLAGS are $XPR_CFLAGS" >&6;} fi if test -n "$XPR_LIBS" ; then { echo "$as_me:$LINENO: Xpr LIBS are $XPR_LIBS" >&5 echo "$as_me: Xpr LIBS are $XPR_LIBS" >&6;} fi if test -n "$XPR_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Xpr DEPENDENCIES are $XPR_DEPENDENCIES" >&5 echo "$as_me: Xpr DEPENDENCIES are $XPR_DEPENDENCIES" >&6;} fi if test -n "$XPR_DATA" ; then { echo "$as_me:$LINENO: Xpr DATA is $XPR_DATA" >&5 echo "$as_me: Xpr DATA is $XPR_DATA" >&6;} fi if test -n "$XPR_PCLIBS" ; then { echo "$as_me:$LINENO: Xpr PCLIBS are $XPR_PCLIBS" >&5 echo "$as_me: Xpr PCLIBS are $XPR_PCLIBS" >&6;} fi if test -n "$XPR_PCREQUIRES" ; then { echo "$as_me:$LINENO: Xpr PCREQUIRES are $XPR_PCREQUIRES" >&5 echo "$as_me: Xpr PCREQUIRES are $XPR_PCREQUIRES" >&6;} fi fi fi # Define the Makefile conditional if test $coin_has_xpr != notGiven && test $coin_has_xpr != skipping; then COIN_HAS_XPR_TRUE= COIN_HAS_XPR_FALSE='#' else COIN_HAS_XPR_TRUE='#' COIN_HAS_XPR_FALSE= fi ############################################################################# # Other third party software # ############################################################################# # Ampl Solver library echo "$as_me:$LINENO: checking for COIN-OR package ASL" >&5 echo $ECHO_N "checking for COIN-OR package ASL... $ECHO_C" >&6 coin_has_asl=notGiven # check if user wants to skip package in any case if test x"$COIN_SKIP_PROJECTS" != x; then for dir in $COIN_SKIP_PROJECTS; do if test $dir = "ASL"; then coin_has_asl=skipping fi done fi if test "$coin_has_asl" != skipping; then # Check whether --with-m4_tolower(ASL) or --without-m4_tolower(ASL) was given. if test "${with_asl+set}" = set; then withval="$with_asl" if test "$withval" = no ; then coin_has_asl=skipping fi fi; fi ASL_LIBS= ASL_CFLAGS= ASL_DATA= ASL_DEPENDENCIES= ASL_PCLIBS= ASL_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_asl != skipping; then # Check whether --with-m4_tolower(ASL)-lib or --without-m4_tolower(ASL)-lib was given. if test "${with_asl_lib+set}" = set; then withval="$with_asl_lib" if test "$withval" = no ; then coin_has_asl=skipping else coin_has_asl=yes ASL_LIBS="$withval" ASL_PCLIBS="$withval" CBCLIB_PCLIBS="$withval $CBCLIB_PCLIBS" CBCLIB_LIBS="$withval $CBCLIB_LIBS" CBCGENERIC_PCLIBS="$withval $CBCGENERIC_PCLIBS" CBCGENERIC_LIBS="$withval $CBCGENERIC_LIBS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then ASL_LIBS_INSTALLED="$withval" CBCLIB_LIBS_INSTALLED="$withval $CBCLIB_LIBS_INSTALLED"CBCGENERIC_LIBS_INSTALLED="$withval $CBCGENERIC_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_asl != skipping; then # Check whether --with-m4_tolower(ASL)-incdir or --without-m4_tolower(ASL)-incdir was given. if test "${with_asl_incdir+set}" = set; then withval="$with_asl_incdir" if test "$withval" = no ; then coin_has_asl=skipping else coin_has_asl=yes ASL_CFLAGS="-I`${CYGPATH_W} $withval`" CBCLIB_CFLAGS="-I`${CYGPATH_W} $withval` $CBCLIB_CFLAGS"CBCGENERIC_CFLAGS="-I`${CYGPATH_W} $withval` $CBCGENERIC_CFLAGS" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then ASL_CFLAGS_INSTALLED="$ASL_CFLAGS" CBCLIB_CFLAGS_INSTALLED="$ASL_CFLAGS $CBCLIB_CFLAGS_INSTALLED"CBCGENERIC_CFLAGS_INSTALLED="$ASL_CFLAGS $CBCGENERIC_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_asl != skipping; then # Check whether --with-m4_tolower(ASL)-datadir or --without-m4_tolower(ASL)-datadir was given. if test "${with_asl_datadir+set}" = set; then withval="$with_asl_datadir" if test "$withval" = no ; then coin_has_asl=skipping else coin_has_asl=yes ASL_DATA="$withval" # if project flags are given by user and we build without pkg-config, then we need to setup the _INSTALLED variables if test -z "$PKG_CONFIG" ; then ASL_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_asl = notGiven; then if test -n "$PKG_CONFIG" ; then # set search path for pkg-config # need to export variable to be sure that the following pkg-config gets these values coin_save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH" PKG_CONFIG_PATH="$COIN_PKG_CONFIG_PATH:$COIN_PKG_CONFIG_PATH_UNINSTALLED" export PKG_CONFIG_PATH # let pkg-config do it's magic if test -n "$PKG_CONFIG" ; then if $PKG_CONFIG --exists "coinasl"; then ASL_VERSIONS=`$PKG_CONFIG --modversion "coinasl" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "coinasl" 2>/dev/null` # pkg-config cannot handle spaces, so CYGPATH_W cannot be put into .pc files # thus, we modify the cflags extracted from pkg-config by putting CYGPATH_W behind -I's # but only do this if is not trivial if test "$CYGPATH_W" != "echo" ; then # need to put into brackets since otherwise autoconf replaces the brackets in the sed command cflags=`echo $cflags | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi ASL_CFLAGS="$cflags" ASL_LIBS=`$PKG_CONFIG --libs "coinasl" 2>/dev/null` ASL_DATA=`$PKG_CONFIG --variable=datadir "coinasl" 2>/dev/null` coin_has_asl=yes echo "$as_me:$LINENO: result: yes: $ASL_VERSIONS" >&5 echo "${ECHO_T}yes: $ASL_VERSIONS" >&6 # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl) if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then ASL_LIBS=`echo " $ASL_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi ASL_PCREQUIRES="coinasl" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in CbcLib CbcGeneric CBCLIB_PCREQUIRES="coinasl $CBCLIB_PCREQUIRES" CBCLIB_CFLAGS="$ASL_CFLAGS $CBCLIB_CFLAGS" CBCLIB_LIBS="$ASL_LIBS $CBCLIB_LIBS" CBCGENERIC_PCREQUIRES="coinasl $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$ASL_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$ASL_LIBS $CBCGENERIC_LIBS" else ASL_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "coinasl"` coin_has_asl=notGiven echo "$as_me:$LINENO: result: not given: $ASL_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $ASL_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module ASL without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module ASL without pkg-config\"" >&2;} { (exit 1); exit 1; }; } fi # reset PKG_CONFIG_PATH variable PKG_CONFIG_PATH="$coin_save_PKG_CONFIG_PATH" export PKG_CONFIG_PATH else echo "$as_me:$LINENO: result: skipped check via pkg-config, redirect to fallback" >&5 echo "${ECHO_T}skipped check via pkg-config, redirect to fallback" >&6 echo "$as_me:$LINENO: checking for COIN-OR package ASL (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package ASL (fallback)... $ECHO_C" >&6 coin_has_asl=notGiven ASL_LIBS= ASL_LIBS_INSTALLED= ASL_CFLAGS= ASL_CFLAGS_INSTALLED= ASL_DATA= ASL_DATA_INSTALLED= ASL_PCLIBS= ASL_PCREQUIRES= # initial list of dependencies is "coinasl", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="coinasl" # we first expand the list of projects to process by adding all dependencies just behind the project which depends on it # further, we collect the list of corresponding .pc files, but do this in reverse order, because we need this order afterwards # the latter we also do with .pc files corresponding to the installed projects, which will be needed to setup Makefiles for examples # also, we setup the DATA variable allproj="" allpcfiles="" allpcifiles="" while test "x$projtoprocess" != x ; do for proj in $projtoprocess ; do # if $proj is available and configured, then a project-uninstalled.pc file should have been created, so search for it pcfile="" save_IFS="$IFS" IFS=":" for dir in $COIN_PKG_CONFIG_PATH_UNINSTALLED ; do # the base directory configure should have setup coin_subdirs.txt in a way that it does not contain projects that should be skipped, so we do not need to test this here again if test -r "$dir/${proj}-uninstalled.pc" ; then pcfile="$dir/$proj-uninstalled.pc" if test -r "$dir/${proj}.pc" ; then pcifile="$dir/${proj}.pc" else { echo "$as_me:$LINENO: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&5 echo "$as_me: WARNING: Found $pcfile, but $dir/${proj}.pc is not available. This may break Makefile's of examples." >&2;} pcifile= fi break fi done IFS="$save_IFS" if test "x$pcfile" != x ; then # read dependencies from $pcfile and filter it projrequires=`sed -n -e 's/Requires://gp' "$pcfile" | sed -e 's/<\{0,1\}>\{0,1\}=[ ]\{0,\}[^ ]\{1,\}//g'` # add projrequires to the front of the list of projects that have to be processed next # at the same time, remove $proj from this list projtoprocess=`echo $projtoprocess | sed -e "s/$proj/$projrequires/"` # read DATA from $pcfile, if _DATA is still empty if test "x$ASL_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` ASL_DATA="$projdatadir" fi allproj="$allproj $proj" allpcfiles="$pcfile:$allpcfiles" else echo "$as_me:$LINENO: result: no, dependency $proj not available" >&5 echo "${ECHO_T}no, dependency $proj not available" >&6 allproj=fail break 2 fi if test "x$pcifile" != x ; then allpcifiles="$pcifile:$allpcifiles" # read DATA_INSTALLED from $pcifile, if _DATA_INSTALLED is still empty if test "x$ASL_DATA_INSTALLED" = x ; then projdatadir= pcifilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcifile` eval `sh -c "$pcifilemod"` if test "${CYGPATH_W}" != "echo"; then projdatadir="\`\$(CYGPATH_W) ${projdatadir} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g'\`" fi ASL_DATA_INSTALLED="$projdatadir" fi fi break done # remove spaces on begin of $projtoprocess projtoprocess=`echo $projtoprocess | sed -e 's/^ *//'` done if test "$allproj" != fail ; then # now go through the list of .pc files and assemble compiler and linker flags # important is here to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcfiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi ASL_CFLAGS="$projcflags $ASL_CFLAGS" # set LIBS variable ASL_LIBS="$projlibs $ASL_LIBS" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # now go through the list of .pc files for installed projects and assemble compiler and linker flags # important is here again to obey the reverse order that has been setup before, # since then libraries that are required by several others should be after these other libraries pcfilesprocessed="" save_IFS="$IFS" IFS=":" for pcfile in $allpcifiles ; do # if $pcfile has been processed already, skip this round if test "x$pcfilesprocessed" != x ; then for pcfiledone in $pcfilesprocessed ; do if test "$pcfiledone" = "$pcfile" ; then continue 2 fi done fi # modify .pc file to a shell script that prints shell commands for setting the compiler and library flags: # replace "Libs:" by "echo projlibs=" # replace "Cflags:" by "echo projcflags=" # remove every line starting with : pcfilemod=`sed -e 's/Libs:\(.*\)$/echo projlibs=\\\\"\1\\\\"/g' -e 's/Cflags:\(.*\)/echo projcflags=\\\\"\1\\\\"/g' -e '/^[a-zA-Z]*:/d' $pcfile` # set projcflags and projlibs variables by running $pcfilemod # under mingw, the current IFS seem to make the : in the paths of the gfortran libs go away, so we temporarily set IFS back to its default projcflags= projlibs= IFS="$save_IFS" eval `sh -c "$pcfilemod"` IFS=":" # add CYGPATH_W cludge into include flags and set CFLAGS variable if test "${CYGPATH_W}" != "echo"; then projcflags=`echo "$projcflags" | sed -e 's/-I\([^ ]*\)/-I\`${CYGPATH_W} \1\`/g'` fi ASL_CFLAGS_INSTALLED="$projcflags $ASL_CFLAGS_INSTALLED" # set LIBS variable ASL_LIBS_INSTALLED="$projlibs $ASL_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_asl=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_ASL 1 _ACEOF # adjust linker flags for (i)cl compiler # for the LIBS, we replace everything of the form "/somepath/name.lib" by "`$(CYGPATH_W) /somepath/`name.lib | sed -e s|\|/|g" (where we have to use excessive many \ to get the \ into the command line for cl), # for the LIBS_INSTALLED, we replace everything of the form "/somepath/" by "`$(CYGPATH_W) /somepath/`", # everything of the form "-lname" by "libname.lib", and # everything of the form "-Lpath" by "-libpath:`$(CYGPATH_W) path` if test x$coin_cxx_is_cl = xtrue || test x$coin_cc_is_cl = xtrue ; then ASL_LIBS=`echo " $ASL_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` ASL_LIBS_INSTALLED=`echo " $ASL_LIBS_INSTALLED" | sed -e 's/ \(\/[^ ]*\/\)/ \`$(CYGPATH_W) \1\`/g' -e 's/ -l\([^ ]*\)/ lib\1.lib/g' -e 's/ -L\([^ ]*\)/ -libpath:\`$(CYGPATH_W) \1\`/g'` fi ASL_PCREQUIRES="coinasl" CBCLIB_PCREQUIRES="coinasl $CBCLIB_PCREQUIRES" CBCLIB_CFLAGS="$ASL_CFLAGS $CBCLIB_CFLAGS" CBCLIB_LIBS="$ASL_LIBS $CBCLIB_LIBS" CBCLIB_CFLAGS_INSTALLED="$ASL_CFLAGS_INSTALLED $CBCLIB_CFLAGS_INSTALLED" CBCLIB_LIBS_INSTALLED="$ASL_LIBS_INSTALLED $CBCLIB_LIBS_INSTALLED" CBCGENERIC_PCREQUIRES="coinasl $CBCGENERIC_PCREQUIRES" CBCGENERIC_CFLAGS="$ASL_CFLAGS $CBCGENERIC_CFLAGS" CBCGENERIC_LIBS="$ASL_LIBS $CBCGENERIC_LIBS" CBCGENERIC_CFLAGS_INSTALLED="$ASL_CFLAGS_INSTALLED $CBCGENERIC_CFLAGS_INSTALLED" CBCGENERIC_LIBS_INSTALLED="$ASL_LIBS_INSTALLED $CBCGENERIC_LIBS_INSTALLED" fi if test $coin_has_asl != notGiven && test $coin_has_asl != skipping; then COIN_HAS_ASL_TRUE= COIN_HAS_ASL_FALSE='#' else COIN_HAS_ASL_TRUE='#' COIN_HAS_ASL_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_asl" >&5 echo "${ECHO_T}$coin_has_asl" >&6 fi if test $coin_has_asl != skipping && test $coin_has_asl != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_ASL 1 _ACEOF # Check whether --enable-interpackage-dependencies or --disable-interpackage-dependencies was given. if test "${enable_interpackage_dependencies+set}" = set; then enableval="$enable_interpackage_dependencies" else enable_interpackage_dependencies=yes fi; if test $enable_interpackage_dependencies = yes ; then # construct dependencies variables from LIBS variables # we add an extra space in LIBS so we can substitute out everything starting with " -" # remove everything of the form -framework xxx as used on Mac and mkl* and libiomp5* and wsock32.lib as used on Windows # then remove everything of the form -xxx # also remove everything of the form `xxx`yyy (may have been added for cygwin/cl) ASL_DEPENDENCIES=`echo " $ASL_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCLIB_DEPENDENCIES=`echo " $CBCLIB_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CBCGENERIC_DEPENDENCIES=`echo " $CBCGENERIC_LIBS " | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` fi if test 1 = 0 ; then #change this test to enable a bit of debugging output if test -n "$ASL_CFLAGS" ; then { echo "$as_me:$LINENO: ASL CFLAGS are $ASL_CFLAGS" >&5 echo "$as_me: ASL CFLAGS are $ASL_CFLAGS" >&6;} fi if test -n "$ASL_LIBS" ; then { echo "$as_me:$LINENO: ASL LIBS are $ASL_LIBS" >&5 echo "$as_me: ASL LIBS are $ASL_LIBS" >&6;} fi if test -n "$ASL_DEPENDENCIES" ; then { echo "$as_me:$LINENO: ASL DEPENDENCIES are $ASL_DEPENDENCIES" >&5 echo "$as_me: ASL DEPENDENCIES are $ASL_DEPENDENCIES" >&6;} fi if test -n "$ASL_DATA" ; then { echo "$as_me:$LINENO: ASL DATA is $ASL_DATA" >&5 echo "$as_me: ASL DATA is $ASL_DATA" >&6;} fi if test -n "$ASL_PCLIBS" ; then { echo "$as_me:$LINENO: ASL PCLIBS are $ASL_PCLIBS" >&5 echo "$as_me: ASL PCLIBS are $ASL_PCLIBS" >&6;} fi if test -n "$ASL_PCREQUIRES" ; then { echo "$as_me:$LINENO: ASL PCREQUIRES are $ASL_PCREQUIRES" >&5 echo "$as_me: ASL PCREQUIRES are $ASL_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: CbcLib CFLAGS are $CBCLIB_CFLAGS" >&5 echo "$as_me: CbcLib CFLAGS are $CBCLIB_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcLib LIBS are $CBCLIB_LIBS" >&5 echo "$as_me: CbcLib LIBS are $CBCLIB_LIBS" >&6;} { echo "$as_me:$LINENO: CbcLib DEPENDENCIES are $CBCLIB_DEPENDENCIES" >&5 echo "$as_me: CbcLib DEPENDENCIES are $CBCLIB_DEPENDENCIES" >&6;} { echo "$as_me:$LINENO: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&5 echo "$as_me: CbcGeneric CFLAGS are $CBCGENERIC_CFLAGS" >&6;} { echo "$as_me:$LINENO: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&5 echo "$as_me: CbcGeneric LIBS are $CBCGENERIC_LIBS" >&6;} { echo "$as_me:$LINENO: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&5 echo "$as_me: CbcGeneric DEPENDENCIES are $CBCGENERIC_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_asl != notGiven && test $coin_has_asl != skipping; then COIN_HAS_ASL_TRUE= COIN_HAS_ASL_FALSE='#' else COIN_HAS_ASL_TRUE='#' COIN_HAS_ASL_FALSE= fi ############################################################################# # CbcGeneric configuration # ############################################################################# # Are we building cbc-generic? Default is no (false). # Check whether --with-cbc-generic or --without-cbc-generic was given. if test "${with_cbc_generic+set}" = set; then withval="$with_cbc_generic" case $withval in yes) cbc_with_cbc_generic=true ;; *) cbc_with_cbc_generic=false ;; esac else cbc_with_cbc_generic=false fi; if test x"$cbc_with_cbc_generic" = xyes ; then { echo "$as_me:$LINENO: building cbc-generic" >&5 echo "$as_me: building cbc-generic" >&6;} fi if test x"$cbc_with_cbc_generic" = xtrue; then CBC_BUILD_CBC_GENERIC_TRUE= CBC_BUILD_CBC_GENERIC_FALSE='#' else CBC_BUILD_CBC_GENERIC_TRUE='#' CBC_BUILD_CBC_GENERIC_FALSE= fi # Set the default solver for cbc-generic. In theory, any OsiXXX should work. # In practice, only the three listed below have had any testing. echo "$as_me:$LINENO: checking for cbc-generic default solver" >&5 echo $ECHO_N "checking for cbc-generic default solver... $ECHO_C" >&6 # Check whether --with-cbc-generic-solver or --without-cbc-generic-solver was given. if test "${with_cbc_generic_solver+set}" = set; then withval="$with_cbc_generic_solver" cbc_default_solver=$withval else cbc_default_solver=clp fi; echo "$as_me:$LINENO: result: $cbc_default_solver" >&5 echo "${ECHO_T}$cbc_default_solver" >&6 # FIXME what about cplex and mosek here? case $cbc_default_solver in clp) ;; dylp) ;; glpk) ;; soplex) ;; *) { echo "$as_me:$LINENO: WARNING: Unrecognised solver $cbc_default_solver chosen as cbc-generic default solver." >&5 echo "$as_me: WARNING: Unrecognised solver $cbc_default_solver chosen as cbc-generic default solver." >&2;} ;; esac cat >>confdefs.h <<_ACEOF #define CBC_DEFAULT_SOLVER "$cbc_default_solver" _ACEOF ############################################################################# # Cbc parallel configuration # ############################################################################# # First we define a new option, --enable-cbc-parallel # Check whether --enable-cbc-parallel or --disable-cbc-parallel was given. if test "${enable_cbc_parallel+set}" = set; then enableval="$enable_cbc_parallel" fi; if test "$enable_cbc_parallel" = yes; then # Define the preprocessor macro cat >>confdefs.h <<\_ACEOF #define CBC_THREAD 1 _ACEOF if test $coin_cxx_is_cl = true ; then # TODO we should check whether the library works and pthread.h is indeed there # Check whether --with-pthreadsw32-lib or --without-pthreadsw32-lib was given. if test "${with_pthreadsw32_lib+set}" = set; then withval="$with_pthreadsw32_lib" CBCLIB_LIBS="$withval $CBCLIB_LIBS" CBCLIB_PCLIBS="$withval $CBCLIB_PCLIBS" else { echo "$as_me:$LINENO: WARNING: --enable-cbc-parallel selected, but --with-pthreadsw32-lib not given" >&5 echo "$as_me: WARNING: --enable-cbc-parallel selected, but --with-pthreadsw32-lib not given" >&2;} CBCLIB_LIBS="pthreadVCE2.lib $CBCLIB_LIBS" fi; # Check whether --with-pthreadsw32-incdir or --without-pthreadsw32-incdir was given. if test "${with_pthreadsw32_incdir+set}" = set; then withval="$with_pthreadsw32_incdir" CXXFLAGS="$CXXFLAGS -I$withval" else { echo "$as_me:$LINENO: WARNING: --enable-cbc-parallel selected, but --with-pthreadsw32-incdir not given" >&5 echo "$as_me: WARNING: --enable-cbc-parallel selected, but --with-pthreadsw32-incdir not given" >&2;} fi; else echo "$as_me:$LINENO: checking for clock_gettime in -lrt" >&5 echo $ECHO_N "checking for clock_gettime in -lrt... $ECHO_C" >&6 if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char clock_gettime (); int main () { clock_gettime (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_rt_clock_gettime=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_rt_clock_gettime=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_rt_clock_gettime" >&5 echo "${ECHO_T}$ac_cv_lib_rt_clock_gettime" >&6 if test $ac_cv_lib_rt_clock_gettime = yes; then CBCLIB_LIBS="-lrt $CBCLIB_LIBS" CBCLIB_PCLIBS="-lrt $CBCLIB_PCLIBS" cat >>confdefs.h <<\_ACEOF #define HAVE_CLOCK_GETTIME 1 _ACEOF else { echo "$as_me:$LINENO: WARNING: --enable-cbc-parallel selected, but -lrt unavailable; using gettimeofday instead of clock_gettime" >&5 echo "$as_me: WARNING: --enable-cbc-parallel selected, but -lrt unavailable; using gettimeofday instead of clock_gettime" >&2;} fi echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6 if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char pthread_create (); int main () { pthread_create (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_pthread_pthread_create=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_pthread_create=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6 if test $ac_cv_lib_pthread_pthread_create = yes; then CBCLIB_LIBS="-lpthread $CBCLIB_LIBS" CBCLIB_PCLIBS="-lpthread $CBCLIB_PCLIBS" else { { echo "$as_me:$LINENO: error: --enable-cbc-parallel selected, but -lpthreads unavailable" >&5 echo "$as_me: error: --enable-cbc-parallel selected, but -lpthreads unavailable" >&2;} { (exit 1); exit 1; }; } fi fi { echo "$as_me:$LINENO: Cbc multithreading enabled" >&5 echo "$as_me: Cbc multithreading enabled" >&6;}; fi ############################################################################## # OsiCbc configuration # ############################################################################## # Handles configuration of the underlying default solver in OsiCbc. The issue # is that OsiCbc defines a default solver, used when the client does not # specify a solver in the constructor. The default solver must, therefore, # be present in the build. This macro checks that this is true, and sets the # compile-time symbols OSICBC_DFLT_SOLVER, OSICBC_CLP_DFLT_SOLVER, and # OSICBC_DFLT_SOLVER_HPP that control the build. The parameter default_solver # should normally be clp, unless you're working on some other solver. # Ideally, this macro would not require enumeration of solvers, but the # effort required to avoid it is just not justified at present. One enumeration # is hidden in AC_OSI_CANONICAL. The other is visible, the AM_CONDITIONAL # list at the end. # In an ideal world this macro would do absolutely nothing if Cbc is not # present, but autotools is not an ideal world and we have to satisfy its # requirements. In particular, the AM_CONDITIONAL macros need to execute or # automake will complain. Really the only thing we need to suppress is the # check that the default solver exists. All the rest is irrelevant when Cbc # isn't present (hence OsiCbc will be configured but not actually compiled). # Process the with-osicbc-default-solver option. # Check whether --with-osicbc-default-solver or --without-osicbc-default-solver was given. if test "${with_osicbc_default_solver+set}" = set; then withval="$with_osicbc_default_solver" osicbc_with_solver=$withval else osicbc_with_solver=clp fi; case "${osicbc_with_solver}" in [Cc][Ll][Pp]*) osi_lc_solver=clp ; osi_mc_solver=Clp ; osi_uc_solver=CLP ; osi_exists_solver=${coin_has_clp-"unavailable"} ;; [Dd][Yy][Ll][Pp]*) osi_lc_solver=dylp ; osi_mc_solver=Dylp osi_uc_solver=DYLP osi_exists_solver=${coin_has_dylp-"unavailable"} ;; [Cc][Pp][Xx]*) osi_lc_solver=cpx ; osi_mc_solver=Cpx osi_uc_solver=CPX osi_exists_solver=${coin_has_cpx-"unavailable"} ;; [Gg][Ll][Pp][Kk]*) osi_lc_solver=glpk ; osi_mc_solver=Glpk osi_uc_solver=GLPK osi_exists_solver=${coin_has_glpk-"unavailable"} ;; [Gg][Rr][Bb]*) osi_lc_solver=grb ; osi_mc_solver=Grb ; osi_uc_solver=GRB ; osi_exists_solver=${coin_has_grb-"unavailable"} ;; [Mm][Ss][Kk]*) osi_lc_solver=msk ; osi_mc_solver=Msk osi_uc_solver=MSK osi_exists_solver=${coin_has_msk-"unavailable"} ;; [Ss][Pp][Xx]*) osi_lc_solver=spx ; osi_mc_solver=Spx osi_uc_solver=SPX osi_exists_solver=${coin_has_spx-"unavailable"} ;; [Ss][Yy][Mm]*) osi_lc_solver=sym ; osi_mc_solver=Sym osi_uc_solver=SYM osi_exists_solver=${coin_has_sym-"unavailable"} ;; [Vv][Oo][Ll]*) osi_lc_solver=vol ; osi_mc_solver=Vol osi_uc_solver=VOL osi_exists_solver=${coin_has_vol-"unavailable"} ;; [Xx][Pp][Rr]*) osi_lc_solver=xpr ; osi_mc_solver=Xpr osi_uc_solver=XPR osi_exists_solver=${coin_has_xpr-"unavailable"} ;; *) osi_lc_solver=clp ; osi_mc_solver=Clp ; osi_uc_solver=CLP ; osi_exists_solver=${coin_has_clp-"unavailable"} { echo "$as_me:$LINENO: WARNING: Unrecognised solver $1; defaulting to $osi_lc_solver." >&5 echo "$as_me: WARNING: Unrecognised solver $1; defaulting to $osi_lc_solver." >&2;} ;; esac # Check that the requested solver is available. if test $osi_exists_solver = no; then { { echo "$as_me:$LINENO: error: selected default solver $osicbc_with_solver is unavailable. Please select an available solver using the --with-osicbc-default-solver option." >&5 echo "$as_me: error: selected default solver $osicbc_with_solver is unavailable. Please select an available solver using the --with-osicbc-default-solver option." >&2;} { (exit 1); exit 1; }; } fi # State the result. { echo "$as_me:$LINENO: OsiCbc default solver is $osi_lc_solver" >&5 echo "$as_me: OsiCbc default solver is $osi_lc_solver" >&6;} # And set the configuration variables. cat >>confdefs.h <<_ACEOF #define OSICBC_DFLT_SOLVER Osi${osi_mc_solver}SolverInterface _ACEOF cat >>confdefs.h <<_ACEOF #define OSICBC_DFLT_SOLVER_HPP "Osi${osi_mc_solver}SolverInterface.hpp" _ACEOF if test $osi_mc_solver = "Clp"; then cat >>confdefs.h <<\_ACEOF #define OSICBC_DFLT_SOLVER_CLP 1 _ACEOF fi # Last but not least, we need automake conditionals. if test $osi_mc_solver = Clp; then OSICBC_DFLT_SOLVER_CLP_TRUE= OSICBC_DFLT_SOLVER_CLP_FALSE='#' else OSICBC_DFLT_SOLVER_CLP_TRUE='#' OSICBC_DFLT_SOLVER_CLP_FALSE= fi if test $osi_mc_solver = Cpx; then OSICBC_DFLT_SOLVER_CPX_TRUE= OSICBC_DFLT_SOLVER_CPX_FALSE='#' else OSICBC_DFLT_SOLVER_CPX_TRUE='#' OSICBC_DFLT_SOLVER_CPX_FALSE= fi if test $osi_mc_solver = Dylp; then OSICBC_DFLT_SOLVER_DYLP_TRUE= OSICBC_DFLT_SOLVER_DYLP_FALSE='#' else OSICBC_DFLT_SOLVER_DYLP_TRUE='#' OSICBC_DFLT_SOLVER_DYLP_FALSE= fi if test $osi_mc_solver = Glpk; then OSICBC_DFLT_SOLVER_GLPK_TRUE= OSICBC_DFLT_SOLVER_GLPK_FALSE='#' else OSICBC_DFLT_SOLVER_GLPK_TRUE='#' OSICBC_DFLT_SOLVER_GLPK_FALSE= fi if test $osi_mc_solver = Grb; then OSICBC_DFLT_SOLVER_GRB_TRUE= OSICBC_DFLT_SOLVER_GRB_FALSE='#' else OSICBC_DFLT_SOLVER_GRB_TRUE='#' OSICBC_DFLT_SOLVER_GRB_FALSE= fi if test $osi_mc_solver = Msk; then OSICBC_DFLT_SOLVER_MSK_TRUE= OSICBC_DFLT_SOLVER_MSK_FALSE='#' else OSICBC_DFLT_SOLVER_MSK_TRUE='#' OSICBC_DFLT_SOLVER_MSK_FALSE= fi if test $osi_mc_solver = Spx; then OSICBC_DFLT_SOLVER_SPX_TRUE= OSICBC_DFLT_SOLVER_SPX_FALSE='#' else OSICBC_DFLT_SOLVER_SPX_TRUE='#' OSICBC_DFLT_SOLVER_SPX_FALSE= fi if test $osi_mc_solver = Sym; then OSICBC_DFLT_SOLVER_SYM_TRUE= OSICBC_DFLT_SOLVER_SYM_FALSE='#' else OSICBC_DFLT_SOLVER_SYM_TRUE='#' OSICBC_DFLT_SOLVER_SYM_FALSE= fi if test $osi_mc_solver = Vol; then OSICBC_DFLT_SOLVER_VOL_TRUE= OSICBC_DFLT_SOLVER_VOL_FALSE='#' else OSICBC_DFLT_SOLVER_VOL_TRUE='#' OSICBC_DFLT_SOLVER_VOL_FALSE= fi if test $osi_mc_solver = Xpr; then OSICBC_DFLT_SOLVER_XPR_TRUE= OSICBC_DFLT_SOLVER_XPR_FALSE='#' else OSICBC_DFLT_SOLVER_XPR_TRUE='#' OSICBC_DFLT_SOLVER_XPR_FALSE= fi ############################################################################## # VPATH links for example input files # ############################################################################## # In case this is a VPATH configuration we need to make sure that the # input files for the examples are available in the VPATH directory. echo "$as_me:$LINENO: checking whether this is a VPATH configuration" >&5 echo $ECHO_N "checking whether this is a VPATH configuration... $ECHO_C" >&6 if test `cd $srcdir; pwd` != `pwd`; then coin_vpath_config=yes; else coin_vpath_config=no; fi echo "$as_me:$LINENO: result: $coin_vpath_config" >&5 echo "${ECHO_T}$coin_vpath_config" >&6 # Allow for newlines in the parameter if test $coin_vpath_config = yes; then cvl_tmp="examples/sudoku_sample.csv" for file in $cvl_tmp ; do coin_vpath_link_files="$coin_vpath_link_files $file" done fi # Allow for newlines in the parameter if test $coin_vpath_config = yes; then cvl_tmp="examples/quad.mps" for file in $cvl_tmp ; do coin_vpath_link_files="$coin_vpath_link_files $file" done fi # Allow for newlines in the parameter if test $coin_vpath_config = yes; then cvl_tmp="examples/quad2.mps" for file in $cvl_tmp ; do coin_vpath_link_files="$coin_vpath_link_files $file" done fi ############################################################################# # Check for doxygen # ############################################################################# { echo "$as_me:$LINENO: configuring doxygen documentation options" >&5 echo "$as_me: configuring doxygen documentation options" >&6;} # Check to see if doxygen is available. # Extract the first word of "doxygen", so it can be a program name with args. set dummy doxygen; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_coin_have_doxygen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$coin_have_doxygen"; then ac_cv_prog_coin_have_doxygen="$coin_have_doxygen" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_coin_have_doxygen="yes" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_coin_have_doxygen" && ac_cv_prog_coin_have_doxygen="no" fi fi coin_have_doxygen=$ac_cv_prog_coin_have_doxygen if test -n "$coin_have_doxygen"; then echo "$as_me:$LINENO: result: $coin_have_doxygen" >&5 echo "${ECHO_T}$coin_have_doxygen" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Look for the dot tool from the graphviz package, unless the user has # disabled it. # Check whether --with-dot or --without-dot was given. if test "${with_dot+set}" = set; then withval="$with_dot" else withval=yes fi; if test x"$withval" = xno ; then coin_doxy_usedot=NO echo "$as_me:$LINENO: checking for dot " >&5 echo $ECHO_N "checking for dot ... $ECHO_C" >&6 echo "$as_me:$LINENO: result: disabled" >&5 echo "${ECHO_T}disabled" >&6 else # Extract the first word of "dot", so it can be a program name with args. set dummy dot; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_coin_doxy_usedot+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$coin_doxy_usedot"; then ac_cv_prog_coin_doxy_usedot="$coin_doxy_usedot" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_coin_doxy_usedot="YES" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_coin_doxy_usedot" && ac_cv_prog_coin_doxy_usedot="NO" fi fi coin_doxy_usedot=$ac_cv_prog_coin_doxy_usedot if test -n "$coin_doxy_usedot"; then echo "$as_me:$LINENO: result: $coin_doxy_usedot" >&5 echo "${ECHO_T}$coin_doxy_usedot" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi # Generate a tag file name and a log file name coin_doxy_tagname=doxydoc/${PACKAGE}_doxy.tag coin_doxy_logname=doxydoc/${PACKAGE}_doxy.log # Process the list of project names and massage them into possible doxygen # doc'n directories. Prefer 1) classic external, source processed using # a project-specific doxygen.conf, we use the tag file; 2) classic # external, source processed using package doxygen.conf; 3) installed # doxydoc. Alternatives 1) and 2) are only possible if the directory will be # configured, which we can't know unless this is the package base configure, # since coin_subdirs is only set there. Hence it's sufficient to check for # membership. If we use a tag file from a classic external, exclude the # source from doxygen processing when doxygen runs in the base directory. coin_doxy_tagfiles= coin_doxy_excludes= tmp="CoinUtils Osi Clp DyLP Cgl Vol" for proj in $tmp ; do lc_proj=`echo $proj | tr [A-Z] [a-z]` echo "$as_me:$LINENO: checking for doxygen doc'n for $proj " >&5 echo $ECHO_N "checking for doxygen doc'n for $proj ... $ECHO_C" >&6 doxytag=${lc_proj}_doxy.tag doxyfound=no for chkProj in $coin_subdirs ; do if test "$chkProj" = "$proj" ; then # proj will be configured, hence doxydoc present in build tree doxysrcdir="${srcdir}/${proj}" # AC_MSG_NOTICE([Considering $doxysrcdir (base)]) if test -d "$doxysrcdir" ; then # with a doxydoc directory? doxydir="$doxysrcdir/doxydoc" # AC_MSG_NOTICE([Considering $doxydir (base)]) # AC_MSG_NOTICE([Subdirs: $coin_subdirs)]) if test -d "$doxydir" ; then # use tag file; don't process source eval doxydir="`pwd`/${proj}/doxydoc" coin_doxy_tagfiles="$coin_doxy_tagfiles $doxydir/$doxytag=$doxydir/html" echo "$as_me:$LINENO: result: $doxydir (tag)" >&5 echo "${ECHO_T}$doxydir (tag)" >&6 coin_doxy_excludes="$coin_doxy_excludes */${proj}" else # will process the source -- nothing further to be done here echo "$as_me:$LINENO: result: $doxysrcdir (src)" >&5 echo "${ECHO_T}$doxysrcdir (src)" >&6 fi doxyfound=yes fi fi done # Not built, fall back to installed tag file if test $doxyfound = no ; then eval doxydir="${datadir}/coin/doc/${proj}/doxydoc" # AC_MSG_NOTICE([Considering $doxydir (install)]) # AC_MSG_NOTICE([Subdirs: $coin_subdirs)]) coin_doxy_tagfiles="$coin_doxy_tagfiles $doxydir/$doxytag=$doxydir/html" echo "$as_me:$LINENO: result: $doxydir (tag)" >&5 echo "${ECHO_T}$doxydir (tag)" >&6 fi done ############################################################################## # Finishing up by writing all the output # ############################################################################## # Here list all the files that configure should create (except for the # configuration header file) ac_config_files="$ac_config_files Makefile examples/Makefile src/Makefile src/OsiCbc/Makefile test/Makefile cbc.pc cbc-uninstalled.pc osi-cbc.pc osi-cbc-uninstalled.pc" ac_config_files="$ac_config_files doxydoc/doxygen.conf" # Here put the location and name of the configuration header file ac_config_headers="$ac_config_headers src/config.h src/config_cbc.h" # Finally, we let configure write all the output... echo "$as_me:$LINENO: checking which command should be used to link input files" >&5 echo $ECHO_N "checking which command should be used to link input files... $ECHO_C" >&6 coin_link_input_cmd="$LN_S" case "$CC" in clang* ) ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) coin_link_input_cmd=cp ;; esac echo "$as_me:$LINENO: result: $coin_link_input_cmd" >&5 echo "${ECHO_T}$coin_link_input_cmd" >&6 if test x$coin_skip_ac_output != xyes; then # library extension case "$CC" in clang* ) LIBEXT=a ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) LIBEXT=lib ;; *) LIBEXT=a ;; esac # Define VPATH_DISTCLEANFILES to be everything that needs to be # cleaned for distclean in a vpath configuration VPATH_DISTCLEANFILES="$coin_vpath_link_files" # Take out subdirectories if their configuration concluded that they # don't need to be compiled if test x"$coin_ac_skip_subdirs" != x; then new_subdirs= for i in $subdirs; do skipme=no for j in $coin_ac_skip_subdirs; do if test $i = $j; then skipme=yes; fi done if test $skipme = no; then new_subdirs="$new_subdirs $i" fi done subdirs="$new_subdirs" fi # need to come before AC_OUTPUT if test x$coin_projectdir != xyes; then # write coin_subdirs to a file so that project configuration knows where to find uninstalled projects echo $coin_subdirs > coin_subdirs.txt else # substitute for OBJDIR, needed to setup .pc file for uninstalled project ABSBUILDDIR="`pwd`" fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${ALWAYS_FALSE_TRUE}" && test -z "${ALWAYS_FALSE_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"ALWAYS_FALSE\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"ALWAYS_FALSE\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_CC_IS_CL_TRUE}" && test -z "${COIN_CC_IS_CL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_CC_IS_CL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_CC_IS_CL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_CXX_IS_CL_TRUE}" && test -z "${COIN_CXX_IS_CL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_CXX_IS_CL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_CXX_IS_CL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${HAVE_EXTERNALS_TRUE}" && test -z "${HAVE_EXTERNALS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"HAVE_EXTERNALS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"HAVE_EXTERNALS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${DEPENDENCY_LINKING_TRUE}" && test -z "${DEPENDENCY_LINKING_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"DEPENDENCY_LINKING\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"DEPENDENCY_LINKING\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_PKGCONFIG_TRUE}" && test -z "${COIN_HAS_PKGCONFIG_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_PKGCONFIG\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_PKGCONFIG\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_COINDEPEND_TRUE}" && test -z "${COIN_HAS_COINDEPEND_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_COINDEPEND\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_COINDEPEND\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_COINDEPEND_TRUE}" && test -z "${COIN_HAS_COINDEPEND_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_COINDEPEND\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_COINDEPEND\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_CLP_TRUE}" && test -z "${COIN_HAS_CLP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_CLP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_CLP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_CLP_TRUE}" && test -z "${COIN_HAS_CLP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_CLP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_CLP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_OSITESTS_TRUE}" && test -z "${COIN_HAS_OSITESTS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_OSITESTS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_OSITESTS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_OSITESTS_TRUE}" && test -z "${COIN_HAS_OSITESTS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_OSITESTS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_OSITESTS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_SAMPLE_TRUE}" && test -z "${COIN_HAS_SAMPLE_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_SAMPLE\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_SAMPLE\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_SAMPLE_TRUE}" && test -z "${COIN_HAS_SAMPLE_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_SAMPLE\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_SAMPLE\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_NETLIB_TRUE}" && test -z "${COIN_HAS_NETLIB_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_NETLIB\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_NETLIB\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_NETLIB_TRUE}" && test -z "${COIN_HAS_NETLIB_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_NETLIB\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_NETLIB\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_MIPLIB3_TRUE}" && test -z "${COIN_HAS_MIPLIB3_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_MIPLIB3\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_MIPLIB3\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_MIPLIB3_TRUE}" && test -z "${COIN_HAS_MIPLIB3_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_MIPLIB3\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_MIPLIB3\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_DYLP_TRUE}" && test -z "${COIN_HAS_DYLP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_DYLP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_DYLP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_DYLP_TRUE}" && test -z "${COIN_HAS_DYLP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_DYLP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_DYLP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_VOL_TRUE}" && test -z "${COIN_HAS_VOL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_VOL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_VOL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_VOL_TRUE}" && test -z "${COIN_HAS_VOL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_VOL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_VOL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_CPX_TRUE}" && test -z "${COIN_HAS_CPX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_CPX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_CPX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_CPX_TRUE}" && test -z "${COIN_HAS_CPX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_CPX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_CPX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_GLPK_TRUE}" && test -z "${COIN_HAS_GLPK_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_GLPK\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_GLPK\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_GLPK_TRUE}" && test -z "${COIN_HAS_GLPK_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_GLPK\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_GLPK\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_GRB_TRUE}" && test -z "${COIN_HAS_GRB_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_GRB\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_GRB\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_GRB_TRUE}" && test -z "${COIN_HAS_GRB_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_GRB\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_GRB\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_MSK_TRUE}" && test -z "${COIN_HAS_MSK_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_MSK\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_MSK\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_MSK_TRUE}" && test -z "${COIN_HAS_MSK_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_MSK\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_MSK\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_SPX_TRUE}" && test -z "${COIN_HAS_SPX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_SPX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_SPX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_SPX_TRUE}" && test -z "${COIN_HAS_SPX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_SPX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_SPX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_XPR_TRUE}" && test -z "${COIN_HAS_XPR_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_XPR\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_XPR\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_XPR_TRUE}" && test -z "${COIN_HAS_XPR_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_XPR\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_XPR\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_ASL_TRUE}" && test -z "${COIN_HAS_ASL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_ASL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_ASL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_ASL_TRUE}" && test -z "${COIN_HAS_ASL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_ASL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_ASL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${CBC_BUILD_CBC_GENERIC_TRUE}" && test -z "${CBC_BUILD_CBC_GENERIC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"CBC_BUILD_CBC_GENERIC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"CBC_BUILD_CBC_GENERIC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_CLP_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_CLP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_CLP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_CLP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_CPX_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_CPX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_CPX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_CPX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_DYLP_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_DYLP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_DYLP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_DYLP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_GLPK_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_GLPK_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_GLPK\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_GLPK\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_GRB_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_GRB_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_GRB\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_GRB\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_MSK_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_MSK_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_MSK\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_MSK\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_SPX_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_SPX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_SPX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_SPX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_SYM_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_SYM_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_SYM\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_SYM\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_VOL_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_VOL_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_VOL\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_VOL\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${OSICBC_DFLT_SOLVER_XPR_TRUE}" && test -z "${OSICBC_DFLT_SOLVER_XPR_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"OSICBC_DFLT_SOLVER_XPR\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"OSICBC_DFLT_SOLVER_XPR\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by Cbc $as_me 2.8.12, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ Cbc config.status 2.8.12 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir INSTALL="$INSTALL" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS section. # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "examples/Makefile" ) CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/OsiCbc/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/OsiCbc/Makefile" ;; "test/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; "cbc.pc" ) CONFIG_FILES="$CONFIG_FILES cbc.pc" ;; "cbc-uninstalled.pc" ) CONFIG_FILES="$CONFIG_FILES cbc-uninstalled.pc" ;; "osi-cbc.pc" ) CONFIG_FILES="$CONFIG_FILES osi-cbc.pc" ;; "osi-cbc-uninstalled.pc" ) CONFIG_FILES="$CONFIG_FILES osi-cbc-uninstalled.pc" ;; "doxydoc/doxygen.conf" ) CONFIG_FILES="$CONFIG_FILES doxydoc/doxygen.conf" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "src/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;; "src/config_cbc.h" ) CONFIG_HEADERS="$CONFIG_HEADERS src/config_cbc.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@build@,$build,;t t s,@build_cpu@,$build_cpu,;t t s,@build_vendor@,$build_vendor,;t t s,@build_os@,$build_os,;t t s,@ALWAYS_FALSE_TRUE@,$ALWAYS_FALSE_TRUE,;t t s,@ALWAYS_FALSE_FALSE@,$ALWAYS_FALSE_FALSE,;t t s,@have_svnversion@,$have_svnversion,;t t s,@CBC_SVN_REV@,$CBC_SVN_REV,;t t s,@CDEFS@,$CDEFS,;t t s,@ADD_CFLAGS@,$ADD_CFLAGS,;t t s,@DBG_CFLAGS@,$DBG_CFLAGS,;t t s,@OPT_CFLAGS@,$OPT_CFLAGS,;t t s,@sol_cc_compiler@,$sol_cc_compiler,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@COIN_CC_IS_CL_TRUE@,$COIN_CC_IS_CL_TRUE,;t t s,@COIN_CC_IS_CL_FALSE@,$COIN_CC_IS_CL_FALSE,;t t s,@MPICC@,$MPICC,;t t s,@CXXDEFS@,$CXXDEFS,;t t s,@ADD_CXXFLAGS@,$ADD_CXXFLAGS,;t t s,@DBG_CXXFLAGS@,$DBG_CXXFLAGS,;t t s,@OPT_CXXFLAGS@,$OPT_CXXFLAGS,;t t s,@CXX@,$CXX,;t t s,@CXXFLAGS@,$CXXFLAGS,;t t s,@ac_ct_CXX@,$ac_ct_CXX,;t t s,@COIN_CXX_IS_CL_TRUE@,$COIN_CXX_IS_CL_TRUE,;t t s,@COIN_CXX_IS_CL_FALSE@,$COIN_CXX_IS_CL_FALSE,;t t s,@MPICXX@,$MPICXX,;t t s,@EGREP@,$EGREP,;t t s,@LN_S@,$LN_S,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@CYGPATH_W@,$CYGPATH_W,;t t s,@PACKAGE@,$PACKAGE,;t t s,@VERSION@,$VERSION,;t t s,@ACLOCAL@,$ACLOCAL,;t t s,@AUTOCONF@,$AUTOCONF,;t t s,@AUTOMAKE@,$AUTOMAKE,;t t s,@AUTOHEADER@,$AUTOHEADER,;t t s,@MAKEINFO@,$MAKEINFO,;t t s,@install_sh@,$install_sh,;t t s,@STRIP@,$STRIP,;t t s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t s,@mkdir_p@,$mkdir_p,;t t s,@AWK@,$AWK,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@am__leading_dot@,$am__leading_dot,;t t s,@AMTAR@,$AMTAR,;t t s,@am__tar@,$am__tar,;t t s,@am__untar@,$am__untar,;t t s,@DEPDIR@,$DEPDIR,;t t s,@am__include@,$am__include,;t t s,@am__quote@,$am__quote,;t t s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t s,@CCDEPMODE@,$CCDEPMODE,;t t s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t s,@CXXDEPMODE@,$CXXDEPMODE,;t t s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t s,@MAINT@,$MAINT,;t t s,@LIBTOOLM4@,$LIBTOOLM4,;t t s,@have_autoconf@,$have_autoconf,;t t s,@have_automake@,$have_automake,;t t s,@have_svn@,$have_svn,;t t s,@BUILDTOOLSDIR@,$BUILDTOOLSDIR,;t t s,@AUX_DIR@,$AUX_DIR,;t t s,@abs_source_dir@,$abs_source_dir,;t t s,@abs_lib_dir@,$abs_lib_dir,;t t s,@abs_include_dir@,$abs_include_dir,;t t s,@abs_bin_dir@,$abs_bin_dir,;t t s,@HAVE_EXTERNALS_TRUE@,$HAVE_EXTERNALS_TRUE,;t t s,@HAVE_EXTERNALS_FALSE@,$HAVE_EXTERNALS_FALSE,;t t s,@host@,$host,;t t s,@host_cpu@,$host_cpu,;t t s,@host_vendor@,$host_vendor,;t t s,@host_os@,$host_os,;t t s,@ECHO@,$ECHO,;t t s,@AR@,$AR,;t t s,@ac_ct_AR@,$ac_ct_AR,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@CPP@,$CPP,;t t s,@CXXCPP@,$CXXCPP,;t t s,@F77@,$F77,;t t s,@FFLAGS@,$FFLAGS,;t t s,@ac_ct_F77@,$ac_ct_F77,;t t s,@LIBTOOL@,$LIBTOOL,;t t s,@ac_c_preproc_warn_flag@,$ac_c_preproc_warn_flag,;t t s,@ac_cxx_preproc_warn_flag@,$ac_cxx_preproc_warn_flag,;t t s,@RPATH_FLAGS@,$RPATH_FLAGS,;t t s,@DEPENDENCY_LINKING_TRUE@,$DEPENDENCY_LINKING_TRUE,;t t s,@DEPENDENCY_LINKING_FALSE@,$DEPENDENCY_LINKING_FALSE,;t t s,@LT_LDFLAGS@,$LT_LDFLAGS,;t t s,@PKG_CONFIG@,$PKG_CONFIG,;t t s,@ac_ct_PKG_CONFIG@,$ac_ct_PKG_CONFIG,;t t s,@COIN_HAS_PKGCONFIG_TRUE@,$COIN_HAS_PKGCONFIG_TRUE,;t t s,@COIN_HAS_PKGCONFIG_FALSE@,$COIN_HAS_PKGCONFIG_FALSE,;t t s,@COIN_PKG_CONFIG_PATH@,$COIN_PKG_CONFIG_PATH,;t t s,@COIN_PKG_CONFIG_PATH_UNINSTALLED@,$COIN_PKG_CONFIG_PATH_UNINSTALLED,;t t s,@COINDEPEND_LIBS@,$COINDEPEND_LIBS,;t t s,@COINDEPEND_CFLAGS@,$COINDEPEND_CFLAGS,;t t s,@COINDEPEND_DATA@,$COINDEPEND_DATA,;t t s,@COINDEPEND_DEPENDENCIES@,$COINDEPEND_DEPENDENCIES,;t t s,@COINDEPEND_LIBS_INSTALLED@,$COINDEPEND_LIBS_INSTALLED,;t t s,@COINDEPEND_CFLAGS_INSTALLED@,$COINDEPEND_CFLAGS_INSTALLED,;t t s,@COINDEPEND_DATA_INSTALLED@,$COINDEPEND_DATA_INSTALLED,;t t s,@CBCLIB_CFLAGS@,$CBCLIB_CFLAGS,;t t s,@CBCLIB_LIBS@,$CBCLIB_LIBS,;t t s,@CBCLIB_PCLIBS@,$CBCLIB_PCLIBS,;t t s,@CBCLIB_PCREQUIRES@,$CBCLIB_PCREQUIRES,;t t s,@CBCLIB_DEPENDENCIES@,$CBCLIB_DEPENDENCIES,;t t s,@CBCLIB_CFLAGS_INSTALLED@,$CBCLIB_CFLAGS_INSTALLED,;t t s,@CBCLIB_LIBS_INSTALLED@,$CBCLIB_LIBS_INSTALLED,;t t s,@CBCGENERIC_CFLAGS@,$CBCGENERIC_CFLAGS,;t t s,@CBCGENERIC_LIBS@,$CBCGENERIC_LIBS,;t t s,@CBCGENERIC_PCLIBS@,$CBCGENERIC_PCLIBS,;t t s,@CBCGENERIC_PCREQUIRES@,$CBCGENERIC_PCREQUIRES,;t t s,@CBCGENERIC_DEPENDENCIES@,$CBCGENERIC_DEPENDENCIES,;t t s,@CBCGENERIC_CFLAGS_INSTALLED@,$CBCGENERIC_CFLAGS_INSTALLED,;t t s,@CBCGENERIC_LIBS_INSTALLED@,$CBCGENERIC_LIBS_INSTALLED,;t t s,@COIN_HAS_COINDEPEND_TRUE@,$COIN_HAS_COINDEPEND_TRUE,;t t s,@COIN_HAS_COINDEPEND_FALSE@,$COIN_HAS_COINDEPEND_FALSE,;t t s,@CLP_LIBS@,$CLP_LIBS,;t t s,@CLP_CFLAGS@,$CLP_CFLAGS,;t t s,@CLP_DATA@,$CLP_DATA,;t t s,@CLP_DEPENDENCIES@,$CLP_DEPENDENCIES,;t t s,@CLP_LIBS_INSTALLED@,$CLP_LIBS_INSTALLED,;t t s,@CLP_CFLAGS_INSTALLED@,$CLP_CFLAGS_INSTALLED,;t t s,@CLP_DATA_INSTALLED@,$CLP_DATA_INSTALLED,;t t s,@COIN_HAS_CLP_TRUE@,$COIN_HAS_CLP_TRUE,;t t s,@COIN_HAS_CLP_FALSE@,$COIN_HAS_CLP_FALSE,;t t s,@OSITESTS_LIBS@,$OSITESTS_LIBS,;t t s,@OSITESTS_CFLAGS@,$OSITESTS_CFLAGS,;t t s,@OSITESTS_DATA@,$OSITESTS_DATA,;t t s,@OSITESTS_DEPENDENCIES@,$OSITESTS_DEPENDENCIES,;t t s,@OSITESTS_LIBS_INSTALLED@,$OSITESTS_LIBS_INSTALLED,;t t s,@OSITESTS_CFLAGS_INSTALLED@,$OSITESTS_CFLAGS_INSTALLED,;t t s,@OSITESTS_DATA_INSTALLED@,$OSITESTS_DATA_INSTALLED,;t t s,@COIN_HAS_OSITESTS_TRUE@,$COIN_HAS_OSITESTS_TRUE,;t t s,@COIN_HAS_OSITESTS_FALSE@,$COIN_HAS_OSITESTS_FALSE,;t t s,@SAMPLE_LIBS@,$SAMPLE_LIBS,;t t s,@SAMPLE_CFLAGS@,$SAMPLE_CFLAGS,;t t s,@SAMPLE_DATA@,$SAMPLE_DATA,;t t s,@SAMPLE_DEPENDENCIES@,$SAMPLE_DEPENDENCIES,;t t s,@SAMPLE_LIBS_INSTALLED@,$SAMPLE_LIBS_INSTALLED,;t t s,@SAMPLE_CFLAGS_INSTALLED@,$SAMPLE_CFLAGS_INSTALLED,;t t s,@SAMPLE_DATA_INSTALLED@,$SAMPLE_DATA_INSTALLED,;t t s,@COIN_HAS_SAMPLE_TRUE@,$COIN_HAS_SAMPLE_TRUE,;t t s,@COIN_HAS_SAMPLE_FALSE@,$COIN_HAS_SAMPLE_FALSE,;t t s,@NETLIB_LIBS@,$NETLIB_LIBS,;t t s,@NETLIB_CFLAGS@,$NETLIB_CFLAGS,;t t s,@NETLIB_DATA@,$NETLIB_DATA,;t t s,@NETLIB_DEPENDENCIES@,$NETLIB_DEPENDENCIES,;t t s,@NETLIB_LIBS_INSTALLED@,$NETLIB_LIBS_INSTALLED,;t t s,@NETLIB_CFLAGS_INSTALLED@,$NETLIB_CFLAGS_INSTALLED,;t t s,@NETLIB_DATA_INSTALLED@,$NETLIB_DATA_INSTALLED,;t t s,@COIN_HAS_NETLIB_TRUE@,$COIN_HAS_NETLIB_TRUE,;t t s,@COIN_HAS_NETLIB_FALSE@,$COIN_HAS_NETLIB_FALSE,;t t s,@MIPLIB3_LIBS@,$MIPLIB3_LIBS,;t t s,@MIPLIB3_CFLAGS@,$MIPLIB3_CFLAGS,;t t s,@MIPLIB3_DATA@,$MIPLIB3_DATA,;t t s,@MIPLIB3_DEPENDENCIES@,$MIPLIB3_DEPENDENCIES,;t t s,@MIPLIB3_LIBS_INSTALLED@,$MIPLIB3_LIBS_INSTALLED,;t t s,@MIPLIB3_CFLAGS_INSTALLED@,$MIPLIB3_CFLAGS_INSTALLED,;t t s,@MIPLIB3_DATA_INSTALLED@,$MIPLIB3_DATA_INSTALLED,;t t s,@COIN_HAS_MIPLIB3_TRUE@,$COIN_HAS_MIPLIB3_TRUE,;t t s,@COIN_HAS_MIPLIB3_FALSE@,$COIN_HAS_MIPLIB3_FALSE,;t t s,@DYLP_LIBS@,$DYLP_LIBS,;t t s,@DYLP_CFLAGS@,$DYLP_CFLAGS,;t t s,@DYLP_DATA@,$DYLP_DATA,;t t s,@DYLP_DEPENDENCIES@,$DYLP_DEPENDENCIES,;t t s,@DYLP_LIBS_INSTALLED@,$DYLP_LIBS_INSTALLED,;t t s,@DYLP_CFLAGS_INSTALLED@,$DYLP_CFLAGS_INSTALLED,;t t s,@DYLP_DATA_INSTALLED@,$DYLP_DATA_INSTALLED,;t t s,@COIN_HAS_DYLP_TRUE@,$COIN_HAS_DYLP_TRUE,;t t s,@COIN_HAS_DYLP_FALSE@,$COIN_HAS_DYLP_FALSE,;t t s,@VOL_LIBS@,$VOL_LIBS,;t t s,@VOL_CFLAGS@,$VOL_CFLAGS,;t t s,@VOL_DATA@,$VOL_DATA,;t t s,@VOL_DEPENDENCIES@,$VOL_DEPENDENCIES,;t t s,@VOL_LIBS_INSTALLED@,$VOL_LIBS_INSTALLED,;t t s,@VOL_CFLAGS_INSTALLED@,$VOL_CFLAGS_INSTALLED,;t t s,@VOL_DATA_INSTALLED@,$VOL_DATA_INSTALLED,;t t s,@COIN_HAS_VOL_TRUE@,$COIN_HAS_VOL_TRUE,;t t s,@COIN_HAS_VOL_FALSE@,$COIN_HAS_VOL_FALSE,;t t s,@CPX_LIBS@,$CPX_LIBS,;t t s,@CPX_CFLAGS@,$CPX_CFLAGS,;t t s,@CPX_DATA@,$CPX_DATA,;t t s,@CPX_DEPENDENCIES@,$CPX_DEPENDENCIES,;t t s,@CPX_LIBS_INSTALLED@,$CPX_LIBS_INSTALLED,;t t s,@CPX_CFLAGS_INSTALLED@,$CPX_CFLAGS_INSTALLED,;t t s,@CPX_DATA_INSTALLED@,$CPX_DATA_INSTALLED,;t t s,@COIN_HAS_CPX_TRUE@,$COIN_HAS_CPX_TRUE,;t t s,@COIN_HAS_CPX_FALSE@,$COIN_HAS_CPX_FALSE,;t t s,@GLPK_LIBS@,$GLPK_LIBS,;t t s,@GLPK_CFLAGS@,$GLPK_CFLAGS,;t t s,@GLPK_DATA@,$GLPK_DATA,;t t s,@GLPK_DEPENDENCIES@,$GLPK_DEPENDENCIES,;t t s,@GLPK_LIBS_INSTALLED@,$GLPK_LIBS_INSTALLED,;t t s,@GLPK_CFLAGS_INSTALLED@,$GLPK_CFLAGS_INSTALLED,;t t s,@GLPK_DATA_INSTALLED@,$GLPK_DATA_INSTALLED,;t t s,@COIN_HAS_GLPK_TRUE@,$COIN_HAS_GLPK_TRUE,;t t s,@COIN_HAS_GLPK_FALSE@,$COIN_HAS_GLPK_FALSE,;t t s,@GRB_LIBS@,$GRB_LIBS,;t t s,@GRB_CFLAGS@,$GRB_CFLAGS,;t t s,@GRB_DATA@,$GRB_DATA,;t t s,@GRB_DEPENDENCIES@,$GRB_DEPENDENCIES,;t t s,@GRB_LIBS_INSTALLED@,$GRB_LIBS_INSTALLED,;t t s,@GRB_CFLAGS_INSTALLED@,$GRB_CFLAGS_INSTALLED,;t t s,@GRB_DATA_INSTALLED@,$GRB_DATA_INSTALLED,;t t s,@COIN_HAS_GRB_TRUE@,$COIN_HAS_GRB_TRUE,;t t s,@COIN_HAS_GRB_FALSE@,$COIN_HAS_GRB_FALSE,;t t s,@MSK_LIBS@,$MSK_LIBS,;t t s,@MSK_CFLAGS@,$MSK_CFLAGS,;t t s,@MSK_DATA@,$MSK_DATA,;t t s,@MSK_DEPENDENCIES@,$MSK_DEPENDENCIES,;t t s,@MSK_LIBS_INSTALLED@,$MSK_LIBS_INSTALLED,;t t s,@MSK_CFLAGS_INSTALLED@,$MSK_CFLAGS_INSTALLED,;t t s,@MSK_DATA_INSTALLED@,$MSK_DATA_INSTALLED,;t t s,@COIN_HAS_MSK_TRUE@,$COIN_HAS_MSK_TRUE,;t t s,@COIN_HAS_MSK_FALSE@,$COIN_HAS_MSK_FALSE,;t t s,@SPX_LIBS@,$SPX_LIBS,;t t s,@SPX_CFLAGS@,$SPX_CFLAGS,;t t s,@SPX_DATA@,$SPX_DATA,;t t s,@SPX_DEPENDENCIES@,$SPX_DEPENDENCIES,;t t s,@SPX_LIBS_INSTALLED@,$SPX_LIBS_INSTALLED,;t t s,@SPX_CFLAGS_INSTALLED@,$SPX_CFLAGS_INSTALLED,;t t s,@SPX_DATA_INSTALLED@,$SPX_DATA_INSTALLED,;t t s,@COIN_HAS_SPX_TRUE@,$COIN_HAS_SPX_TRUE,;t t s,@COIN_HAS_SPX_FALSE@,$COIN_HAS_SPX_FALSE,;t t s,@XPR_LIBS@,$XPR_LIBS,;t t s,@XPR_CFLAGS@,$XPR_CFLAGS,;t t s,@XPR_DATA@,$XPR_DATA,;t t s,@XPR_DEPENDENCIES@,$XPR_DEPENDENCIES,;t t s,@XPR_LIBS_INSTALLED@,$XPR_LIBS_INSTALLED,;t t s,@XPR_CFLAGS_INSTALLED@,$XPR_CFLAGS_INSTALLED,;t t s,@XPR_DATA_INSTALLED@,$XPR_DATA_INSTALLED,;t t s,@COIN_HAS_XPR_TRUE@,$COIN_HAS_XPR_TRUE,;t t s,@COIN_HAS_XPR_FALSE@,$COIN_HAS_XPR_FALSE,;t t s,@ASL_LIBS@,$ASL_LIBS,;t t s,@ASL_CFLAGS@,$ASL_CFLAGS,;t t s,@ASL_DATA@,$ASL_DATA,;t t s,@ASL_DEPENDENCIES@,$ASL_DEPENDENCIES,;t t s,@ASL_LIBS_INSTALLED@,$ASL_LIBS_INSTALLED,;t t s,@ASL_CFLAGS_INSTALLED@,$ASL_CFLAGS_INSTALLED,;t t s,@ASL_DATA_INSTALLED@,$ASL_DATA_INSTALLED,;t t s,@COIN_HAS_ASL_TRUE@,$COIN_HAS_ASL_TRUE,;t t s,@COIN_HAS_ASL_FALSE@,$COIN_HAS_ASL_FALSE,;t t s,@CBC_BUILD_CBC_GENERIC_TRUE@,$CBC_BUILD_CBC_GENERIC_TRUE,;t t s,@CBC_BUILD_CBC_GENERIC_FALSE@,$CBC_BUILD_CBC_GENERIC_FALSE,;t t s,@OSICBC_DFLT_SOLVER_CLP_TRUE@,$OSICBC_DFLT_SOLVER_CLP_TRUE,;t t s,@OSICBC_DFLT_SOLVER_CLP_FALSE@,$OSICBC_DFLT_SOLVER_CLP_FALSE,;t t s,@OSICBC_DFLT_SOLVER_CPX_TRUE@,$OSICBC_DFLT_SOLVER_CPX_TRUE,;t t s,@OSICBC_DFLT_SOLVER_CPX_FALSE@,$OSICBC_DFLT_SOLVER_CPX_FALSE,;t t s,@OSICBC_DFLT_SOLVER_DYLP_TRUE@,$OSICBC_DFLT_SOLVER_DYLP_TRUE,;t t s,@OSICBC_DFLT_SOLVER_DYLP_FALSE@,$OSICBC_DFLT_SOLVER_DYLP_FALSE,;t t s,@OSICBC_DFLT_SOLVER_GLPK_TRUE@,$OSICBC_DFLT_SOLVER_GLPK_TRUE,;t t s,@OSICBC_DFLT_SOLVER_GLPK_FALSE@,$OSICBC_DFLT_SOLVER_GLPK_FALSE,;t t s,@OSICBC_DFLT_SOLVER_GRB_TRUE@,$OSICBC_DFLT_SOLVER_GRB_TRUE,;t t s,@OSICBC_DFLT_SOLVER_GRB_FALSE@,$OSICBC_DFLT_SOLVER_GRB_FALSE,;t t s,@OSICBC_DFLT_SOLVER_MSK_TRUE@,$OSICBC_DFLT_SOLVER_MSK_TRUE,;t t s,@OSICBC_DFLT_SOLVER_MSK_FALSE@,$OSICBC_DFLT_SOLVER_MSK_FALSE,;t t s,@OSICBC_DFLT_SOLVER_SPX_TRUE@,$OSICBC_DFLT_SOLVER_SPX_TRUE,;t t s,@OSICBC_DFLT_SOLVER_SPX_FALSE@,$OSICBC_DFLT_SOLVER_SPX_FALSE,;t t s,@OSICBC_DFLT_SOLVER_SYM_TRUE@,$OSICBC_DFLT_SOLVER_SYM_TRUE,;t t s,@OSICBC_DFLT_SOLVER_SYM_FALSE@,$OSICBC_DFLT_SOLVER_SYM_FALSE,;t t s,@OSICBC_DFLT_SOLVER_VOL_TRUE@,$OSICBC_DFLT_SOLVER_VOL_TRUE,;t t s,@OSICBC_DFLT_SOLVER_VOL_FALSE@,$OSICBC_DFLT_SOLVER_VOL_FALSE,;t t s,@OSICBC_DFLT_SOLVER_XPR_TRUE@,$OSICBC_DFLT_SOLVER_XPR_TRUE,;t t s,@OSICBC_DFLT_SOLVER_XPR_FALSE@,$OSICBC_DFLT_SOLVER_XPR_FALSE,;t t s,@coin_have_doxygen@,$coin_have_doxygen,;t t s,@coin_doxy_usedot@,$coin_doxy_usedot,;t t s,@coin_doxy_tagname@,$coin_doxy_tagname,;t t s,@coin_doxy_logname@,$coin_doxy_logname,;t t s,@coin_doxy_tagfiles@,$coin_doxy_tagfiles,;t t s,@coin_doxy_excludes@,$coin_doxy_excludes,;t t s,@LIBEXT@,$LIBEXT,;t t s,@VPATH_DISTCLEANFILES@,$VPATH_DISTCLEANFILES,;t t s,@ABSBUILDDIR@,$ABSBUILDDIR,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t s,@INSTALL@,$ac_INSTALL,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_HEADER section. # # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } # Do quote $f, to prevent DOS paths from being IFS'd. echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF # Transform confdefs.h into two sed scripts, `conftest.defines' and # `conftest.undefs', that substitutes the proper values into # config.h.in to produce config.h. The first handles `#define' # templates, and the second `#undef' templates. # And first: Protect against being on the right side of a sed subst in # config.status. Protect against being in an unquoted here document # in config.status. rm -f conftest.defines conftest.undefs # Using a here document instead of a string reduces the quoting nightmare. # Putting comments in sed scripts is not portable. # # `end' is used to avoid that the second main sed command (meant for # 0-ary CPP macros) applies to n-ary macro definitions. # See the Autoconf documentation for `clear'. cat >confdef2sed.sed <<\_ACEOF s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times # the same #defines, which is useless. Nevertheless, we may not want to # sort them, since we want the *last* AC-DEFINE to be honored. uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.defines >/dev/null do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/defines.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #undef templates' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.undefs >/dev/null do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#undef' echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/undefs.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail rm -f conftest.undefs mv conftest.tail conftest.undefs done rm -f conftest.undefs cat >>$CONFIG_STATUS <<\_ACEOF # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then echo "/* Generated by configure. */" >$tmp/config.h else echo "/* $ac_file. Generated by configure. */" >$tmp/config.h fi cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } rm -f $ac_file mv $tmp/config.h $ac_file fi else cat $tmp/config.h rm -f $tmp/config.h fi # Compute $ac_file's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $ac_file | $ac_file:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || $as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X$ac_file : 'X\(//\)[^/]' \| \ X$ac_file : 'X\(//\)$' \| \ X$ac_file : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X$ac_file | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'`/stamp-h$_am_stamp_count done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_COMMANDS section. # for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue ac_dest=`echo "$ac_file" | sed 's,:.*,,'` ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_dir=`(dirname "$ac_dest") 2>/dev/null || $as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_dest" : 'X\(//\)[^/]' \| \ X"$ac_dest" : 'X\(//\)$' \| \ X"$ac_dest" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_dest" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 echo "$as_me: executing $ac_dest commands" >&6;} case $ac_dest in depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`(dirname "$mf") 2>/dev/null || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`(dirname "$file") 2>/dev/null || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p $dirpart/$fdir else as_dir=$dirpart/$fdir as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; esac done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi if test x"$coin_vpath_link_files" = x; then : ; else lnkcmd="$coin_link_input_cmd" if test "$lnkcmd" = cp; then { echo "$as_me:$LINENO: Copying data files for VPATH configuration" >&5 echo "$as_me: Copying data files for VPATH configuration" >&6;} else { echo "$as_me:$LINENO: Creating VPATH links for data files" >&5 echo "$as_me: Creating VPATH links for data files" >&6;} fi for file in $coin_vpath_link_files; do dir=`(dirname "./$file") 2>/dev/null || $as_expr X"./$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"./$file" : 'X\(//\)[^/]' \| \ X"./$file" : 'X\(//\)$' \| \ X"./$file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"./$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` if test -d $dir; then : ; else { if $as_mkdir_p; then mkdir -p $dir else as_dir=$dir as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory $dir" >&5 echo "$as_me: error: cannot create directory $dir" >&2;} { (exit 1); exit 1; }; }; } fi rm -f $file $lnkcmd $abs_source_dir/$file $file done fi { echo "$as_me:$LINENO: In case of trouble, first consult the troubleshooting page at https://projects.coin-or.org/BuildTools/wiki/user-troubleshooting" >&5 echo "$as_me: In case of trouble, first consult the troubleshooting page at https://projects.coin-or.org/BuildTools/wiki/user-troubleshooting" >&6;} if test x$coin_projectdir = xyes; then { echo "$as_me:$LINENO: Configuration of $PACKAGE_NAME successful" >&5 echo "$as_me: Configuration of $PACKAGE_NAME successful" >&6;} else { echo "$as_me:$LINENO: Main configuration of $PACKAGE_NAME successful" >&5 echo "$as_me: Main configuration of $PACKAGE_NAME successful" >&6;} fi else { echo "$as_me:$LINENO: No configuration of $PACKAGE_NAME necessary" >&5 echo "$as_me: No configuration of $PACKAGE_NAME necessary" >&6;} fi Cbc-2.8.12/config.guess0000755000076600007660000012706311405215312013274 0ustar coincoin#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, # Inc. timestamp='2007-05-17' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:SunOS:5.*:* | ix86xen:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) case ${UNAME_MACHINE} in pc98) echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:[3456]*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; EM64T | authenticamd) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) echo frv-unknown-linux-gnu exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo or32-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit ;; xtensa:Linux:*:*) echo xtensa-unknown-linux-gnu exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^LIBC/{ s: ::g p }'`" test x"${LIBC}" != x && { echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit } test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: